Mysql

在分析 mysql 查詢時沒有“複製到 tmp 表”狀態

  • December 30, 2018

我有一張有 100k 行的表

創建表`small_table`(
`pk` int(11) NOT NULL AUTO_INCREMENT,
`varc` varchar(255) 預設為空,
`txt` 文本,
主鍵(`pk`)
) 引擎=InnoDB AUTO_INCREMENT=103925 預設字元集=utf8

我已經執行了以下查詢

select varc,count(*) from small_table group by varc;

我也做了同樣的介紹

+----------------------+----------+
| 狀態 | 持續時間 |
+----------------------+----------+
| 出發| 0.000060 |
| 檢查權限 | 0.000010 |
| 開桌 | 0.004685 |
| 初始化 | 0.000025 |
| 系統鎖 | 0.000006 |
| 優化 | 0.000002 |
| 統計 | 0.000010 |
| 準備| 0.000006 |
| 創建 tmp 表 | 0.000020 |
| 排序結果 | 0.000003 |
| 執行 | 0.000005 |
| 發送數據 | 0.001720 |
| 創建排序索引 | 0.000033 |
| 結束 | 0.000002 |
| 查詢結束 | 0.000004 |
| 刪除 tmp 表 | 0.000004 |
| 查詢結束 | 0.000002 |
| 關閉表| 0.000004 |
| 釋放物品 | 0.000015 |
| 清理| 0.000007 |
+----------------------+----------+

該配置文件具有創建 tmp 表狀態(通過 mysql 文件,這意味著在記憶體或磁碟中創建了一個 tmp 表)。我懷疑配置文件沒有復製到 tmp 表狀態(在狀態期間,伺服器將復製到記憶體中的臨時表。)我的假設是它已經創建了一個 tmp 表並且沒有使用它。我對嗎?

我的複製到 tmp 表狀態在哪裡?

它只是有一個稍微不同的名字。它是“創建 tmp 表”,這也更有意義。MySQL 知道將需要一個臨時表,因此它會即時生成它。狀態名稱“複製到 tmp 表”選擇不當。

我通常發現 Profile 沒用。通常“發送數據”是最上面的條目。這沒有給出應該修復什麼以提高性能的線索。

雖然沒有“複製到 tmp 表”,但有一個相當大的“打開表”。但不知道它是您的表還是tmp表。有“創建 tmp 表”。tmp 表可能在記憶體中;也就是說,沒有實際的磁碟表。

有兩種方法可以進行查詢 -

  • 在所有的記憶體中建立一個雜湊varcs;掃描表,增加散列中的條目;對結果進行排序;傳遞它。
  • 首先對錶進行排序(在您的情況下,這涉及 RAM 中的 tmp 表);然後進行簡單的表掃描,一次建構一個COUNT

我不知道優化器何時會選擇一個。但它總是涉及表掃描,這往往是花費的大部分時間(儘管它沒有出現在配置文件中)。

如果你碰巧有INDEX(varc),它會這樣做:

  • 掃描該索引,一次建立一個計數。這將避免臨時表和任何形式的排序。

但是……當查詢時間低於 10 毫秒時,不值得剖析——獲得的東西很少,值得優化的東西也很少。

引用自:https://dba.stackexchange.com/questions/222169