某些范围的SQL Server varbinary聚簇索引查找速度较慢

时间:2017-10-26 21:04:23

标签: sql sql-server indexing varbinary

在我的工作中,我们目前有一个包含5000万行的表,它有两个Varbinary(16)列的索引,分别是ip_start和ip_end。

PRIMARY KEY CLUSTERED 
(
    [ip_end] ASC,
    [ip_start] ASC
)

表格中的前几行是这样的:

ip_start   ip_end      id
0x00000000  0x00000000  0
0x00000001  0x000000FF  1
0x00000100  0x00FFFFFF  2
0x01000000  0x010000FF  3

我们用于查找匹配项的查询是:

SELECT TOP 1 id
FROM dbo.ip_ranges WITH (NOLOCK)
WHERE @lookup <= ip_end AND @lookup >= ip_start

当我查找类似0x00000002的ip时,它会立即返回id 1,但如果我搜索范围介于0x000000000000001之间的范围,则需要几秒钟才能返回NULL。 SQL Server是否应该理解varbinary索引是否有序,因此如果没有匹配则快速返回?

有没有更好的方法来查询这个,期望一些ip将在范围之间或更好的方式来索引表,以便错过不会造成如此大的打击?

2 个答案:

答案 0 :(得分:4)

  

SQL Server是否应该理解varbinary索引是否有序,因此如果没有匹配则会快速返回?

SQL Server了解索引是 ordered ,但它不理解范围不重叠。这个条件@lookup >= ip_start对于一堆ip范围(大约平均一半)是正确的,这就是你看到的不匹配的性能。当第一个键具有不等式时,B-Tree索引不使用第二个键进行索引查找。

不幸的是,标准B树索引对于这种类型的搜索并不是最佳的(沿着两个维度的不等式)。 R-tree(我最初学习的是RD树)更适合。这些主要用于空间索引。

我认为我已经成功完成了这样的查询:

SELECT ir.*
FROM (SELECT TOP 1 ir.*
      FROM dbo.ip_ranges ir
      WHERE @lookup >= ip_start
      ORDER BY ip_start
     ) ir
WHERE @lookup <= ir.ip_end ; 

SQL Server应该使用子查询的索引,快速找到第一个匹配的行。然后,您可以单独检查范围的结尾是否在此行上。这是有效的,因为IP地址范围不重叠。

答案 1 :(得分:0)

使用包含列ID在ip_start上创建非聚集索引

或在一列ip_start上更新聚集索引 并在IP_end上使用包含列ID创建非集群