我有一个数据库,我正在处理包含脉冲测量的数据 架构是这样的:
id - monitorid - starttime - stoptime - pulses
每个监视器每10分钟提供一次信息 目前,这相当于大约13 000 000行。
开始和停止时间是varchar(10),保存unix时间戳。对我来说可能效率不高。
几乎所有针对此表的查询都是'WHERE starttime> $ certaintime AND monitorid = $ monid'。所有这些查询目前都非常缓慢。
我有一个关于monitorid的索引。我还没有把它放在开始时间和停止时间上,因为我认为这会给我带来更好的基数,因为每10分钟的时间段是一个新值。我不确定这个推理。
所以,我的问题是:如何针对大多数面临的类似范围的查询优化此问题。索引启动时间?使用日期而不是时间戳重建表?
欢迎任何建议!
干杯,
迪特
答案 0 :(得分:6)
在monitorid + starttime
列上创建复合btree索引
对于使用WHERE starttime > X AND monitorid = Y
子句
CREATE INDEX name ON tablename( monitorid + starttime )
monitorid
必须是此索引中的前导列,否则索引将无法使用
有关详细信息,请阅读“8.2.1.3.2多部分索引的范围访问方法”一章:https://dev.mysql.com/doc/refman/5.7/en/range-optimization.html
他们写道:
对于BTREE索引,区间可以用于与AND组合的条件,其中每个条件使用=,< =>,IS NULL,>,<,>来比较具有常数值的关键部分。 =,< =,!=,<>,BETWEEN或LIKE'pattern'(其中'pattern'不以通配符开头)。只要可以确定包含与条件匹配的所有行的单个密钥元组(或者如果使用<>或!=,则为两个间隔),可以使用间隔。
只要比较运算符为=,< =>或IS NULL,优化程序就会尝试使用其他关键部分来确定区间。如果运算符是>,<,> =,< =,!=,<>,BETWEEN或LIKE,优化程序将使用它,但不再考虑关键部分。对于以下表达式,优化器使用=来自第一次比较。它还使用了来自第二次比较的> =,但没有考虑其他关键部分,也没有使用第三个比较进行区间构建:
key_part1 ='foo'和 key_part2 > = 10 AND key_part3 > 10
(强调我的)
上面的意思是,在您的特定情况下,如果将创建monitorid + starttime
上的索引,那么opimizec可以使用索引的两个部分,因为monitorid = $monid
在where子句中使用,但是在反向索引顺序starttime + monitorid
,索引的第二部分不可用,因为在where子句中使用了starttime > $certaintime
。