2017-06-22 55 views
2

我有一个数据库,其中有四列,分别对应起始和结束位置的地理坐标x,y。列是:IN子句中的MySQL多列

  • X0
  • Y0
  • X1
  • Y1

我对这些四列与序列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)); 

我想有可能做的事指数?什么是最好的方法(即:最快的查询)?谢谢你的帮助!

注:

  • 我不能更改数据库的模式
  • 我对100'000'000行

编辑: 代码原封不动地竟是工作,但它非常缓慢,并没有利用指数(因为我们有一个旧版本的MySQL v5.6.27)。

+0

这应该在MySQL的正常工作,你试过吗?我看到的第一条评论说,你所关联的问题来自5年前。 – Uueerdo

+1

只要你知道,你**可以**在MySQL中做到这一点。看到我的测试:http://sqlfiddle.com/#!9/7b5c1/1 – sorayadragon

回答

4

为了有效地利用索引,你可以重写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) 
) 
+0

您的解决方案要快得多。使用我们的MySQL版本,单个查询(100'000'000行,列表中的10个元素)在解决方案中耗时3.14秒,使用“IN”语法耗时1427秒。 – nbeuchat

+0

@GordonLinoff建议的查询模式可能更快, 将单独SELECT语句的结果与'UNION ALL'集合运算符连接起来。 EXPLAIN可能会以“ref”和“const”显示查询,而不是“范围”。该模式肯定会使用索引。不保证它会更快,但值得测试。 – spencer7593

+0

只有一次性测试,GordonLinoff的解决方案比你的解决方案稍慢(3.96 vs 3.14秒)。这是迄今为止不是一个严格的测试,但至少,这两个选项都使用索引。 – nbeuchat

1

可以concatenate四个值转换为字符串,并检查他们这样的:

SELECT * 
FROM my_table 
WHERE CONCAT_WS(',', x0, y0, x1, y1) IN ('4,3,5,6', ..., '9,3,2,1'); 
+0

MySQL需要评估表中*每行*的CONCAT_WS函数。这可能会使用索引,但它会对索引进行全面扫描,所有100,000,000行。 – spencer7593

4

我不明白你的意思。以下查询是有效的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条款中的平等的比较将采取指数的优势。

+0

确实,这是一个有效的语法,但需要花费很长时间才能执行。看来我们使用的MySQL版本没有利用索引。 – nbeuchat

0

你正在做的是给在MySQL的版本正确结果的方式我机。我正在使用v5.5.55。也许你正在使用一个较旧的。请检查。

如果您仍想在您自己的版本中解决此问题或者上述解决方案无效,请仅阅读下一个解决方案。

我还不清楚这里所有列的数据类型和范围。所以我假设数据类型是整数,范围在0到9之间。如果是这种情况,你可以很容易地做到这一点,如下所示。

select * from s1 where x0+10*x1+100*y1+1000*y2 in (4356,..., 9321); 
+0

使用这种方法,MySQL将不能在索引'(x0,x1,y1,y2)'上使用范围扫描操作。 MySQL将在表中的100,000,000行中的每一行中的where子句中评估该表达式。 – spencer7593