すでに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教祖それ自体がないんだけど。
URL欄にインデックスがあると思われますか? –
Eugen Rieckこの画像を見てください:http://img62.imageshack.us/img62/589/exampleimage.png – MonsterMMORPG
これは奇妙に見えます - クエリプランは無視できるCPU、I/Oコストを示しています。期待する)。 CPUはユーザーランドまたはカーネルを使用していますか? –