Mysql

兩列索引(相當不等的列)和數據庫優化

  • October 19, 2016

我正在考慮在這樣的表上創建索引:

primary | type | id
     1   a      10001
     2   a      10002
     3   b      10001
     n   b      1....

type 將包含四個值,~ 95 % 將是“a”(或 1,請不要關心確切的值/標準化)。此外,95% 的查詢也將尋找“a”,並結合 id 列表(約 1 到 5 個左右),例如:

SELECT id FROM table WHERE type = 'a' AND id IN (...)

基本任務是檢查給定 id 的列表是否存在,所以“覆蓋索引”是我基本上想要的東西。

現在,據我了解,最好先使用最能減少結果集的列,即 id。但另一方面,智能數據庫引擎可以檢測到大多數查詢是關於“a”的,並且可以僅將索引樹的這個分支保留在記憶體中,或者,如果提供足夠的記憶體,將所有三個索引作為“不同”索引每個,因為最好不要打擾所有的“b”值。

MySQL/MariaDB(只是 InnoDB 後端)是否在做這種優化?還是有其他想法?我對這張表不是很感興趣,更多的是對這個案例的一般看法。

提前感謝您的所有評論;)

有很多細節缺失。創新數據庫?正是SELECT id FROM table WHERE type = 'a' AND id IN (...)有問題的查詢?(很少得到只有id,尤其是當你在 中指定它的時候WHERE。) id不是PK嗎?這很令人困惑。請換個問題。

不管基數如何,使用它通常會更好,很少會更糟

INDEX(type, id)

對於這個和類似的查詢。

一方面,這個特殊SELECT可以完全在 BTree 索引中執行。因此它是一個“覆蓋”索引。將EXPLAIN SELECT...通過說“使用索引”來表明這一點。

如需進一步討論,請提供SHOW CREATE TABLEEXPLAIN SELECT ...與實際查詢。

(是的,我不同意 Károly Nagy 的觀點。)

更多的

“覆蓋”索引是包含SELECT.

列的最佳順序是

  1. 首先佈置最適合定位行的列。
  2. 然後以任何順序添加任何額外的列(以“覆蓋”)。

我在我的Index 食譜中討論了第 1 步。請注意,它說首先放置“=”列。

所以…

  • type因為’=‘而排在第一位;
  • id接下來是因為需要找到所需的行;
  • 最後,“覆蓋”不需要額外的列。

我承認在“95% 的行具有 type=‘a’”方面存在權衡。讓我深入研究兩種方法的細節:

方法1:輔助鍵INDEX(id, type)

這將多次進入 BTree 索引(每個 1 次id),然後向前掃描跳過任何(非常少)不是的行type='a'。(在文件中,有關這種跨越式的討論,請參閱“MRR”。)

方法2:輔助鍵INDEX(type, id)

這將多次進入 BTree 索引(每個組合一個 ( 'a', id),然後向前掃描。但它不需要跳過任何一個。這種方法在使用 ‘a’ 時並沒有明顯快,但對於type='b'.

方法3:輔助鍵INDEX(id)

這肯定比其他人慢。它必須在索引中找到每個id,然後伸手檢查數據type。索引和數據之間的這種來回彈跳將使其大約慢兩倍。優化器注意到這一點並可能決定簡單地忽略索引並掃描整個表會更快。

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