MySQL Workbench 手冊  /  效能工具  /  教學:使用 Explain 來改善查詢效能

7.5 教學:使用 Explain 來改善查詢效能

本教學說明如何使用 Explain 報表來定位並修正有問題(速度慢)的查詢。它使用 DBT-3 資料庫,並從以下簡單的查詢範例開始。

SELECT * FROM orders
WHERE YEAR(o_orderdate) = 1992 AND MONTH(o_orderdate) = 4
AND o_clerk LIKE '%0223';

如下圖所示,查詢範例首先在視覺化 SQL 編輯器中執行。接下來,透過從 查詢 選單中點擊 Explain 目前的陳述式,產生一個 Explain 報表。初始報表顯示一個視覺化 Explain 圖像,當您將指標裝置移至完整資料表掃描中的 orders 資料表上方時,會顯示相關資訊。

圖 7.9 DBT-3 Explain 教學:具有完整資料表掃描的視覺化 Explain

Content is described in the surrounding text.

或者,您可以切換至表格化 Explain,如下圖所示。使用下拉式清單在視覺化和表格化表示之間切換。

圖 7.10 DBT-3 Explain 教學:具有完整資料表掃描的表格化 Explain

Content is described in the surrounding text.

關於查詢的問題

  • 為什麼這個查詢會產生完整資料表掃描?

  • 為什麼已建立索引的 o_orderdate 資料行遺失了,未被列為可能的索引鍵?

仔細觀察,也會注意到已建立索引的資料行在運算式中使用,例如 "WHERE YEAR(o_orderdate) = 1992 AND MONTH(o_orderdate) = 4",因此未使用索引。若要使用現有的索引,您可以調整查詢如下。

SELECT * FROM orders
WHERE o_orderdate BETWEEN '1992-04-01' AND '1992-04-30'
AND o_clerk LIKE '%0223';

更新後的查詢範例會產生一個視覺化 Explain 圖像,其中 索引範圍掃描 取代了上一個查詢範例產生的 完整資料表掃描。接下來的兩張圖顯示了修改後的查詢範例的視覺化和表格化表示。

圖 7.11 DBT-3 Explain 教學:具有索引範圍掃描的視覺化 Explain

Content is described in the surrounding text.

圖 7.12 DBT-3 Explain 教學:具有索引範圍掃描的表格化 Explain

Content is described in the surrounding text.

請注意這些差異。類型從 ALL 變更為 range,可能的索引鍵(和已使用的索引鍵)從 NULL 變更為 i_o_orderdate,而掃描的列數從 150 萬變更為約 33000。儘管如此,掃描 33000 列卻只傳回 18 列是不必要的,因此可以將重點轉移到 o_clerk 資料行。下一個查詢範例(和表格化 Explain 圖)會新增以下索引,應可提高效能。

CREATE INDEX i_o_clerk ON orders(o_clerk);

圖 7.13 DBT-3 Explain 教學:具有索引範圍掃描和索引後的表格化 Explain

Content is described in the surrounding text.

新的索引未被視為可能的索引鍵,因為查詢正在搜尋 o_clerk 資料行的後綴,而索引不適用於後綴(雖然它們適用於前綴)。相反地,這個簡單的範例可以使用完整的職員 ID。調整查詢如下所示,會顯示更好的結果。

SELECT * FROM orders
WHERE o_orderdate BETWEEN '1992-04-01' AND '1992-04-30'
AND o_clerk LIKE 'Clerk#000000223';

以下圖示分別顯示更新後的查詢範例在視覺化 Explain 和表格化 Explain 中的效果。

圖 7.14 DBT-3 Explain 教學:具有索引範圍掃描和完整 ID 的視覺化 Explain

Content is described in the surrounding text.

圖 7.15 DBT-3 Explain 教學:具有索引範圍掃描和完整 ID 的表格化 Explain

Content is described in the surrounding text.

新的 o_clerk 索引被考慮並使用,查詢掃描了 1546 列而不是 32642 列,查詢執行時間從 0.281 秒縮短到 0.234 秒。然而,EXPLAIN 估計這個查詢掃描 1546 列以傳回 18 列。在再次檢閱查詢之後,請考慮多欄索引可以滿足 WHERE 子句的條件,該子句基於 o_orderdateo_clerk 資料行,如下一個陳述式所示。

CREATE INDEX io_clerk_date ON orders(o_clerk, o_orderdate)
注意

o_clerk 在索引中顯示為第一欄,因為 o_orderdate 使用範圍。

現在,執行調整後的查詢會產生更好的結果。估計掃描和傳回了 18 列,並且查詢範例的執行時間為 0.234 秒,如下一個視覺化 Explain 和表格化 Explain 圖所示。

圖 7.16 DBT-3 Explain 教學:具有多欄索引範圍掃描的視覺化 Explain

Content is described in the surrounding text.

圖 7.17 DBT-3 Explain 教學:具有多欄索引範圍掃描的表格化 Explain

Content is described in the surrounding text.

下表總結了本教學中對查詢所做的修改結果。

表 7.2 DBT-3 Explain 教學查詢比較

類型 可能的索引鍵 索引鍵 掃描的列數 持續時間(秒) 額外資訊 傳回的列數
all NULL NULL 1.50M 1.201 使用 where 18
range i_o_orderdate i_o_orderdate 32642 0.281 使用索引條件;使用 where 18
range i_o_orderdate, i_o_clerk i_o_clerk 1546 0.234 使用索引條件;使用 where 18
range i_o_orderdate, i_o_clerk, i_o_clerk_date i_o_clerk_date 18 0.234 使用索引條件 18