В SQL Server сортировка по короткой подстроке более эффективна, чем сортировка по всему длинному полю? - PullRequest
2 голосов
/ 13 февраля 2009

Рассмотрим следующий запрос SQL Server 2005/2008:

Select [UID], [DESC] From SomeTable Order By [Desc];

Если поле Desc довольно длинное (Varchar (125) с множеством записей> 70 символов) и вам не нужна строгая сортировка, было бы более эффективно сделать это:

Select [UID], [DESC] From SomeTable Order By Substring([Desc], 0, 20);

Преимущество заключается в том, что все сравнения довольно короткие (не более 20 символов). Недостатком является то, что он вызывает вызов Substring. В нынешних целях предположим, что вы не хотите помещать индекс в это поле, так как это не первичный ключ, а вышеприведенное является довольно редкой операцией. Какой вариант вы бы выбрали?

Примечание 2: Я спрашиваю здесь в основном из любопытства. В моем приложении Desc является индексированным полем, и я не использую подстроку. Однако я кратко рассмотрел возможность использования Substring, и мне пришло в голову, что я действительно не знаю, какой из вышеперечисленных подходов будет более эффективным.

Наконец, бонусный вопрос: правда ли, что использование Substring в индексированном поле заставит оптимизатор пропустить индекс, а действительно замедлит процесс? Я не думаю, что оптимизатор достаточно умен, чтобы использовать индекс, если используется подстрока (даже с нулевым основанием), но я слишком занят, чтобы проверить это прямо сейчас. Однако, если вы знаете по-другому, пожалуйста, поправьте меня!

Обновление / уточнение: Вы должны предполагать, что поле Desc не проиндексировано для целей исходного вопроса. Если он проиндексирован, ответ довольно прост.

Ответы [ 5 ]

1 голос
/ 13 февраля 2009

Что-то, что вы могли бы рассмотреть, это. При сортировке строк, используя хорошие оптимизированные алгоритмы, вам не нужно анализировать всю строку, чтобы выяснить, какая строка стоит первой. Рассмотрим две строки

F3294r02343232423
B3920490234324234

Вам нужно только проанализировать первый символ каждого, прежде чем вы поймете, что вторая строка должна стоять первой. Я не уверен, насколько это влияет на ваш конкретный набор данных, но вы должны подумать об этом.

В качестве теста вы можете захотеть создать копию своей таблицы с точно такими же данными и индексами, но обрезать поле, по которому вы сортируете, до 20 символов и посмотреть, есть ли заметное увеличение скорости из-за меньшее количество данных. Если есть значительное повышение производительности, вы можете пойти дальше того, что написал Роберт, и создать второй столбец с уже усеченными данными, чтобы вам не приходилось использовать функцию подстроки.

1 голос
/ 13 февраля 2009

Использование non-clustered index подразумевает неявное JOIN.

Сам индекс не содержит неиндексированных значений, он содержит только ссылки на блоки TABLE.

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

Как правило, INDEX SCAN WITH TABLE LOOKUP примерно в 10 раз дороже, чем TABLE SCAN.

Если вам нужны все результаты упорядоченного запроса, особенно как часть или более сложный запрос, подразумевающий nested loops, иногда эффективнее выполнить TABLE SCAN и отсортировать результаты.

Таблица должна быть отсортирована только один раз, и результаты сортировки будут сохранены и использованы повторно. В этом случае SUBSTRING может быть более эффективным.

Если вам нужно 5% упорядоченных результатов или меньше, то INDEX SCAN будет более эффективным, в этом случае вам нужно отсортировать по всему столбцу.

Кроме того, поиск по индексу всегда более отзывчив, поскольку вы получаете первые строки быстрее.

1 голос
/ 13 февраля 2009

Ваша последняя часть полностью соответствует действительности.

Что касается вопроса сортировки, быстрее ли сортировать по подстроке первых 20 символов. Если в строке указано 30 символов, ответ - нет, если 300 символов, то, возможно, да. Я не знаю, где будет граница. Но это будет проходить сортировку по символам. Если 21 символ, это быстрее, чтобы не иметь лишних издержек на подстроку и позволить ему проверить лишние 1 символ.

То, что вы могли бы сделать, - это иметь дополнительный столбец, который представляет собой усеченное описание, и вместо этого отсортировать по нему.

0 голосов
/ 13 февраля 2009

Вы сказали, что игнорируете тот факт, что [Desc] индексируется, однако, учитывая, что вы говорите, что он индексируется и предполагается, что [UID] является PK, и при использовании Clustered Index ваш запрос "покрывается" индексом на [Desc], и, таким образом, SQL будет читать записи в порядке индекса ... поэтому установка SUBSTRING заставит его выполнить дополнительный шаг для сортировки по первым 20 символам, тогда как они уже были прочитаны в отсортированном порядке

правда ли, что использование подстроки в индексированном поле заставит оптимизатор пропустить индекс и действительно замедлит работу

Обычно да, если поле находится в предложении WHERE. Любая функция, примененная к полю в предложении where, может заставить оптимизатор пропустить индексы. Вообще говоря.

0 голосов
/ 13 февраля 2009

Я так не думаю. В этом случае вызов функции вызовет наибольший ущерб производительности. И да, функции, скорее всего, заставят оптимизатор избегать индексов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...