2016-07-27 63 views
0

这是InnoDB with MySQL 5.7的索引。MySQL - 相关级联查询集合的最佳索引

我有一组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 

什么是最低组索引(ES),使得所有的查询可以使用索引(ES)的一个由每个修剪的他们的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. “>”操作主要用于分页目的。即在某些情况下,由于此条款的限制,几乎不会修剪。

我的理解是否正确?

+0

这取决于你的数据类型为真实世界的健康系统。它们是精简还是加载varchar(255) – Drew

+0

请参阅[this](http://stackoverflow.com/a/38002986)有关Optimizer和'IN' – Drew

回答

1

执行不是在同一个查询中同时执行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'S和扫描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个指数具有“覆盖”指标,给您额外的奖励。最后的SELECT需要一个9列索引来“覆盖”;那太多了。

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

(警告:之前约5.6,在跨越不存在,所以“最好的”设置指标是别的东西。)