Как сервер sql сортирует ваши данные? - PullRequest
10 голосов
/ 11 января 2010

Мне было интересно, как сервер sql сортирует данные. Я заметил, что если у меня есть таблица, в которой нет столбца «Id», и вы выбираете данные без «ORDER BY», то сервер sql не выполняет автоматическую сортировку по основному столбцу.

Кто-нибудь знает, по какому правилу sql server выполняет сортировку своих данных?

Ответы [ 4 ]

20 голосов
/ 11 января 2010

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

Мало того, что разные RDMBS-ы ведут себя по-разному, один конкретный экземпляр может вести себя по-разному из-за обновления (исправления). Мало того, что даже состояние программного обеспечения СУБД может оказать влияние: «теплая» база данных ведет себя не так, как «холодная», маленькая таблица ведет себя не так, как большая.

Даже если у вас есть справочная информация о реализации (например: «существует кластерный индекс, поэтому, скорее всего, данные будут возвращены в порядке кластерного индекса»), всегда есть вероятность, что существует другой механизм вы не знаете об этом, что приводит к тому, что строки возвращаются в другом порядке (ex1: «если другой сеанс только что выполнил полное сканирование таблицы с явным ORDER BY, результирующий набор мог быть кэширован; вернуть строки из кэша "; ex2:" a GROUP BY может быть реализовано путем сортировки данных, что влияет на порядок возврата строк "; ex3:" Если все выбранные столбцы находятся во вторичном индексе, который уже кэширован в памяти механизм может сканировать вторичный индекс вместо таблицы, скорее всего, возвращая строки по порядку вторичного индекса ").

Вот очень простой тест, который иллюстрирует некоторые из моих пунктов.

Во-первых, запуск SQL-сервера (я использую 2008). Создать эту таблицу:

create table test_order (
    id int not null identity(1,1) primary key
,   name varchar(10) not null 
)

Проверьте таблицу и убедитесь, что кластерный индекс был создан для поддержки primary key в столбце id. Например, в студии управления сервером sql вы можете использовать древовидное представление и перейти к папке индексов под вашей таблицей. Там вы должны увидеть один указатель с именем вроде: PK__test_ord__3213E83F03317E3D (Clustered)

Вставьте первую строку с этим утверждением:

insert into test_order(name)
select RAND()

Вставьте больше строк, повторив этот оператор 16 раз:

insert into test_order(name)
select RAND()
from   test_order

Теперь у вас должно быть 65536 строк:

select COUNT(*) 
from   test_order

Теперь выберите все строки без использования порядка:

select *
from   test_order

Скорее всего, результаты будут возвращены по порядку первичного ключа (хотя гарантии нет). Вот результат, который я получил (который действительно по порядку первичного ключа):

#      id    name
1      1     0.605831
2      2     0.517251
3      3     0.52326
.      .     .......
65536  65536 0.902214

(# - это не столбец, а порядковый номер строки в результате)

Теперь создайте вторичный индекс для столбца name:

create index idx_name on test_order(name)

Выбрать все строки, но получить только столбец name:

select name
from   test_order

Скорее всего, результаты будут возвращены в порядке вторичного индекса idx_name, поскольку запрос может быть решен только путем сканирования индекса (т. Е. idx_name является , охватывающим индекс). Вот результат, который я получил, который на самом деле порядка name.

#      name
1      0.0185732
2      0.0185732
.      .........
65536  0.981894

Теперь выберите все столбцы и все строки снова:

select * 
from test_order

Вот результат, который я получил:

#      id    name
1      17    0.0185732
2      18    0.0185732
3      19    0.0185732
...    ..    .........

Как вы можете видеть, оно сильно отличается от того, когда мы в первый раз запускали этот запрос. (Похоже, что строки упорядочены по вторичному индексу, но у меня нет объяснения, почему так должно быть).

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

4 голосов
/ 11 января 2010

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

Вы можете увидеть пример этого в этой статье .

0 голосов
/ 12 июня 2014

У меня был похожий опыт, когда SQL Server возвращал результаты, отсортированные иначе, чем я ожидал. Я обнаружил, что если вы укажете табличную подсказку в операторе выбора с именем кластеризованного индекса, вы получите результаты, упорядоченные так, как вы хотите:

select * from test_order WITH (INDEX([ClusteredIndexName]))
0 голосов
/ 11 декабря 2012

AS SQL основан на Set thoery, и Set не гарантирует какой-либо порядок, поэтому, если вы не укажете конкретный порядок подробно, порядок не будет гарантирован.

...