Поскольку у вас уже есть индекс для столбца Url, я предполагаю, что это SELECT (get pageid), тогда, если он не существует, INSERT (новый URL) - это то, что заставляет процессор работать на максимуме.Если у вашего сканера есть несколько потоков, вы можете облагать налогом механизмы параллелизма / блокировки в SQL на tblPages.
Что касается вашего конкретного вопроса, я бы использовал CHECKSUM (crc) вместо HASHBYTES (md).CHECKSUM работает быстрее, он возвращает INT вместо VARBINARY, поэтому индексирование будет проще / быстрее.
Однако именно потому, что CHECKSUM возвращает INT, он склонен к конфликтам, поэтому вам также следует искать URL какИ предложение.
SELECT PageId FROM tblPages WHERE HashedUrl=CHECKSUM(@url) AND PageUrl=@url
Теперь ТОЛЬКО поместите индекс столбца в HashedUrl (не PageUrl).Индекс должен быть НЕ УНИКАЛЬНЫМ из-за возможности коллизий.Это даст вам самые быстрые INSERT и SELECT, пока вы не начнете добираться до количества строк таблицы, превышающего 4 миллиарда, и в этом случае количество коллизий INT CHECKSUM вызовет много частичных сканирований таблицы в неиндексированном столбце PageUrl.
ОБНОВЛЕНИЕ
Вот простой тестовый код, который я использовал
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 мсек "vs" истекшее время = 10318 мс ", однако, более медленные (-30%) ВЫБОРЫ" истекшее время = 37 мс "vs" истекшее время = 28 мс ".
Еще одна интересная заметка - выне может "правильно" УКАЗАТЬ поле URL VARCHAR, потому что длина (в соответствии со спецификацией http ~ 4 КБ) будет превышать 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 как таковой, возможно, мой метод тестирования не самыйточный / полезный, но тема очень интересная с точки зрения нецелесообразной оптимизации на стороне пользователя по сравнению с «черным ящиком».