2012-01-11 33 views
2

我正在寫我自己的網絡爬蟲。目前我直接以uri.absoluteurl存儲網址。所以當我查詢數據庫是否已經添加該網址或不,我直接查詢數據庫爲select pageid from mytable where url='absoluteurl'。我想這會對數據庫造成額外的壓力,因爲我的核心i 7 @ 4.5 ghz cpu幾乎一直處於100%。網絡爬蟲網址存儲在數據庫 - 快速URL查找 - 散列 - C#

所以我想到如果我還在數據庫中存儲URL的MD5散列並查找它們是否存在或不存在可以提高查找速度。

因此等待你的想法。爲了檢查這個url是否存在於數據庫中或者不是最好的方法?

C#4.0,MS-SQL 2008

例:http://img62.imageshack.us/img62/589/exampleimage.png

+1

我懷疑url列上有索引嗎? – 2012-01-11 12:24:59

+0

Eugen Rieck請看這張圖片:http://img62.imageshack.us/img62/589/exampleimage.png – MonsterMMORPG 2012-01-11 12:29:09

+0

這看起來很奇怪 - 查詢計劃顯示可忽略不計的CPU,一些I/O成本(這是我的意思期望)。 CPU是否使用用戶空間或內核? – 2012-01-11 12:36:57

回答

3

既然你已經對網址列的索引,我的猜測是SELECT(獲得的pageid),那麼如果它不存在INSERT (新的URL)是什麼導致CPU達到峯值。如果你的爬蟲有多個線程正在進行,你可能會在tblPages的SQL中對併發/鎖定機制徵稅。

關於您的具體問題,我會使用CHECKSUM(crc)而不是HASHBYTES(md)。 CHECKSUM更快,它返回一個INT而不是一個VARBINARY,所以索引會更容易/更快。

但是,正是由於CHECKSUM返回一個INT,所以很容易發生衝突,因此您還應該將URL搜索爲AND子句。

SELECT PageId FROM tblPages WHERE HashedUrl=CHECKSUM(@url) AND [email protected] 

現在只能放在HashedUrl(未PAGEURL)列索引。由於碰撞的可能性,指數必須是非唯一的。這將爲您提供最快的INSERT和SELECT,直到您開始獲得超過40億的錶行數,在這種情況下,INT CHECKSUM衝突的數量將導致未索引的PageUrl列上進行大量的部分表掃描。

UPDATE

下面是簡單的基準碼我用

GO 
/* NORMAL METHOD */ 
BEGIN 
SET STATISTICS TIME ON 
-- 
IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..#Store1')) 
BEGIN 
    DROP TABLE #Store1 
END 
-- Normal 
CREATE TABLE #Store1 (Id INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED, Data VARCHAR(4000)) 
CREATE UNIQUE CLUSTERED INDEX CIX_STORE1_DATA ON #Store1(Data) 
-- Help Create Data 
DECLARE @Data TABLE(Data VARCHAR(4000)) 
INSERT INTO @Data(Data) VALUES ('red.'), ('YELLOW/'), ('green'), ('.BLUE'), ('/violet'), ('PURPLE-'), ('-orange') 
-- The data set we'll use for testing 
INSERT INTO @Data 
    SELECT a.Data + b.Data + c.Data + d.Data + e.Data + f.Data + g.Data 
    FROM @Data a, @Data b, @Data c, @Data d, @Data e, @Data f, @Data g 
-- INSERTION TESTS 
PRINT('INSERT INTO NORMAL') 
INSERT INTO #Store1(Data) 
    SELECT Data FROM @Data 
-- SELECTION TESTS 
PRINT('SELECT FROM NORMAL') 
SELECT TOP 5000 d.Data, (SELECT s.Id FROM #Store1 s WHERE s.Data = d.Data) FROM @Data d 
-- 
SET STATISTICS TIME OFF 
END 
GO 
/* USING YOUR OWN CHECKSUM/HASH */ 
BEGIN 
SET STATISTICS TIME ON 
-- 
IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects WHERE ID = OBJECT_ID(N'tempdb..#Store2')) 
BEGIN 
    DROP TABLE #Store2 
END 
-- With Hash 
CREATE TABLE #Store2 (Id INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED, Hsh INT, Data VARCHAR(4000)) 
CREATE CLUSTERED INDEX CIX_STORE2_CRC ON #Store2(Hsh) 
-- Help Create Data 
DECLARE @Data TABLE(Data VARCHAR(4000)) 
INSERT INTO @Data(Data) VALUES ('red.'), ('YELLOW/'), ('green'), ('.BLUE'), ('/violet'), ('PURPLE-'), ('-orange') 
-- The data set we'll use for testing 
INSERT INTO @Data 
    SELECT a.Data + b.Data + c.Data + d.Data + e.Data + f.Data + g.Data 
    FROM @Data a, @Data b, @Data c, @Data d, @Data e, @Data f, @Data g 
-- INSERTION TESTS 
PRINT('INSERT INTO CHECKSUM/HASH') 
INSERT INTO #Store2(Hsh, Data) 
    SELECT CHECKSUM(Data), Data FROM @Data 
-- SELECTION TESTS 
PRINT('SELECT FROM CHECKSUM/HASH') 
SELECT TOP 5000 d.Data, (SELECT s.Id FROM #Store2 s WHERE Hsh = CHECKSUM(d.Data) AND Data = d.Data) FROM @Data d 
-- 
SET STATISTICS TIME OFF 
END 

結果(簡述)我的方法實現更快(+ 30%)中插入 「經過時間= 7339毫秒」 與「已過時間= 10318ms「,然而,選擇」經過時間= 37ms「與」經過時間= 28ms「相比較慢(-30%)。

另一個有趣的提示是你不能「正確地」INDEX一個URL VARCHAR字段,因爲長度(根據http spec〜4kb)將大於900字節(SQL 2008的最大允許密鑰大小)。雖然SQL僅爲此提供警告,但警告確實注意到一些INSERTS/UPDATES可能會失敗。

Warning! The maximum key length is 900 bytes. The index 'CIX_STORE1_DATA' has maximum length of 4000 bytes. For some combination of large values, the insert/update operation will fail. 

我不是一個SQL大師本身,也許是我的測試方法是不是最準確的/有用的,但主題很有意思至於不懂事的用戶端優化與該「黑匣子」 。

+0

我最近有類似的東西。不是網址上的索引可能會做一些聰明的事情,比如在內部使用哈希/校驗和來加快索引?我問了這個問題:http://stackoverflow.com/questions/7954602/creating-a-hashcode-for-use-in-a-database-ie-not-using-gethashcode大多數答覆是「不要插入哈希碼/校驗和,只是讓數據庫擔心它「。 – Chris 2012-01-11 13:20:22

+0

在stackoverflow上有很多「只是讓{x}擔心它」。當我們總是依靠別人解決我們可以輕易解決的問題時,我害怕創新和解決未來問題的能力。無論如何 - 爲這個評論添加我的兩分錢價值(不添加任何實際信息):做一個測試 - 用一個體面的樣本集兩種方式進行測試。如果我們認爲SQL沒有插入哈希就會更快,那麼GJ微軟 - 如果沒有,那麼GJ MonsterMMORPG讓你的應用程序更快,並且學習了另一個技巧。 – 2012-01-11 13:31:26

+0

非常感謝您的回答。現在我只抓取某些網站。所以我可以清楚地說,總的URL數量將永遠不會超過1000萬。我認爲碰撞機率在10米以內非常低。這不是非常關鍵的問題,所以我可以接受幾次碰撞,並且速度更快。 – MonsterMMORPG 2012-01-11 13:36:46