Comparaison des performances entre l'utilisation de la fonction Join et Window pour obtenir les valeurs d'avance et de retard


11

J'avoir une table avec des rangées de 20m, et chaque rangée possède 3 colonnes: time, id, et value. Pour chacun idet time, il y a un valuepour le statut. Je veux connaître les valeurs de plomb et de retard d'un certain timepour un spécifique id.

J'ai utilisé deux méthodes pour y parvenir. Une méthode utilise join et une autre méthode utilise les fonctions de fenêtre lead / lag avec un index clusterisé sur timeet id.

J'ai comparé les performances de ces deux méthodes par le temps d'exécution. La méthode de jointure prend 16,3 secondes et la méthode de fonction de fenêtre prend 20 secondes, sans compter le temps de création de l'index. Cela m'a surpris car la fonction window semble être avancée alors que les méthodes de jointure sont en force brute.

Voici le code des deux méthodes:

Créer un index

create clustered index id_time
 on tab1 (id,time)

Méthode Join

select a1.id,a1.time
   a1.value as value, 
   b1.value as value_lag,
   c1.value as value_lead
into tab2
from tab1 a1
left join tab1 b1
on a1.id = b1.id
and a1.time-1= b1.time
left join tab1 c1
on a1.id = c1.id
and a1.time+1 = c1.time

Statistiques d'E / S générées à l'aide de SET STATISTICS TIME, IO ON:

Statistiques pour la méthode Join

Voici le plan d'exécution de la méthode join

Méthode de fonction de fenêtre

select id, time, value, 
   lag(value,1) over(partition by id order by id,time) as value_lag,
   lead(value,1) over(partition by id order by id,time) as value_lead
into tab2
from tab1

(La commande uniquement par timeenregistre 0,5 seconde.)

Voici le plan d'exécution de la méthode de la fonction Window

Statistiques d'E / S

[Statistiques pour la méthode de la fonction Fenêtre 4]


J'ai vérifié les données sample_orig_month_1999et il semble que les données brutes soient bien ordonnées par idet time. Est-ce la raison de la différence de performances?

Il semble que la méthode de jointure ait plus de lectures logiques que la méthode de fonction de fenêtre, alors que le temps d'exécution pour la première est en fait inférieur. Est-ce parce que le premier a un meilleur parallélisme?

J'aime la méthode de la fonction de fenêtre en raison du code concis, existe-t-il un moyen de l'accélérer pour ce problème spécifique?

J'utilise SQL Server 2016 sur Windows 10 64 bits.

Réponses:


11

Les performances en mode ligne relativement faibles des fonctions LEADet des LAGfenêtres par rapport aux jointures automatiques ne sont pas nouvelles. Par exemple, Michael Zilberstein a écrit à ce sujet sur SQLblog.com en 2012. Il y a beaucoup de frais généraux dans les opérateurs de plan Segment, Sequence Project, Window Spool et Stream Aggregate (répétés):

Section Plan

Dans SQL Server 2016, vous disposez d'une nouvelle option, qui consiste à activer le traitement en mode batch pour les agrégats de fenêtres. Cela nécessite une sorte d'index columnstore sur la table, même s'il est vide. La présence d'un index columnstore est actuellement requise pour que l'optimiseur considère les plans en mode batch. En particulier, il permet à l'opérateur en mode batch Window Aggregate beaucoup plus efficace.

Pour tester cela dans votre cas, créez un index columnstore vide non cluster:

 -- Empty CS index
CREATE NONCLUSTERED COLUMNSTORE INDEX dummy 
ON dbo.tab1 (id, [time], [value]) 
WHERE id < 0 AND id > 0;

La requête:

SELECT
    T1.id,
    T1.[time],
    T1.[value],
    value_lag = 
        LAG(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time]),
    value_lead =
        LEAD(T1.[value]) OVER (
            PARTITION BY T1.id
            ORDER BY T1.[time])
FROM dbo.tab1 AS T1;

Devrait maintenant donner un plan d'exécution comme:

Plan de magasin en ligne en mode batch

... qui pourrait bien s'exécuter beaucoup plus rapidement.

Vous devrez peut-être utiliser un OPTION (MAXDOP 1)ou un autre indice pour obtenir la même forme de plan lors du stockage des résultats dans un nouveau tableau. La version parallèle du plan nécessite un tri en mode batch (ou éventuellement deux), ce qui pourrait bien être un peu plus lent. Cela dépend plutôt de votre matériel.

Pour plus d'informations sur l'opérateur d'agrégation de fenêtres en mode batch, consultez les articles suivants d'Itzik Ben-Gan:

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.