我想知道 MySQL(或其底層引擎)如何處理查詢。下面有兩個set查詢(一個用left join,一個用cross join),最終會得到相同的結果。
我的問題是,為什么兩組查詢的處理時間相似?
我期望的是第一組查詢運行得更快,因為計算機正在處理左連接,所以“表”的大小不會擴大,而第二組查詢使“表”的大小(什么我假設計算機需要從多個表中獲取交叉連接的結果,然后才能繼續執行相對較大的 where 子句。
select s.*, a.score as score_01, b.score as score_02
from student s
left join (select \* from sc where cid = '01') a using (sid)
left join (select \* from sc where cid = '02') b using (sid)
where a.score > b.score;
select s.*, a.score as score_01, b.score as score_02
from student s
,(select * from sc where cid = '01') a
,(select * from sc where cid = '02') b
where a.score > b.score and a.sid = b.sid and s.sid = a.sid;
我嘗試了兩組查詢,并期望第一組查詢的處理時間會更短,但事實并非如此。
uj5u.com熱心網友回復:
將此添加到sc:
INDEX(sid, cid, score)
更好的是,如果你有一個無用id的side替換它
PRIMARY KEY(sid, cid)`
(假設那對是唯一的。)
使用這些修復中的任何一個,我希望您的兩個查詢都以相似的速度運行,并且比目前更快。
如需進一步討論,請提供SHOW CREATE TABLE。
解決一些評論
MySQL 忽略關鍵字INNER, OUTER, 和CROSS。所以,這取決于WHERE它是“內部”還是“外部”。
MySQL 將ON和WHERE條件放在一起(除非它對 很重要LEFT),然后決定用于過濾 ( WHERE) 的內容,因此它可以首先執行此操作。然后其他條件(屬于ON)幫助它到達“下一個”表。
所以...請用ON說出表之間的關系;用于WHERE過濾。(并且不要使用舊的逗號連接。)
也就是說,MySQL 將 [通常] 一次查看一個表,執行“嵌套回圈連接”(NLJ) 以轉到下一個。
有許多可能的方法來評估一個JOIN;MySQL 考慮哪一個可能是最好的,然后使用它。
非 LEFT 的順序JOINs無關緊要,運算式的順序也AND'd無關緊要WHERE。
在某些情況下,HAVING運算式可以(并且已經)移到WHERE子句中。
雖然FROM來之前WHERE,兩人還是有些糾纏在一起。但是,一般來說,子句需要按一定的順序排列,而這個順序在邏輯上就是事情發生的順序。
由優化器來組合步驟。例如
WHERE a = 1
ORDER BY b
并且該表具有INDEX(a,b)- 索引將用于同時執行這兩項操作。同上
SELECT a, MAX(b)
...
GROUP BY a
ORDER BY a
可以跳過 (a,b) 上的 BTree 索引并GROUP BY交付結果,而無需對或進行額外的排序ORDER BY。
SELECT x在之后執行WHERE y = 'abc'——嗯,在某種意義上是這樣。但是如果你有INDEX(y,x),優化器足夠聰明,可以x在執行WHERE.
當 aWHERE參考 a 的多個表時JOIN,優化器會陷入困境。它應該從哪個表開始它的 NLJ?它有一些統計資料可以幫助做出決定,但它并不總是正確的。它通常會
- 在其中一張表上過濾
- NLJ 進入下一張表,同時在該
WHERE子句中放入該表的任何ON子句。 - 重復其他表。
當同時存在 aWHERE和 anORDER BY時,優化器通常會過濾 filter,然后排序。但有時(并非總是正確)它會決定使用索引ORDER BY(從而消除排序)并在讀取表時進行過濾。 LIMIT,這在邏輯上是最后完成的,這進一步混淆了決定。
MySQL 沒有FULL OUTER JOIN. 它可以用兩個JOIN和一個來模擬UNION。(很少需要它。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/535760.html
標籤:数据库表现查询优化
