2012-10-18 27 views
11

我们有一个超过两百万行的表,其中所有查询都是使用Column1Column2之间的查找。而且,只会有一个可能的结果。例如...为只有一个匹配的查询编制索引SQL?

Col1  Col2 
1  5 
6  10 
11  15 

select * from table1 where 8 between Col1 and Col2 

我目前对Col1Col2的唯一聚集索引。到目前为止,我一直无法弄清楚如何进一步调整查询和索引来最小化处理的行。目前的执行计划报告了在查找唯一正确答案时所处理的近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)) 
+0

将它写为 'select * from table1 where Col1 = < 8 and Col2> = 8' – Vicki

+0

Col1中的步骤总是5吗?如果是这样,那么答案很简单:) –

+0

你有什么样的执行计划?你可以补充说这个问题吗? –

回答

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行处理。

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

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

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

6

范围始终不重叠?你提到总是只有一个匹配。如果是这样,你可以把它写成:

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

这会给你的Col2最低值高于8行 - 这是你有兴趣将只需要对指数的范围内。 Col2,成本应该很小。

由于您没有提及您正在使用的DBMS,因此应该使用LIMIT 1替换您的数据库用于获取前N个结果的数据。

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