Je suis tombé sur cette question lors d'une conversation Twitter avec Lukas Eder .
Bien que le comportement correct soit d'appliquer la clause ORDER BY à la requête la plus externe, car, ici, nous n'utilisons pas DISTINCT, GROUP BY, JOIN ou toute autre clause WHERE dans la requête la plus externe, pourquoi un SGBDR ne passerait-il pas simplement la les données entrantes telles qu'elles ont été triées par la requête interne?
SELECT *
FROM (
SELECT * FROM table ORDER BY time DESC
) AS t
Lorsque vous exécutez cet exemple sur PostgreSQL, au moins, vous obtenez le même plan d'exécution pour la requête interne et cet exemple de table dérivée, ainsi que le même jeu de résultats.
Donc, je suppose que le planificateur supprimera simplement la requête la plus externe car elle est redondante ou passera simplement par les résultats de la table interne.
Quelqu'un pense-t-il que ce n'est pas le cas?
la source
ORDER BY
plombinternepour une optimisation différente pour le groupe max .Réponses:
La plupart des bases de données sont assez claires sur le fait qu'un
ORDER BY
dans une sous-requête est soit:TOP
ouOFFSET .. FETCH
)OFFSET .. FETCH
ouLIMIT
)Voici un exemple tiré du manuel DB2 LUW (c'est moi qui souligne)
La formulation est assez explicite, tout comme celle de PostgreSQL :
D'après cette spécification, il peut être suivi que tout ordre résultant de la
ORDER BY
clause dans une table dérivée est simplement accidentel et peut coïncider par hasard avec votre ordre attendu (ce qu'il fait dans la plupart des bases de données dans votre exemple trivial), mais il serait imprudent de s'appuyer sur cette.Note latérale sur DB2:
En particulier, DB2 a une fonction moins connue appelée
ORDER BY ORDER OF <table-designator>
, qui peut être utilisée comme suit:Dans ce cas particulier, l'ordre de la table dérivée peut être explicitement réutilisé dans le plus externe SELECT
Note complémentaire sur Oracle:
Pendant des années, il a été une pratique dans Oracle pour implémenter la
OFFSET
pagination à l'aideROWNUM
, qui ne peut être raisonnablement calculée qu'après avoir commandé une table dérivée:On peut raisonnablement s'attendre à ce qu'au moins en présence d'
ROWNUM
une requête, les futures versions d'Oracle ne cassent pas ce comportement afin de ne pas casser à peu près tout l'héritage Oracle SQL, qui n'a pas encore migré vers le plus souhaitable etOFFSET .. FETCH
syntaxe standard lisible de SQL :la source
Meaningless: E.g. PostgreSQL
devrait vraiment être: « peu fiables », parce qu'il fait quelque chose de méchant. Les lignes sont triées dans la requête interne et cet ordre est conservé dans les niveaux de requête externes, sauf indication contraire ou si la réorganisation est opportune pour des opérations supplémentaires. Même si ce n'est qu'un détail d'implémentation, il n'est pas dénué de sens. Cela peut être utilisé pour une entrée triée pour agréger des fonctions. Le manuel laisse même entendre autant:Alternatively, supplying the input values from a sorted subquery will usually work.
ORDER BY
.Oui. Sans
ORDER BY
clause, l'ordre de sortie n'est pas défini et le planificateur de requêtes est tout à fait à sa portée de supposer que vous le savez et le comprenez.Il peut décider que parce que la requête externe ne spécifie pas d'ordre, il peut supprimer l'ordre dans la requête interne pour éviter une opération de tri, surtout s'il n'y a pas d'index cluster ou pas d'index du tout pour prendre en charge l'ordre. Si ce n'est pas le cas maintenant, cela pourrait le faire dans les futures versions.
Ne vous fiez jamais à un comportement indéfini. Si vous avez besoin d'une commande spécifique, donnez une
ORDER BY
clause à l'endroit approprié.la source
TOP 100%
afin que la requête actuelle ne soit pas portable, si cela doit être une priorité pour votre projet. Parce que Postgres obéit à l'ordre dans la requête interne maintenant n'implique pas qu'il le fera toujours à l'avenir (ou que les anciennes versions font, en fait), vous devriez donc éviter de vous fier au comportement au cas où.ORDER BY
est MariaDB: Pourquoi ORDER BY dans une sous-requête FROM est-il ignoré?C'est le problème même avec un comportement indéfini - fonctionne pour vous, fonctionne pour moi, reformate le disque dur en prod;)
Nous pouvons prendre du recul et dire que dans un sens, vous avez raison - il n'y a aucune raison terrestre pour laquelle un SGBDR sensé réorganiserait les lignes dans la sélection intérieure. Mais ce n'est pas garanti - ce qui signifie qu'il peut y avoir à l'avenir une raison, et les vendeurs sont libres de le faire. Cela signifie que tout code qui s'appuie sur ce comportement est à la merci d'un changement qu'un fournisseur pourrait apporter et qu'il n'aurait aucune obligation de publier, car il ne s'agit pas d'un changement de rupture par rapport à un PDV API.
la source
SELECT
sansORDER BY
vraiment n'est pas déterministe, et pas seulement en théorie ou parce que les données ont changé.)La réponse pour toutes les versions existantes de Postgres (que vous testiez) est: Non - pour cette requête particulière. L'ordre de tri est garanti.
Les gens du serveur SQL ne seront pas à l'aise avec cela car Microsoft n'autorise même pas les
ORDER BY
sous-requêtes. L'ordre de tri est néanmoins garanti pour cette simple requête dans Postgres.ORDER BY
est appliqué dans la sous-requête et la requête externe ne fait rien qui puisse changer l'ordre.Le manuel l'indique même dans le chapitre Fonctions d'agrégation :
Notez que cela n'est vrai que lorsque les niveaux de requête externes n'ajoutent pas d'opérations susceptibles de modifier l'ordre. Il n'est donc "garanti" que pour le cas simple, et ce n'est pas soutenu par la norme SQL. Postgres est libre de réorganiser si cela est opportun pour des opérations supplémentaires. En cas de doute, ajoutez un autre
ORDER BY
à l'extérieurSELECT
. (Dans ce cas, leORDER BY
bruit interne serait redondant pour cette simple requête.)la source
"table"
n'est pas une simple table de base mais une vue complexe ou une table partitionnée? Est-ce vrai également lorsque le plan est exécuté en parallèle? Est-ce vrai aussi dans Postgres 10? (Je demande seulement, je ne suis pas sûr de la réponse à aucune de ces questions.)