我有一个数据库,其中有四列对应于起始位置和结束位置的地理坐标x,y。列是:
我有这四列的索引,序列为x0,y0,x1,y1。
我有一百个地理对的组合列表。我如何有效地查询这些数据?
我想按this SO answer的建议做这样的事情,但它只适用于Oracle数据库,而不适用于MySQL:
SELECT * FROM my_table WHERE (x0, y0, x1, y1) IN ((4, 3, 5, 6), ... ,(9, 3, 2, 1));
我原以为可以用索引做点什么?什么是最好的方法(即:最快的查询)?谢谢你的帮助!
注意:
修改
代码原样实际上正在工作,但它非常慢并且没有利用索引(因为我们有一个旧版本的MySQL v5.6.27
)。
答案 0 :(得分:12)
为了有效地使用索引,您可以重写IN谓词
(x0, y0, x1, y1) IN ((4, 3, 5, 6),(9, 3, 2, 1))
像这样:
( ( x0 = 4 AND y0 = 3 AND x1 = 5 AND y1 = 6 )
OR ( x0 = 9 AND y0 = 3 AND x1 = 2 AND y1 = 1 )
)
答案 1 :(得分:7)
MySQL允许像你所示的行构造函数比较,但优化器在MySQL 5.7之前不知道如何使用索引来帮助提高性能。
答案 2 :(得分:5)
我不明白你的观点。以下查询是有效的MySQL语法:
SELECT *
FROM my_table
WHERE (x0, y0, x1, y1) IN ((4, 3, 5, 6), ... ,(9, 3, 2, 1));
我希望MySQL能够使用你所描述的复合索引。但是,如果它不能做到:
SELECT *
FROM my_table
WHERE x0 = 4 AND y0 = 3 AND x1 = 5 AND y1 = 6
UNION ALL
. . .
SELECT *
FROM my_table
WHERE x0 = 9 AND y0 = 3 AND x1 = 2 AND y1 = 1
WHERE
子句中的相等比较将利用索引。
答案 3 :(得分:2)
您可以将concatenate四个值转换为字符串,然后按以下方式进行检查:
SELECT *
FROM my_table
WHERE CONCAT_WS(',', x0, y0, x1, y1) IN ('4,3,5,6', ..., '9,3,2,1');
答案 4 :(得分:0)
您正在做的是在我的机器上的mysql版本中提供正确的结果。我正在使用v5.5.55
。也许你正在使用较旧的。请检查一下。
如果您仍想在自己的版本中解决此问题或上述解决方案无效,则只阅读下一个解决方案。
我仍然不清楚这里所有列的数据类型和范围。所以我假设数据类型是整数,范围介于0到9之间。如果是这种情况,您可以轻松地执行此操作,如下所示。
select * from s1 where x0+10*x1+100*y1+1000*y2 in (4356,..., 9321);