Индексы помимо кластеризованных и некластеризованных
В прошлый раз мы говорили о двух наиболее распространенных типах индексов - кластеризованных и некластеризованных. В эпизоде этой недели мы собираемся потратить всего параграф или два на другие типы индексов, начиная с покрывающих индексов.
Фильтруемые индексы
Предположим, что мы огромный интернет-магазин, и мы постоянно добавляем записи в нашу таблицу dbo.Orders, когда заказчики размещают заказы. Нам нужно запросить заказы, которые еще не были обработаны, например:
SELECT OrderNumber FROM dbo.Orders WHERE OrderProcessed = 0
Подавляющее большинство записей Orders будет иметь OrderProcessed = 1, потому что мы храним всю нашу историю заказов в этой таблице. Если мы создадим индекс в поле OrdersProcessed, у него будет много данных, но мы никогда не будем запускать запросы, чтобы найти OrderProcessed = 1. Начиная с SQL Server 2008, мы можем создать индекс с предложением WHERE:
CREATE INDEX IX_OrderStatus ON dbo.Orders (OrderNumber) WHERE OrderProcessed = 0
Фильтруемые индексы кажутся удивительными на первый взгляд, но у них есть много подводных камней.
Покрывающие индексы
Покрывающие индексы на самом деле не являются индексом другого типа - это термин, который используется в сочетании с запросом и индексом. Если у меня есть такой запрос:
SELECT FirstName, LastName, PhoneNumber FROM dbo.People WHERE LastName = 'Ozar'
И если у меня есть этот индекс:
CREATE INDEX IX_LastName_Includes ON dbo.People (LastName) INCLUDE (FirstName, PhoneNumber)
Затем индекс охватывает все поля, необходимые для запуска этого запроса. SQL Server начнет поиск всех Ozars по фамилии, а затем индекс добавляет поля FirstName и PhoneNumber. SQL Server не должен возвращаться к кластеризованному индексу, чтобы получить нужные мне результаты. Это ведет к более быстрым запросам, а также меньшему количеству конфликтов, что делает кластеризованный индекс (и другие некластеризованные индексы) свободными для использования другими запросами.
Покрывающие индексы наиболее эффективны, когда у вас очень частые запросы, которые постоянно читают данные, и они вызывают блокирующие проблемы или тяжелый ввод-вывод.
Полнотекстовый индекс
Предположим, у нас есть таблица, называемая dbo.MoviePlots, и у нее есть поле Description, в которое мы помещаем сюжет каждого фильма. Мы знаем, что нам понравился фильм, в котором парень боялся змей, но мы не можем вспомнить точную таблицу. Мы могли бы написать следующий запрос:
SELECT * FROM dbo.MoviePlots WHERE Description LIKE '%snakes%'
Но это было бы не очень эффективно. SQL Server должен будет посмотреть описание каждого фильма и прокрутить все слова по одному символу за раз, ища змей. Даже если мы проиндексируем поле «Описание», нам все равно придется сканировать каждую строку.
Полнотекстовые индексы разбивают текстовое поле типа «описание» на слова, а затем сохраняют список слов в отдельном индексе. Они работают быстро, если вам нужно искать конкретные слова, но только до тех пор, пока вы переписываете свой запрос, чтобы использовать команды полнотекстового поиска, например:
SELECT * FROM dbo.MoviePlots WHERE CONTAINS(Description, 'snakes')
Вы даже можете делать забавные вещи, такие как поиск синонимов или вариаций слова. Чтобы узнать больше о полнотекстовой индексации, ознакомьтесь с:
- Books Online on Full Text Indexing - серьезно, прекратите смеяться, руководство действительно хорошее. Эта ссылка предназначена для SQL 2014/2012, но имейте в виду, что с 2008 по 2012 год были изменения.
- Understanding Full Text Indexing by Robert Sheldon - охватывает SQL Server 2008, а также различия между 2005 и 2008 (которые были огромными).
XML индексы
Вы можете хранить XML-данные изначально в таблицах SQL Server, используя XML-поля. SQL Server осведомлен о содержании - в том смысле, что SQL Server знает, что контент является допустимым XML.
При запуске XML запросов SQL Server должен засучить рукава и парсить данные в формате XML. Это интенсивный процесс и рецепт медленной работы. Вместо этого мы можем создавать предварительно обработанные версии XML, чтобы мы могли быстро перейти к конкретным узлам или значениям.
- Primary and Secondary XML Indexes
- Selective XML Indexes - вместо того, чтобы тратить значения, которые мы никогда не используем, SQL Server 2012 может создать эквивалент фильтруемых индексов на XML.
Кучи
Кучи - это таблицы без кластеризованного индекса. Это таблицы, хранящиеся в случайном порядке, данные хранятся в любом старом месте, которое подходит. Когда вы хотите запросить кучу, SQL Server сканирует всю эту чушь.
Звучит плохо, да? В большинстве случаев это так - за исключением пары очень нишевых применений. Если у вас есть таблица только для журналов, то есть есть вставки, но никаких обновлений, удалений или выборов, тогда куча может быть быстрее. Если у вас есть промежуточная таблица в хранилище данных, в которой вы быстро вставляете много данных, а затем вам нужно все сразу вытащить, а затем удалить все, куча может быть быстрее. Просто убедитесь, что это действительно быстрее с учетом потребностей вашего приложения.
Если вам нравятся кучи, последняя попытка убедить вас в обратном: посмотрите отличное видео Кендры Литтл - Heaps: Performance, Maintenance, and Your Sanity.
Выбор правильных индексов для ваших приложений
В Dynamic Management Views (DMV) SQL Server представлено множество полезных инструментов, показывающих какие индексы используются, какие из них не используются, а какие SQL Server желал бы иметь. К сожалению, они не дают целостной картины - это лишь необработанные данные, которые нужно вручную комбинировать и интерпретировать. Мы поговорим об этом на предстоящих уроках, но вам нужно сначала знать основные понятия об индексах.
Чтобы узнать о ваших собственных индексах, запустите sp_BlitzIndex® для проверки работоспособности. Это абсолютно бесплатная хранимая процедура, которая диагностирует повторяющиеся индексы, кучи, блокировки, отсутствующие индексы, неиспользуемые индексы и многое, многое другое.