我在下表中对MySQL进行了搜索,其中包含以下列和索引:
查询如下,请注意天数为6:
SELECT * FROM data WHERE TEMP<"3000" AND TEMP>"2600" AND Date_Time >"2016-05-05 %" and Date_Time <"2016-05-11 %";
此查询以0.59s
如果我在此查询中将天数更改为更多天数,那么我会在更长的时间内获得结果2.15s
SELECT * FROM data WHERE TEMP<"3000" AND TEMP>"2600" AND Date_Time >"2016-05-04 %" and Date_Time <"2016-05-11 %";
如何解决此问题?我觉得荒谬的是,只有另一天影响速度!我的目标是在更广泛的时间内搜索,所以我有点需要知道这背后的原因。
答案 0 :(得分:1)
事实1: MySQL在您的案例中不能使用多于1个索引
正如本博文https://www.percona.com/blog/2009/09/12/3-ways-mysql-uses-indexes/
如果您有索引(A,B)此索引可用于查找行 WHERE条款如A = 5;在5和10之间; A = 5和B之间5和 10然而,它无法帮助查找B BETWEEN 5 AND的行 10谓词,因为它不是索引前缀。
因此,在您拥有TEMP和Date_Time列并且按范围搜索的情况下,范围索引将用于TEMP或Date_Time,查询的第二部分将使用where执行。这是BTREE指数的结构性限制。
事实2:索引未覆盖您的查询,这意味着无法仅使用索引中的数据执行查询而不读取行本身
使用来自索引的读取来执行全表扫描以查找数据行&gt;按索引顺序。使用索引不会出现在Extra列中。 http://dev.mysql.com/doc/refman/5.7/en/explain-output.html#jointype_range
那么你的第一个问题会发生什么:
1. MySQL将在Date_Time索引中查找Date_Time,并选择适合' Date_Time&gt;“2016-05-05%”和Date_Time&lt;“2016-05-11%”'
2.在索引中,TEMP信息不可用,因此MySQL需要从数据表中收集所有index_rows
3. MySQL将在每一行上评估条件'TEMP&lt;“3000”AND TEMP&gt;“2600”。
第二个查询会发生什么? MySQL决定不使用任何可用索引(possible_keys)并执行全表扫描以返回值。这意味着将扫描表格的每一行以检查是否符合条件 TEMP&lt;“3000”AND TEMP&gt;“2600”AND Date_Time&gt;“2016-05-04%”和Date_Time&lt;“2016- 05-11%“。 这可能是因为前缀“2016-05-11”或“2016-05-04”没有值。