3

我有 4 个 IP 地址来源,我想将它们存储在 SQL Server 中,并允许按国家/地区在排除列表中创建可以按原始国家代码分类的范围。

为此,我有 2 张桌子。

IPAddressRange 国家代码

我需要知道的是,如果将此数据返回给客户端然后缓存以进行快速查询,那么存储返回的数据以查询范围内的特定 IP 地址的最佳方法是什么。我想知道提供的 IP 地址是否在列表中。

列表在数据库中的原因是为了便于存储。

我想缓存然后使用客户端上的数据的原因是我听说在 trie 结构中搜索 IP 地址更快。所以,我想我需要从 db 中获取列表,并以一种非常快速搜索的结构存储在缓存中。

A) 存储地址的 SQL 结构和 b) 搜索 IP 地址的代码中的任何帮助。

我知道一个代码项目解决方案,它有一个用于搜索的代码算法,不确定如何将它与存储方面混合。

理想情况下不使用第三方库。代码必须在我们自己的服务器上。

4

7 回答 7

3

我已经按照您的描述按国家/地区进行了过滤。

但是,经过一段时间的试验,我发现用 SQL 无法以高性能的方式完成。这就是为什么像这个(我正在使用的)这样的 IP 数据库提供二进制数据库的原因,它的速度快得多,因为它针对这种数据进行了优化。

他们甚至明确地说:

请注意,对导入 SQL 数据库的 CSV 数据进行查询可能需要几秒钟。如果性能是一个问题,二进制格式要快得多,并且每秒可以处理数千次查找。

此外,他们甚至为您提供查询此数据库的代码。

我在流量中等的生产网站中使用它,过滤每个请求,没有性能问题。

于 2009-01-19T21:13:36.583 回答
1

假设您的 IP 地址是 IPV4,您可以将它们存储在一个整数字段中。创建 2 个字段,一个用于范围的下限,另一个用于上限。然后确保这些字段被索引。搜索值时,只搜索值大于或等于下限,小于或等于上限的地方。在尝试自己编写更复杂的东西之前,我会先尝试这样简单的东西,但这实际上并没有明显更快的结果。

于 2009-01-19T20:45:31.977 回答
0

IPv4 地址可以存储为四字节无符号整数(C# 中的 uint)。IPv6 地址可以是八字节无符号整数(C# 中的 ulong)。在 SQL 中创建适当宽度的列,然后检索它们并将它们存储在变量中。然后,您使用简单的整数数学来检查您想要的范围,假设范围实际上是连续的。

一个更复杂的解决方案是创建一个 IPAddress 类,让您可以访问更熟悉的点四边形结构,但在幕后它会做与您在这里完全相同的事情。

于 2009-01-19T20:44:36.830 回答
0

我从来没有尝试过这个,所以我的回答要持保留态度,但我认为 trie 实际上并不是你想要的,除非你打算存储你想要阻止的每个 IP(而不是范围或子网/掩码) . 我认为 btree 会更适合,在这种情况下,请继续使用您的常规数据库(许多数据库是使用 btree 或同样好的数据结构实现的)。我会将 IP 的 4 个字节中的每一个存储在一个单独的列中,以帮助按“不关心”值等于 NULL 的 A/B/C 类子网进行搜索,但是没有理由不能存储它作为一个 32 位整数列并计算数字以找出它应该落入的范围(在这种情况下存储屏蔽值会稍微棘手一些)。

于 2009-01-19T20:45:10.743 回答
0

IPv6 地址可以是八字节无符号整数(C# 中的 ulong)

IPv6 地址是 128 位(16 字节)而不是建议的 8。我现在正在努力解决 IP 范围的这个问题。

我希望尝试填充或十六进制字符串,然后进行 < 和 > 比较

于 2009-01-19T21:31:21.853 回答
0

只要您将 IPv4 起始地址存储在正确的数据类型中,您就可以有效地做到这一点。varchar(或其他字符串类型)不正确 - 您需要使用 int。

对于 IPv4,将 IP 号码存储在一个足够大的无符号中,然后将其存储为 INET_ATON 格式(这很容易生成;我不确定在 C# 中如何,但并不难)。

然后,您可以通过安排数据库进行范围扫描,轻松有效地查找 IP 地址属于哪个范围。

通过使用 LIMIT(或 MSSQL 中的 SELECT TOP 1),您可以让它在找到记录后停止。

SELECT TOP 1 networkidorwhatever, IPNumber, IPNumberUpperBoundOrWhateverYouCallIt 
FROM networks 
WHERE IPNumber <= IPNUMBERTOQUERY ORDER BY IPNumber DESC 

应该找到编号最高的网络号 <= IP 号,然后确定该 IP 地址是否在其中是一个简单的检查。

如果在 IPNumber 上有一个常规索引,它应该是有效的。

IPv6的类型不同,但原理是一样的。

于 2009-01-19T21:49:38.040 回答
0

对于 IPv4,DBA 通常会推荐 4 个 tinyint 字段,但您正在做范围,这更适合以前提供的整数存储解决方案。在这种情况下,您将存储该范围的起始 IP 地址和结束 IP 地址。那么进行比较就很简单了。

于 2009-01-20T02:36:18.647 回答