簡體   English   中英

當使用索引時,Mysql解釋查詢類型為“ALL”

[英]Mysql Explain Query with type “ALL” when an index is used

我在Mysql中運行了一個查詢,如下所示:

EXPLAIN
SELECT *
FROM(
        SELECT *  # Select Number 2
        FROM post
        WHERE   parentid = 13
        ORDER BY time, id
        LIMIT 1, 10
    ) post13_childs
JOIN post post13_childs_childs
ON post13_childs_childs.parentid = post13_childs.id

結果是:

id |select_type  |table               |type |possible_keys  |key      |key_len  |ref              |rows    |Extra
1  |PRIMARY      |<derived2>          |ALL  | NULL          | NULL    |NULL     |NULL             |10      |
1  |PRIMARY      |post13_childs_childs|ref  |parentid       |parentid |9        |post13_childs.id |10      |Using where
2  |DERIVED      |post                |ALL  |parentid       |parentid |9        |                 |153153  |Using where; Using filesort

這意味着它使用了索引parentid但是由於ALL153153而掃描了所有行。 為什么索引無法幫助Full Scannig

雖然如果我單獨運行派生查詢(選擇#2) 如下所示:

Explain
SELECT * FROM post  
WHERE parentid=13
ORDER BY time , id
LIMIT 1,10

結果是理想的:

id |select_type  |table  |type |possible_keys  |key      |key_len  |ref  |rows    |Extra
1  |SIMPLE       |post   |ref  |parentid       |parentid |9        |const|41      |Using where; Using filesort

編輯:

表格post有以下索引:

  1. id(PRIMARY)
  2. parentId的
  3. 時間,id(timeid)

總行數 - > 141280。
13歲兒童的數量( parentid=13 ) - > 41
兒童11523 - > 10119

當我添加(parent,time,id)索引(parent,time,id)第一個查詢的問題將通過13 - > 40行的explin輸出來解決,輸入:ref
對於11523 - > 19538行,請輸入:ref !!! 這意味着檢查所有11423行的子行,而我限制前10行。

你的子查詢:

    SELECT *  # Select Number 2
    FROM post
    WHERE   parentid = 13
    ORDER BY time, id
    LIMIT 1, 10;

這顯然提到了三列,加上所有其他列你有三個索引。 以下是它們的使用方法:

  • id(PRIMARY) - 這個索引沒用。 雖然在order by子句中提到,但它是第二個條件
  • parentid - 此索引可用於滿足where子句。 但是,在拉出正確的數據之后,需要明確地對其進行排序。
  • time,id(timeid) - 這個索引可以用於排序,具有很大的BUT。 MySQL可以掃描索引以獲得正確順序的所有內容。 但它必須逐行檢查是否滿足了parentid的條件。

只是為了介紹為什么優化很難。 如果您有少量數據(比如表格適合一頁或兩頁),那么全表掃描后跟排序可能就好了。 如果大多數parentid值是13 ,那么第二個索引可能是最壞的情況。 如果表不適合內存,那么第三個將非常慢(稱為頁面顛簸 )。

此子查詢的正確索引是滿足where子句並允許排序的索引。 該指數是parentid, time, id 這不是覆蓋索引(除非這些是表中的所有列)。 但是由於limit子句,它應該將實際行的命中數減少到10。

請注意,對於完整查詢,您需要parentid上的索引。 並且,幸運的是,關於parentid, time, id的索引算作這樣的索引。 因此,您可以刪除該索引。 time, id索引可能不是必需的,除非您需要其他查詢。

您的查詢也只過濾那些自己有“孩子”的“孩子”。 很可能不會返回任何行。 你真的想要一個left outer join嗎?

作為最后的評論。 我假設此查詢是您的真實查詢的簡化。 查詢從兩個表中提取所有列 - 這兩個表是相同的。 也就是說,您將從相同的表中獲取重復的列名。 您應該有列別名以更好地定義列。

執行任何索引無法幫助的ORDER BY都可能導致性能下降。 對於內部查詢,我將在(parentID,time,id)上設置覆蓋索引,以便WHERE和ORDER BY子句都可以使用索引。 由於parentID也是連接后綴的基礎,所以去那里並且非常快。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM