2009-01-19 118 views
3

我有4个IP地址来源,我想将它们存储在SQL Server中,并允许在排除项目中对可以按来源国代码分类的范围进行排序按国家列出。如何存储和搜索IP地址

为此我有2张桌子。

IPAddressRange COUNTRYCODE

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

列表在db中的原因是为了方便存储。

我想要缓存然后使用客户端上的数据的原因是,我听说在搜索结构中搜索IP地址更快。所以,我认为我需要从数据库中获取列表,并将其存储在缓存中,以便快速搜索。

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

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

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

回答

3

我按照您所描述的完全按照国家/地区完成了过滤器。

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

他们甚至明确地说:

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

另外,他们甚至会给你the code来查询这个数据库。

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

0

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

一个更复杂的解决方案是创建一个IPAddress类,使您可以访问更为熟悉的虚线四边形结构,但在它下面它将完成与您在此处完全相同的操作。

+1

您需要16个字节的IPv6地址,而不是8个。 – Alnitak 2009-01-19 20:50:39

0

我从来没有尝试过这样,所以拿我的答案用一粒盐,但我认为一个trie并不是你想要的,除非你打算存储每一个你想阻止的IP(而不是范围或子网/掩码)。我认为btree会更适合,在这种情况下,请继续使用常规数据库(许多数据库使用btrees或同样好的数据结构实现)。我将每个IP的4个字节存储在一个单独的列中,以辅助以“无关”值等于NULL的A/B/C类子网搜索,但没有理由不能存储它作为一个单一的32位整数列并紧缩数字以找出它应该落入的范围(在这种情况下存储被掩盖的值将稍微复杂一些)。

+0

这些天没有A/B/C子网这样的事情。 – Alnitak 2009-01-19 20:58:33

1

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

+0

我不相信数据库可能会调用每个页面请求(可以说每秒1-5K次点击),与使用更加调整的查找IP的算法的排除IP列表的缓存列表相比,它的性能将会非常好。我只是不知道做到这一点的最佳方式。 – Coolcoder 2009-01-19 21:26:11

+0

我试过这个,太啰嗦太慢了。 – 2009-01-19 21:51:36

0

IPv6地址可以是一个八字节 无符号整数(在C#的ULONG)

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

我期待尝试填充或十六进制的字符串,只是做<和>比较

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,类型是不同的,但原理是相同的。

0

对于IPv4,通常DBA会推荐4个tinyint字段,但是您正在执行范围,这更适合于之前提供的整数存储解决方案。在这种情况下,您将存储该范围的起始IP地址和结束IP地址。然后做比较是一件简单的事情。