Хотя интересно узнать, как можно объяснить, что вы часто видите один и тот же порядок, я хотел бы отметить, что никогда не стоит полагаться на неявный порядок, вызванный конкретной реализацией базового механизма базы данных. , Другими словами, приятно знать почему, но вы никогда не должны полагаться на это. Для 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
... .. .........
Как вы можете видеть, оно сильно отличается от того, когда мы в первый раз запускали этот запрос. (Похоже, что строки упорядочены по вторичному индексу, но у меня нет объяснения, почему так должно быть).
В любом случае, суть в том, что не стоит полагаться на неявный порядок. Можно придумать объяснения, почему можно соблюдать определенный порядок, но даже тогда вы не всегда можете предсказать его (как в последнем случае), не имея глубоких знаний о реализации и состоянии времени выполнения.