2017-10-26 6 views
1

현재 저는 50,000,000 개의 행을 가진 테이블을 가지고 있으며이 테이블은 ip_start 및 ip_end 인 두 Varbinary (16) 열에 대한 인덱스가 있습니다. SQL Server varbinary 클러스터 된 인덱스 조회가 특정 범위에서 느립니다.

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 

는 IP와 같은 0x00000002는 반환 id 1을 즉시 찾지 만, 0x000000000000001과 같은 범위 사이의 범위를 검색하면 NULL을 반환하는 데 몇 초가 걸립니다. SQL Server는 varbinary 인덱스가 정렬되어 있으므로 일치하는 항목이없는 경우 신속하게 반환해야합니까?

일부 IP가 범위 또는 더 좋은 방법으로 표를 색인화하여 손실로 인해 큰 히트가 발생하지 않도록 예측할 수있는 더 나은 방법이 있습니까?

답변

4

SQL Server는 varbinary 인덱스가 정렬되어 있으므로 일치하는 항목이없는 경우 신속하게 반환해야합니까?

SQL Server는 인덱스 을 주문한 것을 이해하지만 범위가 중복되지 않는다는 것을 이해하지 못합니다. 이 조건 @lookup >= ip_start은 여러 IP 범위 (평균 약 절반)에 해당하며, 일치하지 않는 경우에 표시되는 성능입니다. B-Tree 색인은 첫 x ​​째 키가 부등호 일 때 색인 조회에 두 x 째 키를 사용하지 않습니다.

표준 B- 트리 색인은 이러한 유형의 검색 (2 차원의 부등식)에 적합하지 않습니다. 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 서버를 신속하게 일치하는 첫 번째 행을 발견, 서브 쿼리에 대한 인덱스를 사용한다. 그런 다음 범위 끝이이 행에 있는지 별도로 확인할 수 있습니다. 이것은 IP 주소 범위가 겹치지 않기 때문에 효과적입니다.