2015-05-08 56 views
-2

假設列pkey是mysql表T的主鍵。基於解釋輸出:爲什麼mysql不優化這個簡單的查詢

  1. 此查詢需要掃描每個只有1行兩種推導PRIMARY選擇(正如人們所期望的那樣):

    SELECT * FROM (SELECT * FROM T where pkey=10) t;

  2. 但此查詢需要爲執行完整的線性掃描 DERIVED和PRIMARY選擇(這表示MySQL不能優化查詢):

    SELECT * FROM (SELECT * FROM T) t where pkey=10;

存在用於查詢#2的至少兩個可能的優化:它可以被轉化爲#1,或子查詢完全去除(即將其更改爲SELECT * FROM T where pkey=10)以及潛在的其他人。

是否有任何更深的原因,MySQL無法優化查詢,也就是說,優化是否有可能改變查詢的可觀察行爲(在這種情況下,MySQL通過不優化來做正確的事情)?

PS:我正在運行MySQL版本5.6.13。

+1

外表不是一般情況下的內表,也不具有內表的索引。我對MySQL開發人員沒有深入的瞭解,但如果它太微不足道了,即使是人類也可以這麼做,也許人類有理由不這樣做,也不應該觸及它。 DBMS優化是關於如何執行儘可能快的查詢,而不是如何將錯誤查詢重寫爲更好的查詢。 – Amadan

+0

MySQL不會將外部查詢的謂詞向下推入視圖查詢中。爲什麼? MySQL優化器中沒有執行該操作的代碼路徑。它不會發生,因爲沒有代碼可以做到這一點。正如Gordon的答案很好地解釋的,MySQL對該陳述所做的是MySQL正是如此。 (這種行爲的好處之一就是我們從MySQL優化器中獲得了非常可預測的執行計劃。) – spencer7593

+1

@Amadan: 問題是關於*爲什麼*它沒有優化它,而不是爲什麼兩個線性第二種情況下需要掃描(這很明顯,一旦知道它不會優化它)。請參閱Gordon的答案。 而你正在用你輕浮的陳述來打擊整個優化領域:「如果它太微不足道了,人類可以做到,也許人類有理由不這樣做」。除非你可以告訴每個mysql規格的兩個查詢是如何不同的(就任何可觀察到的效果而言),否則你不能排除優化的可能性。 – abi

回答

3

MySQL實現了子查詢。所以,當你寫這個(固定有子查詢的別名):

SELECT * 
FROM (SELECT * FROM T) t 
WHERE pkey = 10; 

你告訴SQL引擎T複製到一箇中間臨時表。該表沒有索引,所以這個查詢比第一個版本要貴得多。

這是MySQL的一個特點。幾乎任何其他數據庫都能正確處理。我認爲即使MS Access的。

+1

在MySQL中,*內聯視圖*(別名爲't')被稱爲**派生表**。當我們理解MySQL如何處理這個名稱時,他們使用的名稱是有道理的。內聯視圖查詢的結果是* materialized *作爲表。完成該步驟後,外部查詢可以針對新填充的表運行。 (我們也觀察到存儲視圖的相同行爲。)和其他大多數RDBMS一樣,MySQL不會將外部查詢中的謂詞向下推入視圖查詢中。 – spencer7593