我有4个IP地址源,我想将它们存储在SQL Server中,并允许按原始国家/地区代码分类的范围按国家/地区列在“排除”列表中。
为此我有2张桌子。
IPAddressRange COUNTRYCODE
我需要知道的是,如果这些数据被返回到客户端然后被缓存以便快速查询,那么存储返回数据以查询范围内的特定IP地址的最佳方法是什么。我想知道提供的IP地址是否在列表中。
列表在数据库中的原因是为了便于存储。
我想缓存然后使用客户端上的数据的原因是我听说在trie结构中搜索IP地址更快。所以,我认为我需要从数据库中获取列表,在缓存中存储一个非常快速搜索的结构。
A)中的任何帮助存储地址的SQL结构和b)搜索IP地址的代码。
我知道一个代码项目解决方案,它有一个搜索代码算法,不知道如何将它与存储方面混合。
理想情况下不使用第三方库。代码必须在我们自己的服务器上。
答案 0 :(得分:3)
我按国家/地区完成了一个过滤器,就像您描述的那样。
然而,经过一段时间的实验,我发现它不能用SQL以高效的方式完成。这就是为什么像this one这样的IP数据库(我正在使用的)提供了一个二进制数据库,因为它针对这种数据进行了优化,因此 更快。
他们甚至明确地说:
请注意针对CSV进行的查询 导入SQL数据库的数据可以 需要几秒钟。如果 性能是一个问题,二进制 格式更快,可以处理 每秒数千次查找。
另外,他们甚至会让你the code来查询这个数据库。
我在具有中等流量的生产网站中使用它,过滤每个请求,没有性能问题。
答案 1 :(得分:1)
假设您的IP地址是IPV4,您可以将它们存储在整数字段中。创建2个字段,一个用于范围的下限,另一个用于上限。然后确保将这些字段编入索引。搜索值时,只搜索值大于或等于下限的位置,并小于或等于上限。在尝试自己编写更复杂的东西之前,我会尝试这样简单的事情,这实际上并没有给出明显更快的结果。
答案 2 :(得分:0)
IPv4地址可以存储为四字节无符号整数(C#中的uint)。 IPv6地址可以是8字节无符号整数(C#中的ulong)。在SQL中创建适当宽度的列,然后检索并将它们存储在变量中。然后使用简单整数数学来检查所需的范围,假设范围实际上是连续的。
更精细的解决方案是创建一个IPAddress类,使您可以访问更熟悉的点分四边形结构,但在幕后它将完成与此处完全相同的操作。
答案 3 :(得分:0)
我从来没有尝试过这个,所以我的答案很简单,但我认为除非你打算存储你想要阻止的每一个IP(而不是范围或子网),否则实际上并不是你想要的。 /口罩)。我认为btree更适合,在这种情况下,只需继续使用您的常规数据库(许多数据库使用btree或同样好的数据结构实现)。我将IP的4个字节中的每个字节存储在一个单独的列中,以帮助按类A / B / C子网搜索“不关心”值等于NULL,但是没有理由不能存储它作为一个32位整数列,并对数字进行处理,以确定它应该落入哪个范围(在这种情况下,存储蒙蔽值会稍微有些棘手)。
答案 4 :(得分:0)
IPv6地址可以是8字节 无符号整数(C#中的ulong)
IPv6地址是128位(16字节),而不是建议的8位。 我正在努力解决IP范围的这个问题。
我希望尝试填充或十六进制字符串,然后执行<和>比较
答案 5 :(得分: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
应该找到编号最大的网络号码&lt; = IP号码,然后通过一个简单的检查来确定该IP地址是否在其中。
如果在IPNumber上有传统索引,它应该是有效的。
对于IPv6,类型不同,但原理是相同的。
答案 6 :(得分:0)
对于IPv4,通常DBA会推荐4个tinyint字段,但是你正在做范围,这更适合以前提供的整数存储解决方案。在这种情况下,您将存储该范围的起始IP地址和结束IP地址。然后进行比较是一件简单的事情。