簡體   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