2010-05-03 8 views
6

Nous avons récemment découvert un problème de performances avec l'un de nos systèmes et je pense avoir le correctif, mais je ne suis pas certain que ma compréhension soit correcte.Est-ce que ma compréhension de "select distinct" est correcte?

Dans la forme la plus simple, nous avons un tableau blah dans lequel nous accumulons diverses valeurs basées sur un champ clé. La forme de base est:

recdate date 
rectime time 
system varchar(20) 
count  integer 
accum1 integer 
accum2 integer 

Il y a beaucoup plus accumulateurs que cela, mais ils sont tous de la même forme. La clé primaire est composée de recdate, rectime et system.

Lorsque des valeurs sont collectées dans la table, le nombre de recdate/rectime/system est incrémenté et les valeurs de cette clé sont ajoutées aux accumulateurs. Cela signifie que les moyennes peuvent être obtenues en utilisant accumN/count.

Maintenant, nous avons aussi une vue sur la table spécifiée comme suit:

create view blah_v (
    recdate, rectime, system, count, 
    accum1, 
    accum2 
) as select distinct 
    recdate, rectime, system, count, 
    value (case when count > 0 then accum1/count end, 0), 
    value (case when count > 0 then accum2/count end, 0) 
    from blah; 

En d'autres termes, la vue nous donne la valeur moyenne des accumulateurs plutôt que les sommes. Il s'assure également que nous n'obtenons pas de division par zéro dans les cas où le compte est zéro (ces enregistrements et existent et nous ne sommes pas autorisés à les supprimer, donc ne vous embêtez pas à me dire qu'ils sont des ordures - vous prêchez à la chorale).

Nous avons remarqué que la différence de temps entre la pratique:

select distinct recdate from XX 

varie considérablement selon que l'on utilise la table ou la vue. Je parle de la différence étant 1 seconde pour la table et 27 secondes pour la vue (avec 100K lignes). Nous avons en fait retrouvé le select distinct. Ce qui semble se passer, c'est que le SGBD charge actuellement toutes les lignes et les classe afin de supprimer les doublons. C'est juste, c'est ce que nous lui avons bêtement dit de faire. Mais je suis sûr que le fait que la vue inclue tous les composants de la clé primaire signifie qu'il est impossible d'avoir des doublons de toute façon. Nous avons validé le problème car, si nous créons une autre vue sans le distinct, il fonctionne à la même vitesse que la table sous-jacente. Je voulais juste confirmer ma compréhension qu'un select distinct ne peut pas avoir de doublons s'il inclut tous les composants clés primaires. Si c'est le cas, nous pouvons simplement changer la vue de manière appropriée.

Répondre

3

Oui, cela ne sert à rien de demander des résultats distinct lorsque tous les éléments de la clé primaire sont inclus. La contrainte de clé primaire de la table empêche déjà les doublons entre ces colonnes, mais votre DBMS traitera toujours les tuples pour s'assurer qu'ils sont distincts.

2

Si la vue est sélectionnée directement à partir d'une seule table et qu'un sous-ensemble de colonnes sélectionnées est unique sur la table, il s'ensuit que les lignes sélectionnées sont uniques en valeurs et distinct est redondant.

4

Dans ce cas, DISTINCT ne vous sert à rien car vos champs distincts sont déjà garantis uniques en raison de la contrainte PRIMARY KEY sur la table sous-jacente.Vous pourriez essayer de réécrire l'affichage comme:

create view blah_v ( 
    recdate, rectime, system, count, 
    accum1, 
    accum2 
) as select 
     recdate, rectime, system, count, 
     case when count > 0 then accum1/count else 0 end, 
     case when count > 0 then accum2/count else 0 end, 
     from blah; 

Partagez et appréciez.