Mysql

為什麼 MySQL 8 在使用具有降序 PRIMARY KEY、2 個索引和現有行的有效連接條件的表時不返回任何行

  • August 16, 2022

使用 2 個表(A 和 B),可通過它們的 PK 連接,其中 A 的 PRIMARY KEY 排序為 DESC(PK 按 MySQL 8 允許的降序排列),並且 A 在 ASC 排序中具有 2 個索引。

當我執行類似的查詢時

SELECT * FROM `A` a
LEFT JOIN `B` b ON a.id <=> b.id
WHERE a.idx1 = 'X' AND a.idx2 = 'Y';

它不會返回任何內容……但是,如果我添加一個精確的條件,例如:

SELECT * FROM `A` a
LEFT JOIN `B` b ON a.id <=> b.id
WHERE a.idx1 = 'X' AND a.idx2 = 'Y' AND a.id = 1337;

它將找到具有指定值作為 PRIMARY KEY 的行。

一個解釋表明,當 MySQL 沒有找到任何東西時,它會使用 ‘index_merge_intersection’ 優化。如果我們禁用 ‘index_merge’ 優化,第一個查詢將按預期返回所有結果。

為什麼?

它實際上是一個 MySQL 8.0 錯誤(針對 MySQL 8.0.27-debug / 8.0.28 報告),但在 (8.0.23) 之前也存在,並且似乎也存在於 fork (MariaDB/Percona/AWS Aurora/…) 上。

您可以在此處檢查該錯誤是否最終得到修復:https ://bugs.mysql.com/bug.php?id=106207

在此之前,您可以使用以下解決方案之一來緩解問題:

不要在你的 PRIMARY KEYS 上使用 DESC 排序,只有 ASC

(這也可以避免由於 MySQL 無法理解 FK 可以使用 DESC PK 而出現的 FOREIGN_KEY INDEX 的重複)

或者

從 optimizer_switch 設置中禁用 index_merge 優化

通過使用以下查詢:

SET optimizer_switch='index_merge=off,index_merge_intersection=off';

(或通過更改 optimizer_switch 的預設/全域值)因此 MySQL 將無法陷入此錯誤。

“index_merge_intersection”幾乎總是表明需要更有效的“複合”索引。添加此索引:

INDEX(idx1, idx2)

(和 Drop INDEX(idx1)

這應該會加快查詢速度;我不知道它是否可以解決 DarkCenobyte 提到的錯誤。

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