我在MySQL表中有大约100亿行坐标为(x double, y double, z double)
的点。我已经在列x
,y
和z
上创建了索引索引,因此按范围过滤很好而且很快。
查询模板:({}
中的内容将替换为实际值)
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在做范围过滤器时似乎更喜欢它,同时查询也会花费更少的时间。
答案 0 :(得分:2)
查询计划将告诉您实际使用的索引 - 但出于讨论目的,我们假设始终使用Y.
您可能会看到类似于Index X选择18,748行的情况,X和Z范围过滤除45行以外的所有行,但对于第二个查询,Index X选择235,748行,X和Z范围将结果过滤到38行。
相同的查询,相同的执行计划不计入I / O数量,但在第二个查询中处理的数据更多,以获得总行数相似的结果。
根据zerkms建议的实际查询计划信息更新此答案。