11

我们有一个包含超过 200 万行的表,其中所有针对它的查询都将是使用Column1and的 Between 查找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))
4

3 回答 3

7

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

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

这将为您提供最低值Col2高于 8 的行 - 这是您感兴趣的范围。该索引仅在 上需要Col2,并且成本应该很小。

由于您没有提及您正在使用的 DBMS,因此LIMIT 1应将其替换为您的 DB 用于获取前 N 个结果的任何内容。

您必须检查Col1 <= your_value代码以确保您要查找的值确实在该范围内。

于 2012-10-18T15:18:01.670 回答
3

我想我已经找到了答案。我必须首先在 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 行已处理。

于 2012-10-18T22:04:10.910 回答
1
select * from table1 where Col1 <= 8 and Col2 >= 8

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

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

于 2012-10-18T15:12:45.360 回答