繁体   English   中英

MySQL-相关级联查询集的最佳索引

[英]MySQL - Optimal Indexes for Set of Related Cascading Queries

这用于带有MySQL 5.7的InnoDB。

我有一组4个相关的级联查询:

SELECT DISTINCT A, COUNT(*) FROM MYTABLE
    WHERE D IN ? AND A > ?
    GROUP BY A ORDER BY A LIMIT 100

SELECT DISTINCT B, COUNT(*) FROM MYTABLE
    WHERE A = ? AND D IN ? AND B > ?
    GROUP BY B ORDER BY B LIMIT 100

SELECT DISTINCT C, COUNT(*) FROM MYTABLE
    WHERE A = ? AND B = ? AND D IN ? AND C > ?
    GROUP BY C ORDER BY C LIMIT 100

SELECT E, F, G, H FROM MYTABLE
    WHERE A = ? AND B = ? AND C = ? AND D IN ? AND ID > ?
    ORDER BY ID LIMIT 100

最小索引集是什么,以便所有查询可以使用它们的每个WHERE子句来修剪它们,并且还可以使用它们来加快ORDER BY的使用,因此所有查询都可以使用?

根据我对复合索引的了解,我需要:

CREATE INDEX INDEX01 ON MYTABLE (D, A)

CREATE INDEX INDEX02 ON MYTABLE (A, D, B)

CREATE INDEX INDEX03 ON MYTABLE (A, B, D, C)

CREATE INDEX INDEX04 ON MYTABLE (A, B, C, D)

(ID是主键列)

这个对吗?

我认为,如果我对WHERE子句进行重新排序,就可以只使用一个复合索引:

SELECT DISTINCT A, COUNT(*) FROM MYTABLE
    WHERE D IN ? AND A > ?
    GROUP BY A ORDER BY A LIMIT 100

SELECT DISTINCT B, COUNT(*) FROM MYTABLE
    WHERE D IN ? AND A = ? AND B > ?
    GROUP BY B ORDER BY B LIMIT 100

SELECT DISTINCT C, COUNT(*) FROM MYTABLE
    WHERE D IN ? AND A = ? AND B = ? AND C > ?
    GROUP BY C ORDER BY C LIMIT 100

SELECT E, F, G, H FROM MYTABLE
    WHERE D IN ? AND A = ? AND B = ? AND C = ? AND ID > ?
    ORDER BY ID LIMIT 100

那么我只需要:

CREATE INDEX INDEX01 ON MYTABLE (D, A, B, C)

那是对的吗?

但是,我认为以这种方式对WHERE子句进行排序并不是最佳选择。 始终尝试将“ IN”操作和“>”操作放在最后2个WHERE子句中的原因是:

  1. 与“ =”相比,MySQL将需要为“ IN”(与多个值进行比较)做更多的工作,并且可能(由于我的数据集和我正在过滤的内容),此子句将修剪更少的行。

  2. “>”操作主要用于分页目的。 即,在某些情况下,由于该条款,几乎没有修剪。

我的理解正确吗?

不要做既DISTINCTGROUP BY在相同的查询。 由于总数( COUNT ),您可能需要GROUP BY ,因此折腾DISTINCT

对于GROUP BY x ORDER BY x LIMIT 100 ,以下操作可能会有所帮助:

INDEX(x)  -- or INDEX(x, ...)

因此,以防万一。 我的意思是,优化器可能选择使用索引来处理GROUP BY + ORDER BY + LIMIT而不是查看WHERE 如果决定使用WHERE ,则...

WHERE D IN ? AND A > ?
INDEX(D, A)

可以跳过(“ MRR”)D并扫描A,但是它不能消耗任何GROUP BYORDER BY

WHERE A = ? AND D IN ? AND B > ?
INDEX(A, D, B)

将所有“ =”东西放在索引中。 其余的逻辑如上所述。

WHERE A = ? AND B = ? AND D IN ? AND C > ?
INDEX(A, B, D, C) or INDEX(B, A, D, C)

(逻辑相同)

WHERE A = ? AND B = ? AND C = ? AND D IN ? AND ID > ?
INDEX(A,B,C, -- in any order, then
      D, ID) -- at end, in this order.

因此,对于这4条语句,我建议按照给定的顺序使用4或5个索引:

INDEX(D, A)
INDEX(A, D, B)
INDEX(B, A, D, C)  -- I picked that one to get one starting with B
INDEX(c, B, A, D, ID)
INDEX(ID)  -- but don't add if you already have `PRIMARY KEY(ID)`

作为奖励,在这些索引中,前3个SELECTs具有“覆盖”索引,这为您提供了额外的奖励。 最后一个SELECT将需要9列索引来“覆盖”; 太多了

WHERE中AND'd事物的顺序没有区别。 因此,我想我可以忽略其余的问题。

(注意:在5.6之前,不存在跨越式增长,因此“最佳”索引集将是其他东西。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM