2016-06-08 61 views
1

我有這樣的查詢:如何在條件之間存在OR時創建索引?

DELETE FROM events WHERE type = 4 AND author_id IN (?, ?) AND post_id IN (?, ?) 

如你所知,author_id IN (? , ?)轉化爲author_id = ? OR author_id = ?。那麼我應該在author_id列上創建索引嗎?

事實上,我試圖瞭解MySQL如何處理它們之間存在OR的條件。我在某處讀到這句話:

MySQL似乎在遇到OR時忽略索引。

但我不明白它的意思。任何人都可以嗎?總體來說,我需要什麼索引來查詢以上?

+0

用'SELECT type,author_id,post_id'替換'DELETE',然後預先加入'EXPLAIN'並使用MySQL客戶端運行查詢。創建你想要的任何索引,'EXPLAIN'查詢將告訴你使用了哪些索引。詳細瞭解['EXPLAIN'輸出]的含義(http://dev.mysql.com/doc/refman/5.7/en/explain-output.html)。 – axiac

+0

基本的經驗法則:添加一個索引到'決定'上下文中使用的任何字段,這是'where','join','order by,'etc ... –

+0

@MarcB好了,有時候我們需要添加一個倍數列索引。例如:'(type,author_id,post_id)'..但是,在這些條件之間存在「AND」時,情況就是如此。我想知道當他們之間有'OR'時我應該怎麼做... –

回答

2

確實,OR通常會阻止有效使用索引。處理WHERE子句時,查詢通常只能使用每個表的一個索引。所以,如果你有一個像

WHERE col1 = 1 OR col2 = 2 

的條件它不能使用任何一個索引來查找所有匹配的行。你一般最好是關閉將查詢分爲二,並使用UNION

SELECT ... 
FROM TABLE 
WHERE col1 = 1 
UNION 
SELECT ... 
FROM TABLE 
WHERE col2 = 2 

不過,我覺得我讀的地方,在簡單的情況下,MySQL是能夠自動完成這一轉變。檢查您的查詢的EXPLAIN輸出。

但是當OR條件涉及相同的列時,它仍然可以使用該索引,例如,如果你有

WHERE col1 = 1 OR col1 = 2 

它只是查找這兩個索引條目在索引中的col1。這是當你寫它做什麼:

WHERE col1 IN (1, 2) 

然而,查詢比這更復雜,因爲它也與AND組合多個條件。如果您只是使用=比較,則可以使用多列索引(例如,

INDEX (type, author_id, post_id) 

但是,當你有多個IN條件,這不能做,因爲它會需要枚舉所有組合。

type = 4 AND author_id IN (1, 2) AND post_id IN (10, 20) 

需要查找所有這些索引:

4, 1, 10 
4, 1, 20 
4, 2, 10 
4, 2, 20 

我不認爲MySQL會產生這樣所有的組合(但我可能是錯的 - 檢查EXPLAIN輸出,看看它可以)。

取而代之的是,它會選擇它認爲最有效的索引,使用它來查找與該部分條件匹配的行,並掃描這些行以評估其餘條件。

+0

偉大的解釋,upvote ..!最後,任何索引都不會對我的查詢有用嗎? –

+0

我想我的解釋不是很好,如果你需要這樣的話。它將選擇其中一個索引並使用它,並掃描其他條件的行。 – Barmar

+0

啊..你是說只有一個索引會有用嗎?那麼我應該在'type','author_id','post_id'上添加一個單獨的索引,並讓MySQL決定使用哪個索引? –

相關問題