[英]Instructing MySQL to apply WHERE clause to rows returned by previous WHERE clause
我有以下查詢:
SELECT dt_stamp
FROM claim_notes
WHERE type_id = 0
AND dt_stamp >= :dt_stamp
AND DATE( dt_stamp ) = :date
AND user_id = :user_id
AND note LIKE :click_to_call
ORDER BY dt_stamp
LIMIT 1
claim_notes
表大約有一百萬行,因此該查詢運行非常緩慢,因為它必須針對未索引的note
列進行搜索(我對此無能為力)。 我知道當應用type_id
, dt_stamp
和user_id
條件時,我將針對約60行而不是50萬行進行搜索。 但是MySQL似乎並沒有按順序應用它們。 我想做的是看看是否有一種方法告訴MySQL僅將note LIKE :click_to_call
條件應用於滿足前一個條件的行,以便它不搜索具有此條件的所有行。
我想出的是這樣的:
SELECT dt_stamp
FROM (
SELECT *
FROM claim_notes
WHERE type_id = 0
AND dt_stamp >= :dt_stamp
AND DATE( dt_stamp ) = :date
AND user_id = :user_id
)
AND note LIKE :click_to_call
ORDER BY dt_stamp
LIMIT 1
這有效並且非常快。 我只是想知道這是否是正確的方法,或者是否有更正式的方法來處理它。
不要使用派生表解決方案,因為它不具有性能。 我對擁有=
和>=
運算符MySQL首先適合LIKE
感到驚訝。
無論如何,我會說您可以嘗試在這些字段上添加一些索引,然后看看會發生什么:
ALTER TABLE claim_notes ADD INDEX(type_id, user_id);
ALTER TABLE claim_notes ADD INDEX(dt_stamp);
后一個索引實際上並不會改善對索引的搜索,而是會改善結果的排序。
當然,有一個EXPLAIN
查詢將幫助。
不必這樣做。 如果您的WHERE子句中有多個用AND
分隔的術語,則MySQL優化器可以處理它。 基本上,它知道如何做“適用所有你可以使用索引,那么只有到剩下的行申請未索引表達式的條件。”
但是選擇正確的索引很重要。 多列索引最適合一系列AND
項,而不是單個索引。 MySQL可以應用索引交集,但這要比使用單個索引查找相同的行要低得多。
一些邏輯規則適用於創建多列索引:
與非唯一列上的條件相比,唯一列上的條件優先。
相等條件( =
)優先於范圍( >=
, IN
, BETWEEN
, !=
等)。
索引中的第一列用於范圍條件之后,后續列將不使用索引。
大多數情況下,在列上搜索函數的結果(例如DATE(dt_stamp)
)不會使用索引。 在這種情況下,最好存儲DATE
數據類型並使用=
而不是>=
。
如果條件匹配大於表的20%,MySQL可能會決定跳過索引並繼續進行表掃描。
以下是我本人和Percona同事的一些網絡研討會,以幫助解釋索引設計:
您可以免費獲得這些網絡研討會的幻燈片,並免費觀看錄像,但是錄像需要注冊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.