8
votes

Oracle SQL retourne des lignes de manière arbitraire lorsque la clause de "commande par" n'est utilisée

Peut-être que quelqu'un peut m'expliquer cela, mais lors de la recherche d'une table de données de Oracle, où plusieurs enregistrements existent pour une clé (disent un identifiant client), l'enregistrement qui apparaît en premier pour ce client peut varier s'il n'y a pas d'implicitement " Ordre par "Déclaration appliquant la commande en disant un autre champ tel qu'un type de transaction. Donc, l'exécution de la même requête sur la même table pourrait générer un ordre d'enregistrement différent de 10 minutes.

E.g., une exécution pourrait générer:

cust_id, transaction_type
123 A
123 B

sauf si une clause "ordre par transaction_type" est utilisée, Oracle pourrait renvoyer arbitrairement le résultat suivant la prochaine fois que la requête est exécutée:

cust_id, transaction_type
123 b de
123 A

Je suppose que j'avais l'impression qu'il y avait une commande par défaut de la base de données de lignes dans Oracle qui (peut-être) reflétait la commande physique sur le support de disque. En d'autres termes, un ordre arbitraire immuable et garantirait le même résultat lorsqu'une requête est réelle.

Cela a-t-il à voir avec l'optimiseur et la manière dont il décide où récupérer le plus efficacement les données?

Bien sûr, la meilleure pratique d'une perspective de programmation est de forcer quelle que soit la commande requise, j'étais juste un peu troublé par ce comportement.


2 commentaires

Je ne sais pas pourquoi, mais c'est une observation très amusante et surtout la partie «inverse» de celle-ci. :)


Vous n'êtes pas forcer commande, vous êtes choisir it.


8 Réponses :


10
votes

Il n'y a pas de commande par défaut, jamais. Si vous ne spécifiez pas ordre par , vous pouvez obtenir le même résultat le premier 10000 fois, puis il peut changer.

Notez que cela est également vrai même avec commander par pour des valeurs égales. Par exemple: xxx

si vous utilisez ordre par col2 , vous ne savez toujours pas si la rangée 1 ou 2 viendra en premier.


0 commentaires

22
votes

L'ordre des lignes retourné à l'application à partir d'une instruction est complètement arbitraire sauf indication contraire. Si vous voulez, besoin ou attendez-vous à revenir dans un certain ordre, c'est la responsabilité de l'utilisateur de spécifier une telle commande.

(CAVEAT: Certaines versions d'Oracle trieront implicitement les données de l'ordre croissant si certaines opérations ont été utilisées, telles que distinctes, union, moins, intersectez ou groupe par . Cependant, comme Oracle a mis en œuvre le tri de hachage, la nature du type des données peut varier et beaucoup de SQL s'appuyant sur cette caractéristique cassée.)


4 commentaires

+1 (ou plus précisément, beaucoup de SQL s'appuyant sur cette fonctionnalité étaient exposés comme ayant toujours été cassé )


Je souhaite presque parfois que la clause d'organisation était requise, afin que les gens se rendraient compte que par défaut dans Oracle, des tables sont organisées par le tas.


+1 - Mais cela nécessiterait que les personnes qui ont utilisé Oracle depuis des années (auto-incluses) devraient comprendre ce que la clause d'organisation de Create Table signifie (et merci de vous remercier, votre commentaire m'a poussé à y aller sur cette question).


Merci tout pour votre contribution. Je pense que la raison pour laquelle ce comportement était contre-intuitif pour moi, car je suis un statisticien et tire généralement des données dans un jeu de données SAS (qui ressemble à l'analogue d'une table en oracle.) Une fois que ces données sont tirées dans le format SAS, la commande ( Cependant, arbitraire initialement) est fixe car les données sont cachées sur le disque dans un ordre spécifique. Encore une fois, je ne dirais jamais que je m'appuie sur cet ordre par défaut dans ma programmation, juste qu'un morceau de code retournerait un résultat identique, même si aucune commande n'est spécifiée / forcée / demandée. Merci pour la clarification.



5
votes

La réponse simple est que la norme SQL indique qu'il n'y a pas d'ordre par défaut pour les requêtes qui n'ont pas de commande par déclaration, vous ne devriez donc jamais en supposer un.

La vraie raison serait probablement liée aux hayes attribuées à chaque ligne, car elle est tirée dans le jeu d'enregistrements. Il n'y a aucune raison d'assumer une hachage cohérente.


0 commentaires

7
votes

Image juste d'image des rangées dans une table comme des balles dans un panier. Les balles ont-elles une commande?

Je ne pense pas qu'il y ait un SGBD qui garantit une commande si la commande n'est pas spécifiée.

Certains peuvent retournent toujours les lignes dans l'ordre dans lequel ils ont été insérés, mais c'est un effet secondaire de la mise en œuvre.

Certains plans d'exécution pourraient causer le résultat que le résultat soit commandé même sans ordre, mais à nouveau, il s'agit d'un effet secondaire de mise en œuvre que vous ne devriez pas compter sur.


0 commentaires

6
votes

Si une commande par clause n'est pas présente, la base de données (non seulement l'oracle - toute base de données relationnelle) est libre de retourner des lignes dans n'importe quel ordre qu'il arrive à les trouver. Cela variera en fonction du plan de requête choisi par l'optimiseur.

Si l'ordre dans lequel les lignes sont renvoyées, vous devez utiliser une commande par clause. Vous pouvez parfois avoir de la chance et les lignes reviendront dans l'ordre de votre choix, mais il n'ya aucune garantie qu'un) vous aurez de la chance sur d'autres requêtes, et b) l'ordre dans lequel les rangées sont retournés demain seront les mêmes que l'ordre dans lequel ils sont retournés aujourd'hui.

En outre, les mises à jour du produit de base de données peuvent modifier le comportement des requêtes. Nous avons dû brouiller un peu lors de la mise à niveau de version majeure l'année dernière, lorsque nous avons constaté que Oracle 10 reprise un groupe par des résultats dans une ordonnance différente de l'oracle 9. Raison - Aucun ordre par clause.

commander par - lorsque l'ordre des données renvoyées compte vraiment.


1 commentaires

WOW, groupe en n'implique pas automatiquement l'ordre par. Merci, je vais me rappeler ça. Ceci est une autre instance où SAS SQL (appelée ProC SQL) diffère de Oracle SQL. Proc SQL ignorerait réellement une commande aussi superflue lorsqu'un groupe par clause est présent.



2
votes

Si vous n'utilisez pas la commande, la commande est arbitraire ; Cependant, dépend des aspects de stockage et de mémoire phisique. Donc, si vous répétez la même requête des centaines de fois en 10 minutes, vous obtiendrez presque le même ordre à chaque fois, car probablement rien ne change.

Les choses qui pourraient changer l'ordre "de l'ordre" sont:

  • le plan d'exécution - si c'est changé (vous avez pointu que)
  • insère et supprime sur les tables impliquées dans la requête.
  • Autres choses comme la présence à la mémoire des rangées. (D'autres requêtes sur d'autres tables pourraient influencer cela)

1 commentaires

Vous avez raison, pour la plupart, rien ne changera. Je viens de remarquer que dans une requête qui redevient un million de lignes, quelques milliers pourraient être différentes entre les courses successifs. Mon collègue qui est plus expert sur Oracle m'a expliqué que même si le code de code et les tables référencées sont statiques, les résultats pourraient être basés sur un certain nombre de facteurs de temps d'exécution, dont certains que vous avez mentionnés. Cela me donne en fait une nouvelle appréciation de la quantité d'oracle dans les coulisses pour maximiser la vitesse de récupération.



0
votes

Lorsque vous entrez dans la récupération de données parallèle, I / O n'est-il pas possible d'obtenir différentes séquences sur différentes exécutions, même sans modification des données stockées?

C'est-à-dire que dans un environnement multiprocession, l'ordre d'achèvement des filets parallèles est indéfini et peut varier avec ce qui se passe d'autre sur le même processeur partagé.


1 commentaires

Je ne pense pas qu'il y ait quelque chose à suggérer que la récupération de données parallèle est impliquée ici.



0
votes

Comme je suis nouveau sur le moteur de base de données Oracle, j'ai remarqué ce comportement dans mes instructions qui n'a pas de code par .

J'utilise Microsoft SQL Server depuis des années maintenant. SQL Server Moteur récupérera toujours les données commandées par "l'index en cluster" de la table, qui est fondamentalement l'indice principal principal. SQL Server insérera toujours de nouvelles données dans une commande séquentielle en fonction de l'index en cluster.

Ainsi, lorsque vous effectuez une sélection sur une table sans commande par SQL Server, il récupérera toujours les données commandées par la valeur principale.

commander par peut causer des frais généraux de performance graves, c'est pourquoi vous ne voulez pas l'utiliser à moins que vous n'êtes pas satisfait de la commande de résultats incohérents.

J'ai fini par une conclusion que, dans toutes mes requêtes Oracle, je dois utiliser commander par ou je finirai avec une ordonnance imprégnée qui affectera grandement mes rapports d'utilisateur final.


0 commentaires