Mysql

MySQL - 如何優化大表查詢中的多個 OR 條件

  • January 19, 2022

我有一個具有以下結構的表:

Configuration (
 id: binary(16) Primary key,
 htId: binary(16),
 raId: binary(16),
 date,
 amount
);

我已經創建了這些索引:

idx_ht (htId) BTREE, idx_ra (raId) BTREE, idx_date (date) BTREE, idx_ht_ra_date (raId, htId, date) BTREE。

該表有近 1.5 億條記錄。

這是我要優化的具有多個 htId-raId 對的慢查詢。

Select htId, raId, SUM (amount) as totalAmount
From Configuration r
Where ((r.htId = htId_1 AND r.raId = raId_2) 
OR (r.htId = htId_3 AND r.raId = raId_4) ... ~1000 pairs more (r.htId = htId_X AND r.raId = raId_X)) 
AND date Between fromDate 
AND toDate
Group by r.htId, r.raId
Having Count(1) = DATE_DIFF(fromDate, toDate)
Order by totalAmount ASC LIMIT 0,100

有什麼辦法可以優化上面的查詢嗎?當查詢有多個這樣的 OR 時,索引似乎對我的查詢沒有任何影響。查詢需要很多時間。任何幫助將不勝感激。BR。

OR很難優化,尤其是其中的 1000 個。

看看你是否可以通過一個表中的值,然後JOIN到那個表。

然後提供EXPLAIN SELECT ....

(and ) 子句中的許多ORed 謂詞通常難以優化。它們通常會強制進行索引掃描,或者更糟糕的全表掃描。WHERE``JOIN … ON

一個常見的優化是將所有ORs 重構為單獨SELECT的 s,然後將UNION它們重構,如下所示:

SELECT Things 
 FROM Tables
WHERE Condition1
   OR Condition2
    …   …
   OR ConditionN

變成

SELECT Things 
 FROM Tables
WHERE Condition1
UNION 
SELECT Things 
 FROM Tables
WHERE Condition2
    …   …
UNION 
SELECT Things 
 FROM Tables
WHERE ConditionN

如果返回大量行,這可能會非常低效,因為這UNION意味著某種結果集。如果您知道每個過濾子句都將始終相互返回不同的行,則可以通過使用UNION ALL. 對於您的約 1,000 個子句,它實際上可能並不實用。

當然,可能會有一個重新排列少得多的解決方案。例如,我希望索引 ondate會有很大幫助。也許查詢計劃器錯誤地掃描idx_ht_ra_date而不是認為這將比date首先過濾更有效,因為索引包含所有過濾的列。date 可能是第一個( date, raId, htId)的複合索引$$ † $$通過在那裡給它一個更好的選擇會有所幫助。事實上,我可能也傾向於amount包括$$ † $$所以它不需要查找任何其他內容,因為您過濾和選擇的所有內容都將包含在索引中。

為了幫助更多的人,需要查看目前實際發生的情況(編輯問題以包括EXPLAIN輸出和其他人已經提到的其他詳細資訊)以及您希望每次返回多少行。

$$ † $$如果您使用的是 MS SQL Server 的 postgres,我建議您使用INCLUDE支持來添加額外的欄位,但 mySql 不支持

引用自:https://dba.stackexchange.com/questions/268685