Ускорение предложения ORDER BY с индексом - PullRequest
0 голосов
/ 24 августа 2018

У меня запрос с предложением ORDER BY, который является медленным из-за того, что в таблице более 11 миллионов строк.

Я могу значительно ускорить его, добавив кластерный индекс к столбцу в ORDER BY пункт.Однако программное обеспечение создает запрос на заказ по различным столбцам, в зависимости от пользовательских настроек.И вы не можете добавить более одного кластеризованного индекса в таблицу .

Мой вопрос: можно ли использовать некластеризованные индексы для повышения производительности ORDER BY?Или в кластерных индексах есть что-то особенное, что означает, что я не смогу быстро сортировать все столбцы?

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

Ответы [ 3 ]

0 голосов
/ 24 августа 2018

Только мои два цента.

Другой ответ великолепен, но не рассматривает идею удаления одного-единственного кластерного индекса. Для некоторых людей эта идея похожа на богохульство: D, но я видел ее в действии.

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

Если ваша таблица является таблицей кластеризованных индексов (большинство из них в SQL Server), все другие некластеризованные индексы становятся «вторичными» индексами и поэтому не столь эффективны. Если ваш запрос извлекает несколько строк (скажем, менее 10 тыс. Строк), вы не заметите «эффект вторичного индекса». Это когда запрос получает много строк, когда вы начинаете видеть эту проблему.

Почему они не так эффективны? Потому что все вторичные индексы не указывают на «идентификатор строки». Нет, потому что в кластеризованных индексированных таблицах нет идентификатора строки. Вторичные индексы указывают вместо key . И это может стать медленным, в зависимости от того, насколько плоха селективность вашего кластерного индекса.

Совершенно другая стратегия - которую стоит рассмотреть хотя бы для целей бенчмаркинга - полностью удалить кластерный индекс. Таким образом, все строки получат идентификатор строки, и внезапно все вторичные индексы станут истинными первичными индексами . Если я не ошибаюсь, вам нужно (заново) создать свою таблицу как non-clustered; может быть, вы можете просто изменить его, но я не уверен.

Если ваши запросы становятся медленными, я думаю, стоит рассмотреть эту стратегию, чтобы ускорить все ваши вторичные индексы.

0 голосов
/ 24 августа 2018

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

Идея в том, чтобы использовать покрытые запросы.В вашем случае я видел кластерные индексы, которые находятся в поле идентификатора, где некластеризованный индекс содержит первичный ключ (обычно составной первичный ключ), который включает столбец кластеризованного индекса.Оттуда SELECT на основе первичного ключа и порядка кластеризованного индекса (он уже отсортирован).

Обновление:

Я только что увидел план выполнения запроса.Вы получаете сканирование таблицы, что означает, что ни один из столбцов в предложении WHERE не содержится ни в первичном ключе, ни в индексе.Что касается оптимизатора, таблица работает в куче.Поэтому любой индекс, который вы добавляете и который содержит (то есть охватывает) столбцы, содержащиеся в предложении WHERE, вероятно, будет использоваться.В результате запрос будет возвращаться намного быстрее.

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

0 голосов
/ 24 августа 2018

Некластеризованные индексы могут абсолютно использоваться для оптимизации сортировки.Индексы - это, по сути, двоичные деревья поиска, что означает, что они содержат значения, отсортированные по порядку.

Однако, в зависимости от запроса, вы можете поместить SQL Server в головоломку.

Если у вас есть таблица с 100 миллионами строк, ваш запрос будет соответствовать 11 миллионам из них, как показано ниже, дешевле ли использовать индекс на category, чтобы выбрать строки и отсортировать результаты по name, или прочитать все 100 миллионов строк из индекса, предварительно отсортированного по name, а затем отфильтровать 89 миллионовиз них путем проверки category?

select ...
from product
where category = ?
order by name;

Теоретически, SQL Server может использовать индекс на name для чтения строк в порядке и использовать индекс наcategory эффективно фильтровать?Я скептическиЯ редко видел, чтобы SQL Server использовал несколько индексов для доступа к одной и той же таблице в одном запросе (при условии выбора одной таблицы, игнорирования объединений или рекурсивных CTE).Это должно было бы проверить индекс 100 миллионов раз.Индексы имеют высокие накладные расходы на поиск по индексу, поэтому они эффективны, когда один поиск сужает результирующий набор на много.

Не видя схемы, статистики и точного запроса, мне трудно сказать,это имеет смысл, но я ожидаю, что я обнаружу, что SQL Server будет использовать индекс для условия where и отсортирует результаты, игнорируя индекс для столбца сортировки.

Индекс для столбца сортировки может использоваться, если вывыбираем всю таблицу, хотя.Как select ... from product order by name;

Опять же, ваш пробег может варьироваться.Это предположение, основанное на прошлом опыте.

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