繁体   English   中英

SQL Server varbinary 聚集索引查找在某些范围内缓慢

[英]SQL Server varbinary clustered index lookups slow for certain ranges

在我的工作中,我们目前有一个包含 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 将在范围之间或更好的方法来索引表,以便未命中不会导致如此大的命中?

SQL Server 不应该理解 varbinary 索引是有序的,因此如果没有匹配项,它会快速返回吗?

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

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

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

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 地址范围不重叠。

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

或者更新一列 ip_start 上的聚簇索引,并在 ip_end 上创建非聚簇索引,包含列 id

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM