【发布时间】:2014-11-03 07:33:16
【问题描述】:
我在 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 在执行范围过滤时似乎更喜欢它,而且查询花费的时间也始终更少。
【问题讨论】:
-
请出示执行计划。 MySQL 可能不使用多个索引,并且数据倾斜可能是不幸的。您能否分别发布三个维度中的计数(
where x between 1-5 and 1+5等)。 -
除了执行计划和统计信息 - 表架构
-
18748vs235748--- 这是一个数量级的扫描差异。 -
您可以尝试使用复合索引。但是字段的顺序很重要,把最严格的字段放在第一位(如果在这方面有任何明显的区别)。
-
@zerkms 我创建了一个复合键 (x, y, z),MySQL 在执行范围过滤时似乎更喜欢它,而且查询花费的时间也始终更少,来自
EXPLAIN的Extra读取@987654336 @我猜这是好事
标签: mysql sql database performance optimization