既然你已經對網址列的索引,我的猜測是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大師本身,也許是我的測試方法是不是最準確的/有用的,但主題很有意思至於不懂事的用戶端優化與該「黑匣子」 。
我懷疑url列上有索引嗎? – 2012-01-11 12:24:59
Eugen Rieck請看這張圖片:http://img62.imageshack.us/img62/589/exampleimage.png – MonsterMMORPG 2012-01-11 12:29:09
這看起來很奇怪 - 查詢計劃顯示可忽略不計的CPU,一些I/O成本(這是我的意思期望)。 CPU是否使用用戶空間或內核? – 2012-01-11 12:36:57