Поскольку у вас уже есть индекс на столбце Url, мое предположение является SELECT (получить PageId), то, если он не существует ВСТАВИТЬ (новый URL-адрес) является причиной того, что процессор достигает максимума. Если у вас искатель имеет несколько потоков, вы можете обменивать механизмы параллелизма/блокировки в SQL на tblPages.
Что касается вашего конкретного вопроса, я бы использовал 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 до тех пор, пока вы не начнете получать число строк таблицы более 4 миллиардов, и в этом случае количество столкновений 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 мс" против «прошло время = 10318 мс ", однако медленнее (-30%) ВЫБОР" Истекшее время = 37 мс "против" прошедшего времени = 28 мс ".
Еще одно интересное замечание: вы не можете «правильно» УКАЗАТЬ поле 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-адреса? –
Eugen Rieck, пожалуйста, посмотрите на это изображение: http://img62.imageshack.us/img62/589/exampleimage.png – MonsterMMORPG
Это выглядит странно - в плане запроса отображаются нерадивые CPU, некоторые затраты на ввод-вывод (это то, что я ожидать). Является ли процессор доступным для пользователя или ядром? –