[英]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.