为什么这个查询在某些数据范围内会慢,而且速度快于其他数据?

时间:2014-11-03 07:33:17

标签: mysql sql database performance optimization

我在MySQL表中有大约100亿行坐标为(x double, y double, z double)的点。我已经在列xyz上创建了索引索引,因此按范围过滤很好而且很快。

查询模板:{}中的内容将替换为实际值)

select id from points_table where
    x between {x-5} and {x+5} and
    y between {y-5} and {y+5} and
    z between {z-5} and {z+5};

现在,奇怪的是,对于某些点,此查询始终需要约0.05秒,而对于其他点则需要大约1.5秒,即使返回的结果数量大致相同。

其中一个例子是,

(x,y,z) = (1,5,-6)查询的

需要约0.04秒并获取45个结果,但是,

(x,y,z) = (-2,0,3)查询的

需要~1.20秒并获得38个结果

这对我来说很奇怪。这种行为可能是什么原因?

编辑:根据要求解释这两个问题,

explain select id from points_table where x between 1-5 and 1+5 and y between 5-5 and 5+5 and z between -6-5 and -6+5; 
+----+-------------+--------------+-------+-------------------+-------+---------+------+-------+-----------------------------------------------+
| id | select_type | tab          | type  | possible_keys     | key   | key_len | ref  | rows  | Extra                                         |
+----+-------------+--------------+-------+-------------------+-------+---------+------+-------+-----------------------------------------------+
|  1 | SIMPLE      | points_table | range | pnt_x,pnt_y,pnt_z | pnt_y | 9       | NULL | 18748 | Using index condition; Using where; Using MRR |
+----+-------------+--------------+-------+-------------------+-------+---------+------+-------+-----------------------------------------------+


explain select id from points_table where x between -2-5 and -2+5 and y between 0-5 and 0+5 and z between 3-5 and 3+5; 
+----+-------------+--------------+-------+-------------------+-------+---------+------+--------+-----------------------------------------------+
| id | select_type | tab          | type  | possible_keys     | key   | key_len | ref  | rows   | Extra                                         |
+----+-------------+--------------+-------+-------------------+-------+---------+------+--------+-----------------------------------------------+
|  1 | SIMPLE      | points_table | range | pnt_x,pnt_y,pnt_z | pnt_y | 9       | NULL | 235748 | Using index condition; Using where; Using MRR |
+----+-------------+--------------+-------+-------------------+-------+---------+------+--------+-----------------------------------------------+

我认为只使用了y的索引,行数也存在很大差异,这可以解释时间差。

但现在我的问题是,

如何让mysql使用所有索引?他们在那里是有原因的。

修改

所以我创建了一个复合键(x,y,z),并且MySQL在做范围过滤器时似乎更喜欢它,同时查询也会花费更少的时间。

1 个答案:

答案 0 :(得分:2)

查询计划将告诉您实际使用的索引 - 但出于讨论目的,我们假设始终使用Y.

您可能会看到类似于Index X选择18,748行的情况,X和Z范围过滤除45行以外的所有行,但对于第二个查询,Index X选择235,748行,X和Z范围将结果过滤到38行。

相同的查询,相同的执行计划不计入I / O数量,但在第二个查询中处理的数据更多,以获得总行数相似的结果。

根据zerkms建议的实际查询计划信息更新此答案。