MySQL explain 中的 rows 究竟是如何計算的?


今天同事在處理系統慢SQL時遇到幾個疑惑的問題,簡單描述如下~

【背景鋪墊】

相關表:

CREATE TABLE test_table (
  id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
  name varchar(32) NOT NULL,
  PRIMARY KEY (id)
) ENGINE = InnoDB CHARSET = utf8mb4;

test_table 表記錄數約12w+

問題描述

相關SQL:

EXPLAIN SELECT COUNT(*)

FROM test_table

WHERE id >= 10534

AND id <= 15375;

疑問1:上述SQL理應按id主鍵(聚簇索引)范圍查找,為啥explain里的rows會多余兩者之差呢?

在SQL結尾處增加 LIMIT 10 后,rows數值竟然沒有任何影響(覺得可能會變為: 10)。

EXPLAIN SELECT COUNT(*)

FROM test_table

WHERE id >= 10000

LIMIT 10;

疑問2:LIMIT值不會影響rows的值么?

rows究竟是怎么計算的呢?

這個rows在官網文檔中的解釋如下:

rows (JSON name: rows)

The rows column indicates the number of rows MySQL believes it must examine to execute the query.

For [InnoDB] tables, this number is an estimate, and may not always be exact.

http://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain_rows

簡單理解即:這個rows就是mysql認為估計需要檢測的行數。

為了探究rows究竟是如何算出來的,查找MYSQL源碼來看看:

文件1:sql/opt_explain_traditional.cc
   關鍵部分:push(&items, column_buffer.col_rows, nil)
文件2:sql/opt_explain.cc
   關鍵部分:select->quick->records
文件3:sql/opt_range.cc
   關鍵部分:check_quick_select

而check_quick_select的功能,在MySQL源碼中的注釋為:

Calculate estimate of number records that will be retrieved by a range scan on given index using given SEL_ARG intervals tree.

簡單翻譯就是:這個方法僅僅根據給出的關於這個索引的條件和索引本身,來判斷需要掃描多少行。

總結

MySQL Explain 里的 rows 這個值

  • 是MySQL認為它要檢查的行數(僅做參考),而不是結果集里的行數;
  • 同時 SQL里的 LIMIT 和這個也是沒有直接關系的。

另外,很多優化手段,例如關聯緩沖區和查詢緩存,都無法影響到rows的顯示。MySQL可能不必真的讀所有它估計到的行,它也不知道任何關於操作系統或硬件緩存的信息。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM