2009-01-19 125 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地址。然後做比較是一件簡單的事情。