优化 IP 范围搜索?

Ash*_*ish 6 index sql-server-2000

我有一个简单的查询和表,我想知道哪种索引对这种表和查询是有效的。

在我的表中,我有 3 列

CREATE TABLE mYTable(ipFrom BIGINT, ipto BIGINT, url NVARCHAR(255))
Run Code Online (Sandbox Code Playgroud)

我正在运行这个简单的查询。

SELECT url 
FROM MyTable 
WHERE ipto <= somevalue AND ipfrom >= somevalue
Run Code Online (Sandbox Code Playgroud)

我还在所有 3 列上创建了索引,这些列聚集在 ipFrom 上,其余 2 列上没有聚集。但是这个查询在 CPU 和读取方面给我带来了非常糟糕的性能。

有什么建议。


我实施的是我喜欢根据 IP 地址重定向用户。我存储了来自不同地区和州的多个 IP 范围,并根据用户的 IP 将用户重定向到适当的 URL。

是的,我认为我在两列中以错误的方式插入了数据(稍后会重命名列),但这里的重点是最小化 CPU。

当我查看那里的执行计划时,它会在 where 子句中转换数据,我不知道它为什么要在 where 子句中转换数据。有这样的事情

|--聚簇索引查找(OBJECT:([T].[TC]), SEEK:([T].[C] > Convert([@V])

Jac*_*las 6

根据马丁的评论,我假设问题中有一个错字。

与单一范围的问题上寻求要么ipFrom或者ipTo是平均起来将需要寻求一半表。另一种方法是

1)添加一个计算列,例如:

 ALTER TABLE MyTable
  ADD granule 
AS CASE WHEN (ipTo-ipFrom)<16 THEN 1 WHEN (ipTo-ipFrom)<256 THEN 2 ELSE 3 END;
Run Code Online (Sandbox Code Playgroud)

2) 索引计算列和 ipFrom

CREATE ClUSTERED INDEX IX ON MyTable(granule, ipFrom ); 
Run Code Online (Sandbox Code Playgroud)

3)这样的查询:

SELECT url
FROM   MyTable
WHERE  granule = 1
       AND ipFrom BETWEEN @somevalue - 16 AND @somevalue
       AND ipTo >= @somevalue
UNION ALL
SELECT url
FROM   MyTable
WHERE  granule = 2
       AND ipFrom BETWEEN @somevalue - 256 AND @somevalue
       AND ipTo >= @somevalue
UNION ALL
SELECT url
FROM   MyTable
WHERE  granule = 3
       AND ipFrom <= @somevalue
       AND ipTo >= @somevalue;
Run Code Online (Sandbox Code Playgroud)

确切地说,您如何定义“颗粒”函数将取决于ipto-ipfrom数据中的传播速度。


gbn*_*gbn 1

这符合您当前的逻辑(未经测试),但请参阅我对问题的评论。
我所做的是反转过滤器以排除不需要的行:现在您可以索引iptoipfrom(当然,索​​引中也需要 url,除非您有可以替代的 PK)

我建议 SQL Server 2005+ 使用此方法

SELECT url 
FROM MyTable 

EXCEPT
SELECT url 
FROM MyTable 
WHERE ipto > somevalue

EXCEPT
SELECT url 
FROM MyTable 
WHERE ipfrom < somevalue
Run Code Online (Sandbox Code Playgroud)

但是,对于 SQL Server 2000

SELECT url 
FROM MyTable M
WHERE
   NOT EXISTS (SELECT *
        FROM MyTable M2
        WHERE ipto > somevalue AND M.url = M2.url)
   AND
   NOT EXISTS (SELECT *
        FROM MyTable M3
        WHERE pfrom < somevalue AND M.url = M3.url)
Run Code Online (Sandbox Code Playgroud)