Récemment, j'expliquais à mes collègues l'importance d'avoir une colonne permettant de trier les données dans une table de base de données si cela est nécessaire, par exemple pour les données classées chronologiquement. Cela s'est révélé quelque peu difficile car ils pouvaient simplement réexécuter leur requête en apparence sans fin et cela renvoyait toujours le même ensemble de lignes dans le même ordre.
J'ai déjà remarqué cela et tout ce que je pouvais vraiment faire, c'est insister pour qu'ils me fassent confiance et ne pas simplement supposer qu'une table de base de données se comportera comme un fichier CSV ou Excel traditionnel.
Par exemple, exécuter la requête (PostgreSQL)
create table mytable (
id INTEGER PRIMARY KEY,
data TEXT
);
INSERT INTO mytable VALUES
(0, 'a'),
(1, 'b'),
(2, 'c'),
(3, 'd'),
(4, 'e'),
(5, 'f'),
(6, 'g'),
(7, 'h'),
(8, 'i'),
(9, 'j');
va créer un tableau avec un ordre conceptuel clair. La sélection de ces mêmes données de la manière la plus simple serait:
SELECT * FROM mytable;
Me donne toujours les résultats suivants:
id | data
----+------
0 | a
1 | b
2 | c
3 | d
4 | e
5 | f
6 | g
7 | h
8 | i
9 | j
(10 rows)
Je peux le faire encore et encore et il me renverra toujours les mêmes données dans le même ordre. Cependant, je sais que cet ordre implicite peut être rompu, je l'ai déjà vu, en particulier dans les grands ensembles de données, où une valeur aléatoire sera apparemment jetée au «mauvais» endroit lorsqu'elle est sélectionnée. Mais il m'est venu à l'esprit que je ne sais pas comment cela se produit ni comment le reproduire. J'ai du mal à obtenir des résultats sur Google, car la requête de recherche a tendance à renvoyer une aide générale sur le tri des jeux de résultats.
Donc, mes questions sont essentiellement les suivantes:
Comment puis-je prouver de façon concrète et concrète que l'ordre de retour des lignes d'une requête sans
ORDER BY
instruction n'est pas fiable, de préférence en provoquant et en montrant une ventilation de l'ordre implicite même lorsque la table en question n'est pas mise à jour ou modifiée ?Cela fait-il une différence si les données ne sont insérées qu'une seule fois en masse et ne sont plus jamais mises à jour?
Je préférerais une réponse basée sur les post-gres car c'est celle que je connais le mieux mais je suis plus intéressé par la théorie elle-même.
order by
clause à leurs requêtes? Essayent-ils d'économiser sur le stockage du code source? l'usure du clavier? le temps qu'il faut pour taper la clause redoutée?Réponses:
Je vois trois façons d'essayer de les convaincre:
Laissez-les essayer la même requête mais avec une table plus grande (plus de nombre de lignes) ou lorsque la table est mise à jour entre les exécutions. Ou de nouvelles lignes sont insérées et certaines anciennes sont supprimées. Ou un index est ajouté ou supprimé entre les exécutions. Ou la table est aspirée (en Postgres). Ou les index sont reconstruits (dans SQL Server). Ou la table est passée de cluster à un tas. Ou le service de base de données est redémarré.
Vous pouvez suggérer qu'ils prouvent que différentes exécutions renverront le même ordre. Peuvent-ils le prouver? Peuvent-ils fournir une série de tests prouvant que toute requête donnera le résultat dans le même ordre, quel que soit le nombre de fois où elle sera exécutée?
Fournissez la documentation des divers SGBD à ce sujet. Par exemple:
PostgreSQL :
SQL Server :
Oracle :
la source
ORDER BY
, qui garantira la commande, peu importe comment la table va changer ? Pourquoi ne pas ajouter un coffre-fort, qui ne fait pas de mal?C'est à nouveau l'histoire du cygne noir. Si vous n'en avez pas encore vu, cela ne signifie pas qu'ils n'existent pas. Espérons que dans votre cas, cela ne conduira pas à une autre crise financière mondiale, simplement à quelques clients mécontents.
La documentation Postgres le dit explicitement:
"Le système" dans ce cas comprend le démon postgres lui-même (y compris la mise en œuvre de ses méthodes d'accès aux données et l'optimiseur de requêtes), le système d'exploitation sous-jacent, la disposition logique et physique du stockage de la base de données, éventuellement même des caches CPU. Étant donné que vous, en tant qu'utilisateur de la base de données, n'avez aucun contrôle sur cette pile, vous ne devez pas vous fier à ce qu'elle continue de se comporter indéfiniment comme elle se comporte cette minute.
Vos collègues commettent l' erreur de généralisation hâtive . Pour réfuter leur argument, il suffit de montrer que leur supposition n'est fausse qu'une seule fois, par exemple par ce dbfiddle .
la source
Prenons l'exemple suivant, où nous avons trois tables liées. Commandes, utilisateurs et détails de la commande. OrderDetails est lié avec des clés étrangères à la table Orders et à la table Users. Il s'agit essentiellement d'une configuration très typique pour les bases de données relationnelles; sans doute tout le but d'un SGBD relationnel .
Ici, nous interrogeons la table OrderDetails où le UserID est 15:
La sortie de la requête ressemble à:
Comme vous pouvez le voir, l'ordre de sortie des lignes ne correspond pas à l'ordre des lignes dans la table OrderDetails.
L'ajout d'une explicite
ORDER BY
garantit que les lignes seront retournées au client dans l'ordre souhaité:Si l'ordre des lignes est impératif et que vos ingénieurs savent que l'ordre est impératif, ils ne devraient jamais vouloir utiliser une
ORDER BY
instruction, car cela pourrait leur coûter leur désignation s'il y avait une défaillance liée à un ordre incorrect.Un deuxième exemple, peut-être plus instructif, utilisant le
OrderDetails
tableau ci-dessus, où nous ne joignons aucun autre tableau, mais où nous avons simplement besoin de trouver des lignes correspondant à la fois à OrderID et à UserID, nous voyons le problème.Nous allons créer un index pour prendre en charge la requête, comme vous le feriez probablement dans la vie réelle si les performances sont importantes (quand n'est-ce pas?).
Voici la requête:
Et les résultats:
L'ajout d'une
ORDER BY
clause garantira très certainement que nous obtenons le bon tri ici également.Ces maquettes ne sont que de simples exemples où les lignes ne sont pas garanties d'être "en ordre" sans
ORDER BY
déclaration explicite . Il existe de nombreux autres exemples comme celui-ci, et comme le code du moteur de SGBD change assez fréquemment, le comportement spécifique peut changer avec le temps.la source
À titre d'exemple pratique, dans Postgres, l'ordre change actuellement lorsque vous mettez à jour une ligne:
Je ne pense pas que les règles de cette commande implicite existante soient documentées nulle part, soient définitivement sujettes à changement sans préavis et ne sont certainement pas un comportement portable sur les moteurs de base de données.
la source
pas exactement une démo, mais trop long pour un commentaire.
Sur les grandes tables, certaines bases de données effectueront des analyses parallèles entrelacées:
Si deux requêtes souhaitent analyser la même table et arriver presque en même temps, la première peut être à mi-chemin dans la table lorsque la seconde démarre.
La deuxième requête peut recevoir des enregistrements à partir du milieu de la table (à la fin de la première requête), puis recevoir les enregistrements à partir du début de la table.
la source
Créez un index cluster qui a le «mauvais» ordre. Par exemple, cluster sur
ID DESC
. Cela produira souvent l'ordre inverse (bien que cela ne soit pas garanti non plus).la source