首頁 >資料庫 >mysql教程 >高基數與低基數:範圍索引哪一列應該排在第一位?

高基數與低基數:範圍索引哪一列應該排在第一位?

DDD
DDD原創
2024-12-08 07:30:15965瀏覽

High Cardinality vs. Low Cardinality: Which Column Should Come First in a Range Index?

範圍索引中的高基數列排序

在資料庫設計中,當在多個列上建立索引時,這些列的順序可以顯著影響範圍查詢的效能。特別是,對於同時涉及高基數列和低基數列的查詢,索引中的最佳列排序可能是違反直覺的。

場景:

考慮具有以下架構的表:

CREATE TABLE `files` (
  `did` int(10) unsigned NOT NULL DEFAULT '0',
  `filename` varbinary(200) NOT NULL,
  `ext` varbinary(5) DEFAULT NULL,
  `fsize` double DEFAULT NULL,
  `filetime` datetime DEFAULT NULL,
  PRIMARY KEY (`did`,`filename`),
  KEY `fe` (`filetime`,`ext`),          -- This?
  KEY `ef` (`ext`,`filetime`)           -- or This?
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;

該表存儲文件元數據,大約有 100 萬行。 filetime 列大部分具有不同的值,表示高基數,而 ext 列具有有限數量的值,表示低基數。

查詢:

以下查詢用於根據ext 和filetime 擷取檔案資訊:

WHERE ext = '...'
  AND filetime BETWEEN ... AND ...

最佳索引選擇:

問題是哪個索引fe 或ef 比較適合此查詢。直觀上,人們可能會認為首先具有高基數列(文件時間)的索引會更有效。然而,分析顯示事實恰恰相反。

解釋:

使用EXPLAIN 命令,我們可以檢查不同索引選擇的查詢計劃:

-- Force index on fe (filetime first)
EXPLAIN SELECT COUNT(*), AVG(fsize)
FROM files FORCE INDEX(fe)
WHERE ext = 'gif' AND filetime >= '2015-01-01' AND filetime < '2015-01-01' + INTERVAL 1 MONTH;

-- Force index on ef (ext first)
EXPLAIN SELECT COUNT(*), AVG(fsize)
FROM files FORCE INDEX(ef)
WHERE ext = 'gif' AND filetime >= '2015-01-01' AND filetime < '2015-01-01' + INTERVAL 1 MONTH;

結果表明,低基數ext 列在前的索引ef的性能明顯優於fe.

使用優化器追蹤的進一步分析表明,使用 fe 索引,優化器估計會掃描大量行 (16684) 以過濾 ext 值。透過 ef 索引,它可以有效地使用兩個索引列並僅檢索相關行 (538)。

結論:

建立複合索引以支援範圍時查詢時,建議首先放置參與相等性測試的列(在本例中為ext),無論其基數如何。這使得索引可以在查詢執行計劃中更有效地使用,從而提高效能。

以上是高基數與低基數:範圍索引哪一列應該排在第一位?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn