问题 为只有一个匹配的Between查询索引SQL?


我们有一个包含超过两百万行的表,其中对它的所有查询都是使用的查找 Column1 和 Column2。此外,只有一个可能的结果。例如...

Col1     Col2
1        5
6        10
11       15

select * from table1 where 8 between Col1 and Col2

我目前有一个独特的聚簇索引 Col1 和 Col2。到目前为止,我一直无法弄清楚如何进一步调整查询和索引以最小化处理的行。执行计划目前报告在找到唯一正确答案时处理的成本几乎为0.5和113k行。

我可以忽略哪些选择?

根据要求,当前执行计划的一些细节:

Operation
 Clustered Index Seek
Predicate
 CONVERT_IMPLICIT(bigint,[@2],0)<=[Col2]
Seek Predicate
 Seek Keys[1]: End: Col1 <= Scalar Operator(CONVERT_IMPLICIT(bigint,[@1],0))

6784
2017-10-18 15:05


起源

将它写为'select * from table1,其中Col1 = <8和Col2> = 8'会有帮助吗? - Vicki
Col1中的步长总是5吗?如果是这样,答案很简单:) - Yoni Baciu
您的执行计划是什么样的?你可以在问题中加上这个吗? - Mikael Eriksson
Column1和Column2的数据类型是什么?如何将8的值放入查询(参数,硬编码等)? - Dave Simione
嗯,与您发布的SQL查询示例相比,您发布的“当前执行计划”看起来非常不同(和错误)。您能否发布您的实际SQL代码,因为有些东西不在这里。 - RBarryYoung


答案:


范围是否始终不重叠?你提到总有一场比赛。如果是,您可以将其写为:

SELECT * FROM table1 
   WHERE 8 <= Col2 
   ORDER BY Col2 ASC
   LIMIT 1

这将为您提供最低值的行 Col2 大于8 - 这是你感兴趣的范围。只需要索引 Col2,成本应该很小。

既然你没有提到你正在使用的DBMS,那么 LIMIT 1 应该替换为数据库用于获取前N个结果的任何内容。

你必须检查 Col1 <= your_value 在代码中,以确保您正在寻找的值确实在范围内。


6
2017-10-18 15:18





我想我找到了答案。我必须首先在Col1上创建一个Unique Clustered Index,然后在Col2上创建一个Unique Unclustered Index。然后必须更新查询以强制查找每个索引。

select * from table1 where Col1 = 
    (select max(Col1) from table1 where Col1 <= 8)
and Col2 = 
    (select min(Col2) from table1 where Col2 >= 8)

执行计划现在报告0.0098成本和1行处理。


3
2017-10-18 22:04





select * from table1 where Col1 <= 8 and Col2 >= 8

也许两列之间的“之间”导致问题。

此外,您应该在两列(Col1,Col2)上只有1个复合索引。


1
2017-10-18 15:12