12
votes

SQL Distinct Keyword se tourbaisse sur les performances?

J'ai reçu une requête SQL qui utilise le mot-clé distinct. Lorsque j'ai essayé de courir la requête, il a fallu au moins une minute pour rejoindre deux tables avec des centaines de milliers d'enregistrements et renvoyer quelque chose.

J'ai ensuite sorti le distinct et est revenu en 0,2 seconde. Est-ce que le mot clé distinct fait vraiment des choses si mal? P>

Edit: Voici la requête P>


SELECT Distinct
c.username, o.orderno, o.totalcredits, o.totalrefunds,
o.recstatus, o.reason 

from management.contacts c 
join management.orders o
on (c.custID = o.custID)
where o.recDate > to_date('2010-01-01', 'YYYY/MM/DD')


6 commentaires

Pouvez-vous poster la requête actuelle? Dans mon expérience, l'ajout du mot clé distinct est souvent un hack pour corriger une requête mal écrite.


Franchement, je ne comprends pas réellement le but de la déclaration distincte, et le gars qui l'a écrit est devenu depuis longtemps ...


@Keikoku: La requête renvoie-t-elle un nombre différent de lignes avec / sans le distinct?


Je le laisse actuellement courir. C'est dans les 100 000+ et encore. Quoi qu'il en soit, quel est le but d'utiliser distinct quand il y a tellement de colonnes sélectionnées? Je ne peux tout simplement pas imaginer quand ça serait utile


@Keikoyu: Je soupçonne la même chose. Il semble que o.orderno pourrait suffire à faire chaque rangée unique, mais je ne connais évidemment pas vos données.


Je viens de me demander autour et certains ont mentionné qu'il est possible d'avoir des informations en double, mais vraiment, pas lorsque je jette dans toutes ces colonnes. Si la seule raison d'utiliser distincte est de renvoyer des résultats uniques, alors avoir deux ou trois colonnes (date, ordonnancement et nom) qui rendent l'impossibilité que des données en double soient suffisantes. En fait, peut-être que je devrais juste jeter dans la colonne qui ressemble à un numéro d'index ... Merci pour votre aide.


4 Réponses :


14
votes

Oui, comme en utilisant distinct sera (parfois selon un commentaire), les résultats doivent être commandés. Tri des centaines d'enregistrements prend du temps.

essayer groupe par Toutes vos colonnes, il peut parfois amener l'optimiseur de requête pour choisir un algorithme plus efficace (au moins avec Oracle, j'ai remarqué un gain de performance significatif).


3 commentaires

Juste une petite note latérale: elle ne sera pas nécessairement faite en commandant le résultat. La base de données est libre d'appliquer toute stratégie qu'elle pense convient à calculer les lignes distinctes. Oracle peut utiliser un index ou une hachage en fonction desquelles les colonnes doivent être distinctes. Les deux n'entraîneront pas une étape de tri. Mais si le tri est impliqué, cela pourrait bien être assez coûteux.


@A_HORSE_WITH_NO_NAME, (même plus petit côté pas sur une note latérale): Hash est un index aussi. Ainsi accordé, aucun tri n'est nécessaire, mais la construction d'un indice est.


@UnReason: Mais le hachage ne triera pas le résultat. C'est ce que je voulais souligner. Et une analyse d'index n'est pas nécessairement triée non plus non plus



3
votes

Objet de distinct est de préparer des enregistrements en double à partir du résultat défini pour toutes les colonnes sélectionnées.

  • Si l'une des colonnes sélectionnées est unique après la jointure, vous pouvez supprimer distinct.
  • Si vous ne le savez pas, mais vous savez que la combinaison des valeurs de la colonne sélectionnée est unique, vous pouvez laisser tomber distinct.

    En réalité, normalement, avec des bases de données correctement conçues, vous avez rarement besoin de distincte et dans les cas où vous le faites, c'est (?) évident que vous en avez besoin. Les SDBM ne peuvent toutefois pas laisser au hasard et doivent réellement créer une structure d'indexation pour l'établir.

    Normalement, vous trouvez des distincts partout où les gens ne sont pas sûrs des jointures et des relations entre les tables.

    Aussi, dans les classes lorsque vous parlez de bases de données relationnelles pures où le résultat doit être un ensemble approprié (sans éléments répétitifs = enregistrements), vous pouvez trouver qu'il est assez courant que les gens se distinguent pour garantir cette propriété à des fins de correction théorique . Parfois, cela rampe dans les systèmes de production.


2 commentaires

Est-ce une pratique courante de mettre distinct? J'ai pris un coup d'œil rapide dans certaines autres requêtes qui ont été écrits par la même personne et chacun d'entre eux utilise distinct, même s'il interroge une colonne qui conserve un numéro unique pour chaque entrée ajoutée à la table. Dans ce cas, le nombre n'est pas nécessaire, mais je devrais peut-être simplement le jeter pour garantir l'unicité.


Non, cela ne devrait pas être une pratique courante. Il tue la performance (à moins que la planificateur de requête puisse déterminer qu'il est superflu; Je ne sais pas à quel point l'oracle fait-il bien). Vous devez savoir de la cardinalité de vos jointures, de votre caractère unique des colonnes, des conditions que vous appliquez et des résultats que vous attendez si vous en avez besoin ou non.



0
votes

Vous pouvez essayer de faire un groupe par comme ceci: xxx

Vérifiez également si vous avez l'index sur O.RecDate


0 commentaires

7
votes

distinct définit toujours des cloches d'alarme à moi - cela signifie généralement une mauvaise conception de la table ou un développeur qui n'est pas sûr d'eux-mêmes. Il est utilisé pour éliminer les lignes en double, mais si les jointures sont correctes, elle devrait rarement être nécessaire. Et oui, il y a un coût important pour l'utiliser.

Quelle est la clé principale de la table des commandes? En supposant que c'est ordonnant que cela devrait être suffisant pour ne garantir aucun doublé. Si c'est autre chose, vous devrez peut-être faire un peu plus avec la requête, mais vous devriez en faire un objectif de supprimer ces distincts! ; -)

Aussi vous avez mentionné que la requête prenait un certain temps pour courir lorsque vous vérifiez le nombre de lignes - il peut souvent être plus rapide d'envelopper la requête complète dans "Sélectionner le nombre (*) de ()" surtout si vous obtenez De grandes quantités de rangées retournées. Juste pendant que vous testez évidemment. ; -)

Enfin, assurez-vous que vous avez indexé le bustid sur la table des commandes (et peut-être être recdate aussi).


1 commentaires

Oui, j'ai trouvé la raison pour laquelle Distinct a été utilisé, et c'est parce qu'ils voulaient rejoindre toutes les commandes et clients ensemble, mais ont fini par des commandes en double entraînant une raison quelconque, plusieurs enregistrements ont été apportés pour une seule commande contenant des informations différentes sans importance. cette requête. Mais le pointe du compte est agréable, il semble que 6 millions d'enregistrements soient 6 millions d'enregistrements.