Я наткнулся на этот вопрос в беседе в Твиттере с Лукасом Эдером .
Хотя правильное поведение будет заключаться в применении предложения ORDER BY к самому внешнему запросу, поскольку здесь мы не используем DISTINCT, GROUP BY, JOIN или любое другое предложение WHERE в самом внешнем запросе, почему бы СУРБД просто не передать входящие данные как они были отсортированы по внутреннему запросу?
SELECT *
FROM (
SELECT * FROM table ORDER BY time DESC
) AS t
При запуске этого примера на PostgreSQL, по крайней мере, вы получаете один и тот же план выполнения как для внутреннего запроса, так и для этого примера производной таблицы, а также один и тот же набор результатов.
Итак, я предполагаю, что планировщик просто отбросит самый внешний запрос, потому что он избыточен, или просто пропустит результаты из внутренней таблицы.
Кто-нибудь думает, что это может быть не так?
источник
ORDER BY
приводит к различной оптимизации для групповых макс .Ответы:
Большинство баз данных совершенно ясно понимают, что
ORDER BY
подзапрос - это либо:TOP
илиOFFSET .. FETCH
)OFFSET .. FETCH
илиLIMIT
)Вот пример из руководства по DB2 LUW (выделено мое)
Формулировка довольно четкая, как и в PostgreSQL :
Из этой спецификации следует, что любой порядок, полученный в результате
ORDER BY
предложения в производной таблице, является просто случайным и может совпадать с вашим ожидаемым порядком (что он делает в большинстве баз данных в вашем тривиальном примере), но было бы неразумно полагаться на это.Дополнительное примечание по DB2:
В частности, DB2 имеет менее известную функцию под названием
ORDER BY ORDER OF <table-designator>
, которая может использоваться следующим образом:В этом конкретном случае упорядочение производной таблицы может быть явно использовано повторно во внешнем SELECT
Дополнительное примечание по Oracle:
В течение многих лет в Oracle практикуется использование
OFFSET
разбиения на страницыROWNUM
, которое может быть разумно рассчитано только после заказа производной таблицы:Можно разумно ожидать, что, по крайней мере, при наличии
ROWNUM
в запросе будущие версии Oracle не будут нарушать это поведение, чтобы не сломать практически весь существующий Oracle SQL, который еще не перешел на гораздо более желательный и читаемый стандартныйOFFSET .. FETCH
синтаксис SQL :источник
Meaningless: E.g. PostgreSQL
действительно должно быть: «ненадежным», потому что это что-то значит. Строки сортируются во внутреннем запросе, и этот порядок сохраняется на внешних уровнях запроса, если не указано иное, или переупорядочение не подходит для дополнительных операций. Даже если это просто деталь реализации, это не бессмысленно. Это можно использовать для отсортированного ввода в агрегатные функции. Руководство даже намекает так много:Alternatively, supplying the input values from a sorted subquery will usually work.
ORDER BY
.Да. Без
ORDER BY
предложения порядок вывода не определен, и планировщик запросов вполне может предположить, что вы это знаете и понимаете.Он может решить, что, поскольку внешний запрос не определяет порядок, он может отбросить порядок во внутреннем запросе, чтобы избежать операции сортировки, особенно если нет кластерного индекса или индекса вообще, чтобы поддерживать порядок. Если этого не произойдет сейчас, это может быть сделано в будущих версиях.
Никогда не полагайтесь на неопределенное поведение. Если вам нужен конкретный заказ, дайте
ORDER BY
пункт в соответствующем месте.источник
TOP 100%
чтобы текущий запрос не был переносимым, если это будет приоритетом для вашего проекта. Поскольку Postgres подчиняется порядку во внутреннем запросе сейчас, это не означает, что это всегда будет происходить в будущем (или что на самом деле старые версии), поэтому вы должны избегать полагаться на поведение на всякий случайORDER BY
является MariaDB: почему ORDER BY в подзапросе FROM игнорируется?Сама проблема с неопределенным поведением - работает для вас, работает для меня, переформатирует жесткий диск в prod;)
Мы можем сделать шаг назад и сказать, что в каком-то смысле вы правы - нет никаких земных причин, по которым любая здравомыслящая СУБД будет переставлять строки во внутреннем выборе. Но это не гарантировано - это означает, что в будущем может быть причина, и поставщики могут это сделать. Это означает, что любой код, основанный на этом поведении, зависит от изменений, которые может сделать поставщик, и которые он не обязан публиковать, поскольку это не является принципиальным изменением от API POV.
источник
SELECT
без»ORDER BY
действительно недетерминировано, и не только в теории или потому, что данные изменились.)Ответ для всех существующих на данный момент версий Postgres (которые вы тестировали): Нет - для этого конкретного запроса. Порядок сортировки гарантирован.
Людям на SQL-сервере это будет неудобно, поскольку Microsoft даже не допускает
ORDER BY
подзапросов. Тем не менее, порядок сортировки для этого простого запроса в Postgres гарантирован.ORDER BY
применяется в подзапросе, и внешний запрос не делает ничего, что могло бы изменить порядок.Руководство даже намекает так много в главе Агрегатные функции :
Обратите внимание, что это верно только тогда, когда внешние уровни запросов не добавляют операции, которые могут изменить порядок. Так что это «гарантировано» только для простого случая, и это не поддерживается стандартом SQL. Postgres может изменить порядок, если он подходит для дополнительных операций. В случае сомнений добавьте еще один
ORDER BY
к внешнемуSELECT
. (В этом случае внутренняя частьORDER BY
будет лишним шумом для этого простого запроса.)источник
"table"
это не простая базовая таблица, а сложное представление или секционированная таблица? Верно ли и то, что план имеет параллельное исполнение? Это правда и в Postgres 10? (Я только спрашиваю, я не уверен в ответе на любой из этих вопросов.)