2010-09-29 2 views
0

У меня есть база данных, содержащая адреса, по одному адресу на строку. Содержит каждый адрес в Великобритании, поэтому ~ 28 миллионов строк. Один из столбцов - «Улица», который я использую для выполнения поиска. В этом столбце есть неидеальный, некластеризованный индекс.TSQL Поиск большой индексированной базы данных с использованием LIKE

Однако у меня есть несоответствия со скоростью поиска.

select * from Postcodes where Street = 'London Road' 

Принимает ~ 1 с.

select * from Postcodes where Street like'London Road%' 

Также занимает около секунды.

declare @Street varchar(20) = 'London Road%' 
select * from Postcodes where Street like @Street 

Однако это утверждение, хотя и идентично второму, занимает около 40 секунд для запуска.

Я полностью потерял причину этой разницы в скорости. Есть идеи?

+0

Что тип данных Улица пожалуйста? – gbn

ответ

1

Проблема заключается в том, что MSSQLServer не может заранее знать, что будет содержаться в переменной @Street, поэтому он не может использовать индекс в столбце Street.

Если ваше заявление:

select * from Postcodes where Street = 'London'; 
select * from Postcodes where Street like 'London Road%'; 

Он может использоваться индекс по Street колонке, потому что он знает, что строка начинается с London.

Если ваше заявление:

select * from Postcodes where Street like @VariableName; 

Он не может использовать индекс, потому что с этим утверждением вы должны быть в состоянии сделать:

select * from Postcodes where Street like 'London%'; 
select * from Postcodes where Street like '%London%'; 

или любое другое допустимое значение для VariableName. Это типичная проблема в прекомпилированных операторах.

Что вы можете сделать, это использовать строку напрямую или не использовать параметры и изменить оператор как динамический оператор SQL в TSQL.

+0

Это не причина. Проблема заключается в том, что он не использует более узкий индекс, так как не оценивает значение переменной для определения селективности. Он все еще может добиваться успеха в поиске дикой карты. Только начало и конец диапазона охватывают весь индекс. –

1

Если вы заранее знаете, что вы никогда не будете иметь ведущие символы и на SQL Server 2008, вы можете попробовать

declare @Street varchar(20) = 'London Road%' 
SELECT * FROM 
Postcodes WITH (FORCESEEK) 
where Street like @Street 
Смежные вопросы