Когда вы создаете индекс для столбца или количества столбцов в MS SQL Server (я использую версию 2005), вы можете указать, что индекс для каждого столбца будет либо по возрастанию, либо по убыванию. Мне трудно понять, почему этот выбор вообще существует. Разве поиск не будет таким же быстрым при использовании методов двоичной сортировки? Какая разница, какой порядок я выберу?
sql
sql-server
optimization
indexing
Джошуа Кармоди
источник
источник
Ответы:
В первую очередь это имеет значение при использовании составных индексов:
CREATE INDEX ix_index ON mytable (col1, col2 DESC);
может использоваться для:
SELECT * FROM mytable ORDER BY col1, col2 DESC
или:
SELECT * FROM mytable ORDER BY col1 DESC, col2
, но не для:
SELECT * FROM mytable ORDER BY col1, col2
Индекс по одному столбцу можно эффективно использовать для сортировки обоими способами.
Подробнее читайте в статье в моем блоге:
Обновить:
Фактически, это может иметь значение даже для индекса с одним столбцом, хотя это не так очевидно.
Представьте себе индекс столбца кластеризованной таблицы:
CREATE TABLE mytable ( pk INT NOT NULL PRIMARY KEY, col1 INT NOT NULL ) CREATE INDEX ix_mytable_col1 ON mytable (col1)
Индекс on
col1
сохраняет упорядоченные значенияcol1
вместе со ссылками на строки.Поскольку таблица кластеризована, ссылки на строки фактически являются значениями
pk
. Они также упорядочены в пределах каждого значенияcol1
.Это означает, что листья индекса фактически упорядочены
(col1, pk)
, и этот запрос:SELECT col1, pk FROM mytable ORDER BY col1, pk
не нуждается в сортировке.
Если мы создадим индекс следующим образом:
CREATE INDEX ix_mytable_col1_desc ON mytable (col1 DESC)
, то значения
col1
будут отсортированы по убыванию, но значенияpk
внутри каждого значенияcol1
будут отсортированы по возрастанию.Это означает, что следующий запрос:
SELECT col1, pk FROM mytable ORDER BY col1, pk DESC
может быть подан ,
ix_mytable_col1_desc
но неix_mytable_col1
.Другими словами, столбцы, составляющие a
CLUSTERED INDEX
в любой таблице, всегда являются конечными столбцами любого другого индекса в этой таблице.источник
Для истинного индекса с одним столбцом это не имеет большого значения с точки зрения оптимизатора запросов.
Для определения таблицы
CREATE TABLE T1( [ID] [int] IDENTITY NOT NULL, [Filler] [char](8000) NULL, PRIMARY KEY CLUSTERED ([ID] ASC))
Запрос
SELECT TOP 10 * FROM T1 ORDER BY ID DESC
Использует упорядоченное сканирование с направлением сканирования,
BACKWARD
указанным в плане выполнения. Однако есть небольшая разница в том, что в настоящее времяFORWARD
можно распараллеливать только сканирование.Однако это может иметь большое значение с точки зрения логической фрагментации . Если индекс создается с ключами в порядке убывания, но к новым строкам добавляются значения ключей в порядке возрастания, вы можете получить каждую страницу вне логического порядка. Это может серьезно повлиять на размер операций ввода-вывода при сканировании таблицы, и она не находится в кеше.
Посмотреть результаты фрагментации
avg_fragmentation avg_fragment name page_count _in_percent fragment_count _size_in_pages ------ ------------ ------------------- ---------------- --------------- T1 1000 0.4 5 200 T2 1000 99.9 1000 1
для сценария ниже
/*Uses T1 definition from above*/ SET NOCOUNT ON; CREATE TABLE T2( [ID] [int] IDENTITY NOT NULL, [Filler] [char](8000) NULL, PRIMARY KEY CLUSTERED ([ID] DESC)) BEGIN TRAN GO INSERT INTO T1 DEFAULT VALUES GO 1000 INSERT INTO T2 DEFAULT VALUES GO 1000 COMMIT SELECT object_name(object_id) AS name, page_count, avg_fragmentation_in_percent, fragment_count, avg_fragment_size_in_pages FROM sys.dm_db_index_physical_stats(db_id(), object_id('T1'), 1, NULL, 'DETAILED') WHERE index_level = 0 UNION ALL SELECT object_name(object_id) AS name, page_count, avg_fragmentation_in_percent, fragment_count, avg_fragment_size_in_pages FROM sys.dm_db_index_physical_stats(db_id(), object_id('T2'), 1, NULL, 'DETAILED') WHERE index_level = 0
Можно использовать вкладку пространственных результатов, чтобы проверить предположение, что это связано с тем, что в обоих случаях на более поздних страницах есть восходящие значения ключей.
SELECT page_id, [ID], geometry::Point(page_id, [ID], 0).STBuffer(4) FROM T1 CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% ) UNION ALL SELECT page_id, [ID], geometry::Point(page_id, [ID], 0).STBuffer(4) FROM T2 CROSS APPLY sys.fn_PhysLocCracker( %% physloc %% )
источник
Порядок сортировки имеет значение, когда вы хотите получить много отсортированных данных, а не отдельные записи.
Обратите внимание, что (как вы предполагаете в своем вопросе) порядок сортировки обычно гораздо менее важен, чем то, какие столбцы вы индексируете (система может считывать индекс в обратном порядке, если порядок противоположен тому, который она хочет). Я редко задумываюсь о порядке сортировки индекса, в то время как меня мучают столбцы, охватываемые индексом.
@Quassnoi - отличный пример того, когда это действительно важно.
источник