2015-08-21 111 views
1

MySQL首先執行什麼操作:WHERE子句或ORDER BY子句?MySQL首先執行什麼操作:WHERE子句或ORDER BY子句?

我之所以問是確定我是否應該添加一個索引來給定列。

我有一個表,如下所示:

| Column | Type  | Index | 
|-----------|-------------|-------| 
| id  | INT (pk) | Yes | 
| listorder | INT   | ?? | 
| data  | VARCHAR(16) | No | 
| fk  | INT (fk) | Yes | 

我會經常執行查詢,如SELECT id, data FROM mytable WHERE fk=12345 ORDER BY listorder ASC。對於我的數據集,它只會導致少量的記錄(〜5)對於一個給定fk,但是,也有在表中多條記錄與許多fk值,和許多重複listorder值跨越許多fk值。

如果先進行WHERE條款,那麼我期待我不應該添加索引到listorder,因爲它會導致UPDATE性能下降,而不用於SELECT顯著改善。

+1

什麼戈登Linoff sais。另外,在評估索引時,絕對不要提出抽象問題,但總是在** actual **查詢中使用** actual **數據(或合理的數據集合)運行'EXPLAIN',因爲不同的數據集可能觸發不同的索引。 – watery

+0

@watery我目前沒有任何數據,但試圖解釋什麼數據將盡可能最好。 – user1032531

+0

Yuk,據我所知,但這就是爲什麼我說「或一組合理的數據可能是什麼」,因爲真實的數據可能會改變索引的使用/選擇(即當處理同一張表上的多個索引時)。您可能無法確定您創建的索引是否會按照您的預期使用。你可以發現你的DBMS根本沒有使用索引。索引的使用甚至可能隨着數據集的變化而改變,這就是我爲什麼這麼說的原因。 – watery

回答

3

的方式SQL(所有品牌和服務器的型號)使用索引來滿足查詢有一點比你承擔更復雜。通常先通過篩選(WHERE)然後排序來滿足查詢。

對於確切的查詢,你向我們展示了,如果你有(FK,listorder)的SQL引擎將能夠使用索引來滿足您的查詢的兩個子句一個複合索引。索引將首先由WHERE子句隨機訪問,然後它將按照滿足排序條款的順序。

閱讀此:http://use-the-index-luke.com/

更新的化合物指數不小於更新單個列索引昂貴得多。無論哪種方式,使用索引都要比掃描表的WHERE操作要好。

+0

感謝Ollie,我會閱讀你建議的鏈接。我看到了複合索引如何爲我提供兩個「SELECT」查詢的最佳選擇。它會引起'UPDATE'查詢的問題嗎?還是這樣的性能影響已經發生了,因爲我有(並且需要)並且在表PK和'fk'上索引? – user1032531

+0

請參閱我的編輯。你說fk索引是非常有選擇性的,所以你可能看不到添加第二列到那個索引的性能差別。 –

2

首先評估WHERE子句。我認爲這在MySQL中總是如此,但偶爾會有一個例外(至少在其他數據庫中)。

對於此查詢:

SELECT id, data 
FROM mytable 
WHERE fk = 12345 
ORDER BY listorder ASC; 

最實用的指標是mytable(fk, listorder)

+0

我看到你的答案從「大部分」變爲「總是」,直到「幾乎總是」。:)我不關心其他數據庫。不會索引'mytable(fk,listorder)'會導致緩慢的更新(更新會定期爲我的應用程序發生)? – user1032531

+0

@ user1032531。 。 。任何索引都會稍微減緩「更新」。這通常不是問題,除非您的負載是以每秒數百次更新來衡量的。一些數據庫引擎會掃描索引進行排序(有時),然後應用「where」。我不認爲MySQL這樣做。 –

1

在SQL處理中,WHERE條款被認爲是一個隱含的連接語句。實際上它甚至相當於查詢優化器中的INNER JOIN。較早的ANSI語法在90年代初才採用INNER JOIN。許多舊的SQL SELECT語句讀取如下:

SELECT * 
FROM table1, table2 
WHERE table1.ID = table2.ID 

後來的金標準如下:

SELECT * 
FROM table1 
INNER JOIN table2 
ON table1.ID = table2.ID 

但是這兩個語句是等價的。但很多人認爲INNER JOIN更具人性化。在INNER vs WHERE看到這個爽朗的SO帖子。

不像大多數編程語言,SQL語法中的順序並不確定處理的順序。諷刺的是,在最後一行ORDER BY(除非TOP或LIMIT聲明)通常只是後的第一個中的最後一步,並在FROM子句:

FROM table source 
JOIN condition 
WHERE condition 
GROUP BY expression 
HAVING condition 
SELECT fields 
ORDER BY fields 

從本質上講,發動機結構表和/或由FROM,JOIN和WHERE子句確定的虛擬表。一旦建立了該結構,就會處理彙總,字段選擇和排序。所以在你拿到桌子之前你不能點餐!

指數有助於處理的幾乎所有方面。在ORDER BY上設置索引不會導致性能下降。但是,對齊WHERE和ORDER BY可以促進排序優化。看到這個MySQL reference。事實上,如果不需要,MySQL已知會省略索引。