2012-01-11 11 views
2

私は自分のWebクローラーを作成しています。現在私はuri.absoluteurlとして直接URLを保管しています。だから私は、そのURLがすでに追加されているかどうか私はデータベースを照会するときに直接select pageid from mytable where url='absoluteurl'としてデータベースを照会しています。私はこれがデータベースに余分なストレスを引き起こしていると思います。なぜなら私のコアは7 @ 4.5GHzのCPUがほぼ100%であるからです。データベースに保存されているWebクローラーURL - 高速URL参照 - ハッシュ - C#

私はデータベースにURLのmd5ハッシュを保存し、そのURLが存在するかどうかを調べることでルックアップのスピードを上げることができると思いました。

これについてあなたのアイデアを待っています。そのURLがデータベースに存在するかどうかをチェックするために、最良の方法は何ですか?

#4.0 C、MS-SQL 2008

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

+1

URL欄にインデックスがあると思われますか? –

+0

Eugen Rieckこの画像を見てください:http://img62.imageshack.us/img62/589/exampleimage.png – MonsterMMORPG

+0

これは奇妙に見えます - クエリプランは無視できるCPU、I/Oコストを示しています。期待する)。 CPUはユーザーランドまたはカーネルを使用していますか? –

答えて

3

すでにURL列にインデックスを持っているので、私の推測では、SELECT(pageidにし得る)、それが存在しない場合、INSERTがあります(新しいURL)が原因でCPUがピークに達しています。クローラに複数のスレッドがある場合は、tblPagesのSQLで同時実行性/ロックメカニズムに課税される可能性があります。

あなたの特定の質問に関して、私はハッシュビート(md)の代わりにCHECKSUM(crc)を使用します。 CHECKSUMは高速ですが、VARBINARYの代わりにINTを返しますので、索引付けが容易/高速になります。

しかし、正確にはCHECKSUMがINTを返すため、衝突する可能性が高いので、URLをAND句としても検索する必要があります。

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

ここでは、列インデックスをHashedUrl(PageUrlではなく)に配置します。衝突の可能性があるため、インデックスはNON-UNIQUEでなければなりません。これにより、最速のINSERTとSELECTが得られます。これは、40億を超える数のテーブル行を取得するまでになります。その場合、INT CHECKSUMの衝突によってインデックスされていないPageUrl列に対して多くの部分的なテーブルスキャンが発生します。

UPDATE

は、ここで私は私の方法は、(+ 30%)より高速を実現(簡潔で)

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 

結果を使用し、簡単なベンチマークコードだ「経過対 "= 7339ミリ秒経過時間" を挿入します時間= 10318ms "と遅く(-30%)、"経過時間= 37ms "と"経過時間= 28ms "を選択する。

もう1つ興味深いのは、長さ(http spec〜4kbによる)が900バイト(SQL 2008の最大許容キーサイズ)より大きいため、URL VARCHARフィールドを「正しく」INDEXできないことです。 SQLでは警告のみが表示されますが、INSERT/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

私は最近これに似たものを持っていました。より高速なインデックス作成のために内部的にハッシュ/チェックサムを使用するなど、賢明なことを行う可能性のあるURLのインデックスはありませんか?私はこの質問をしました:http://stackoverflow.com/questions/7954602/creating-a-hashcode-for-use-in-a-database-ie-not-using-gethashcodeほとんどの返信は「挿入しないでくださいハッシュコード/チェックサムは、データベースがそれを心配させるだけです "。 – Chris

+0

stackoverflowには「{x}を心配させる」ことがたくさんあります。私はイノベーションと未来のスキルを解決することを恐れています。私たちは、自分たちが容易に解決できる問題を解決するために常に他人に頼っています。とにかく - 実際の情報を追加することなく、このコメントに価値の2セントを追加する:適切なサンプルセットを使って両方の方法でテストする。 SQLがハッシュを挿入しなくても高速になるならば、GJマイクロソフト - もしそうでなければ、GJ MonsterMMORPGはあなたのアプリをもっと速くして、あなたのツールベルトのもう一つのトリックを学びました。 –

+0

ありがとうございました。今私は特定のウェブサイトだけをクロールしています。だから、私は明らかに総URLカウントは1000万を超えることはないと言うことができます。私は10mのうちに衝突の可能性が非常に低いと考えています。それは非常に重要な問題ではありませんので、私はいくつかの衝突を受け入れることができます。 – MonsterMMORPG

関連する問題