为只有一个匹配的Between查询索引SQL?
Posted
技术标签:
【中文标题】为只有一个匹配的Between查询索引SQL?【英文标题】:Indexing SQL for Between query with only one match? 【发布时间】:2012-10-18 15:05:17 【问题描述】:我们有一个包含超过 200 万行的表,针对它的所有查询都将是使用 Column1
和 Column2
的 Between 查找。此外,只有一种可能的结果。比如……
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))
【问题讨论】:
写成'select * from table1 where Col1==8'会有帮助吗 Col1 中的步长是否始终为 5?如果是这样,那么答案很简单:) 你的执行计划是什么样的?您能否将其添加到问题中? Column1和Column2的数据类型是什么?以及如何将 8 的值放入查询中(参数、硬编码等)? 嗯,与您发布的 SQL 查询示例相比,您发布的“当前执行计划”看起来非常不同(并且错误)。能否请您发布您的实际 SQL 代码,因为这里不正确。 【参考方案1】:范围是否总是不重叠的?你提到总是只有一场比赛。如果是,你可以写成:
SELECT * FROM table1
WHERE 8 <= Col2
ORDER BY Col2 ASC
LIMIT 1
这将为您提供Col2
的最低值高于 8 的行 - 这是您感兴趣的范围。该索引仅在 Col2
上需要,并且成本应该很小。
由于您没有提及您使用的 DBMS,LIMIT 1
应替换为您的 DB 用于获取前 N 个结果的任何内容。
您必须检查代码中的Col1 <= your_value
,以确保您要查找的值确实在该范围内。
【讨论】:
【参考方案2】:我想我已经找到了答案。我必须首先在 Col1 上创建唯一聚集索引,然后在 Col2 上创建唯一非聚集索引。然后必须更新查询以强制对每个索引进行查找。
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】:select * from table1 where Col1 <= 8 and Col2 >= 8
也许两列的“中间”会导致问题。
此外,两列 (Col1, Col2) 上应该只有 1 个复合索引。
【讨论】:
以上是关于为只有一个匹配的Between查询索引SQL?的主要内容,如果未能解决你的问题,请参考以下文章
使用 between 语句查询包含数字的 SQL 列 varchar6
SQL Server 查询使用 BETWEEN 过滤器带来不匹配的数据