mysql - 要创建哪些索引来加速繁重的筛选和分组查询?

标签 mysql database indexing

我有一个这样的表,它有数百万条记录:

CREATE TABLE `myTable` (
`DateTime` DATETIME NOT NULL,
`Col1` MEDIUMINT UNSIGNED NOT NULL,
`Col2` MEDIUMINT UNSIGNED NOT NULL,
`Col3` MEDIUMINT UNSIGNED NOT NULL,
`Col4` MEDIUMINT UNSIGNED NOT NULL,
`Event` MEDIUMINT UNSIGNED NOT NULL,
`State` MEDIUMINT UNSIGNED NOT NULL,
PRIMARY KEY (`DateTime`,`Col4`,`Event`,`State`)
);

我运行一个查询来计算一个时间范围内按时间段分组的记录数,如果它们匹配基于 Col1/Col2/Col3/Col4 值的“过滤器”。例如,3 分钟:

select
    FROM_UNIXTIME(UNIX_TIMESTAMP(MIN(`DateTime`))-(UNIX_TIMESTAMP(MIN(`DateTime`)) % (3*60))) as 'Period',
    count(*) as 'NumberOfRecords'
from
    `myTable`
where
    `DateTime` > '2016-09-01' and `DateTime` < '2016-09-09'
    AND `Col1` IN (3, 6, 11, 14, etc... )
    AND `Col2` IN (5 ,25 , 325 , 293, 294, etc.... )
    AND `Col3` IN (3 , 9 , 95 , 395 , 435, etc...)
    AND `Col4` IN (124, 125, 135, 325, etc...)
group by
    UNIX_TIMESTAMP(`DateTime`) DIV (3*60);

我应该有什么索引来加速这个查询?我不在乎插入速度有多慢,我希望查询运行得非常快。

一般来说,每个 col1、col2、col3、col4 大约有 1,000 个唯一值,但有数百万条记录适合该日期范围。

我在想:

CREATE INDEX `myIndex` ON `myTable` ( `DateTime`, `Col`,`Col2`,`Col3`,`Col4 )

但我不确定我的顺序是否正确?还是制作 4 个索引更好,每个索引一个 (DateTime,ColX)?

最佳答案

鉴于您的五列表结构,此查询很难优化,因为您要运行多达六个不同的范围谓词

范围谓词包括操作 > , < , <> , BETWEEN , LIKE , 或 IN() .基本上,除 = 以外的任何类型的搜索.

范围谓词可能匹配列中的许多值。

相等谓词恰好匹配列中的一个值(可能有很多行具有该值,但它是一个值)。

定义索引时,放入索引的列应该首先是相等比较中的列引用,然后是范围谓词中引用的一个列。在范围谓词中引用的第一列之外的索引中的任何其他列都不会计算在执行查找中。

例如,如果您在 (col1, col2, col3) 上有一个索引, 满足以下条件:

WHERE col1=123 AND col2 IN (4, 5, 6) AND col3=789

这个查询可以使用索引的前两列。 col3不会使用索引。查询将检查与前两项匹配的所有行,并针对所有这些行逐一评估第三项。

而同一个索引将使用所有三列按以下条件进行查找:

WHERE col1=123 AND col2=789 AND col3 IN (4, 5, 6)

也就是说,前两列的相等谓词和索引中最后一列的范围谓词。

当您使用 EXPLAIN 时,其中一列报告索引条目的字节数。在上面的示例中,假设所有三列都是 32 位整数列。第一个查询的 EXPLAIN 将报告它使用了 8 个字节(两个整数的值),第二个查询的 EXPLAIN 将报告它使用了 12 个字节(三个整数的值)。

在您的情况下,您的条件中有 所有 项的范围谓词。这不能使用 B-Tree 索引进行优化。它可以为任何一列使用索引。因此,您可能会创建五个单独的索引,每个都在其中一列上,并希望优化器选择能够最有效地缩小搜索范围的索引。或者你可以使用 index hints自己选择最好的索引。

我写了一个您可能会感兴趣的演示文稿,名为 How to Design Indexes, Really .这是我的演讲录音:https://www.youtube.com/watch?v=ELR7-RdU9XU

除了B树索引之外,还有其他类型的索引。对多列的范围谓词搜索可能需要 R 树索引。所以你可能会发现要真正优化这个查询,你需要将数据的副本加载到 Apache Solr 中。或 Crate或其他类似的搜索引擎。

关于mysql - 要创建哪些索引来加速繁重的筛选和分组查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39401532/

相关文章:

database - 哪个数据库被普遍认为是企业界的大佬?

mysql - 如何从 IF 子句返回时间

php - Mysql查询计数某些值

另一位程序员的C++理解遍历B树

php - 提高 MySQL 中 2 个左连接和多个 SUM 的性能

SQL Server 2008索引碎片问题

indexing - 谷歌企鹅恢复时间?

php - 查询多个mysql行并在之后分成变量?

java - 在哪里初始化连接池,java tomcat

android - 如何将 Android 手机上的 SQLite 数据库与服务器上的 MySQL 数据库同步?