Почему сортировка записей в таблице не соответствует кластеризованному индексу?

Я готовился к интервью и только что пришел на эти вещи.

Я выполнил следующие операторы:

create table trial
(
    Id int not null,
    Name varchar(10)
)

alter table trial add constraint unq unique clustered (Name)

alter table trial add constraint pk primary key nonclustered(Id)

insert into trial values (1,'a'),(3,'d'),(5,'b'),(2,'c')

select * from trial

Результат показан здесь:

введите здесь описание изображения

Мой вопрос: почему результат не сортируется по столбцу имени, поскольку столбец имени имеет кластеризованный индекс?

Результат:

1 a
2 c
3 d
5 b

Как использовать индекс для физической сортировки таблицы?


person Sagar    schedule 26.05.2016    source источник
comment
Отметьте используемые СУБД. (Индексы всегда более или менее специфичны для продукта.)   -  person jarlh    schedule 26.05.2016
comment
Версия для разработчиков MS SQL 2014   -  person Sagar    schedule 26.05.2016
comment
Прочтите эту статью по теме. blogs.msdn .microsoft.com/conor_cunningham_msft/2008/08/27/   -  person Sean Lange    schedule 26.05.2016


Ответы (2)


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

введите здесь описание изображения

Вы можете принудительно использовать кластеризованный индекс:

SELECT * FROM TRIAL WITH (INDEX(UNQ))

И вы, вероятно, получите:

введите здесь описание изображения

и набор результатов:

Id  Name
1   a
5   b
2   c
3   d

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

Я скопирую фрагмент из книги Exam 70-461: Querying Microsoft SQL Server 2012, где вы можете получить хорошее объяснение:

Может показаться, что вывод отсортирован по empid, но это не гарантируется. Что может быть более запутанным, так это то, что если вы повторно запускаете запрос, кажется, что результат продолжает возвращаться в том же порядке; но опять же, это не гарантировано. Когда механизм базы данных (в данном случае SQL Server) обрабатывает этот запрос, он знает, что может возвращать данные в любом порядке, поскольку нет явных инструкций для возврата данных в определенном порядке. Возможно, из-за оптимизации и других причин ядро ​​базы данных SQL Server на этот раз решило обрабатывать данные определенным образом. Есть даже некоторая вероятность того, что такой выбор будет повторяться, если физические обстоятельства останутся прежними. Но есть большая разница между тем, что может произойти из-за оптимизации и других причин, и тем, что на самом деле гарантировано.

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

Короче говоря, это невозможно переоценить: запрос, который не содержит явных инструкций для возврата строк в определенном порядке не гарантирует порядок строк в результате. Когда вам действительно нужна такая гарантия, единственный способ предоставить ее — добавить в запрос предложение ORDER BY, и этому посвящен следующий раздел.

РЕДАКТИРОВАТЬ на основе комментариев:

Дело в том, что даже если вы используете кластеризованный индекс, он может возвращать неупорядоченный набор. Предположим, у вас есть физический порядок сгруппированных ключей, например (1, 2, 3, 4, 5). В большинстве случаев вы получите (1, 2, 3, 4, 5), но могут быть ситуации, когда оптимизатор решит выполнить параллельное чтение и скажет, что у него есть 2 параллельных чтения и он читает (1, 2, 3) и (4, 5). Теперь может случиться так, что сначала будет возвращено (4, 5), а затем может быть возвращено (1, 2, 3). Если у вас нет пункта order by, движок не будет тратить свои ресурсы на заказ этого набора и даст вам (4, 5, 1, 2, 3). Таким образом, это объясняет, почему вы всегда должны убедиться, что у вас есть пункт order by, когда вы хотите заказать.

person Giorgi Nakeuri    schedule 26.05.2016
comment
Спасибо .. за это разъяснение. На самом деле я знал, что физический порядок записей в таблице всегда соответствует кластеризованному индексу. .. Но я был неправ... - person Sagar; 27.05.2016
comment
@Sagar, нет, ты был прав в этом. Подробнее объясню в ответе. - person Giorgi Nakeuri; 27.05.2016
comment
Спасибо .. Я действительно доволен этим ответом. Параллельно читает... правильно. - person Sagar; 28.05.2016

Повторите: таблицы SQL представляют неупорядоченные наборы. Наборы результатов SQL неупорядочены, если только запрос не содержит условие order by.

Итак, если вы хотите, чтобы данные были в порядке, используйте order by:

select t.*
from trial t
order by t.name;

Если вам нужны результаты в определенном порядке, используйте order by. SQL Server имеет хороший оптимизатор. Если он может использовать индекс для запроса — чтобы избежать фактической сортировки — тогда он обычно будет использовать индекс.

person Gordon Linoff    schedule 26.05.2016
comment
да, я знаю.. почему записи в таблице не сортируются по кластеризованному индексу?? - person Sagar; 26.05.2016
comment
Извините, у вас нет возможности узнать, как записи сортируются в таблице. Вы можете только видеть, как записи возвращаются вам, когда вы их запрашиваете - и это чисто внутренняя неопределенная вещь SQL, если вы не запрашиваете указанный порядок. - person Arvo; 26.05.2016
comment
@Сагер. . . Проблема не в том, как сортируются таблицы. Вопрос в том, как работает запрос. Если бы вы сделали дамп данных страниц, вы, вероятно, обнаружили бы, что данные действительно упорядочены на страницах данных. Однако запрос не должен это учитывать. - person Gordon Linoff; 26.05.2016