IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Le RBAR peut donner de meillieure performance ?


Sujet :

Développement SQL Server

  1. #1
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut Le RBAR peut donner de meillieure performance ?
    En dépit du titre de ce billet, les questions que je me pose en fait sont en bas.

    J'ai souvent lu des avertissements contre le RBAR ainsi que le conseil d'éviter APPLY tant que se faire se peut
    Pourtant il m'est arrivé de noter un gain de performance très important en utilisant APPLY alors qu'un équivalent par jointure traditionnel était aussi possible.
    Malheureusement, il ne m'est pas possible de mettre ici certains exemples bien réels (et tout aussi concrets) que j'ai pu croisé.
    Mais je crois être parvenu à faire un petit script qui permet de tester un peu cela:

    Création de table

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
     
    	SET NOCOUNT ON
     
    	CREATE TABLE t20130712_tmp (
    		ID INT UNIQUE
    		, X INT IDENTITY
    	)
    	GO
     
    	CREATE TABLE t20130712_tmp2 (
    		ID INT
    		, X INT IDENTITY
    		, UNIQUE (ID, X)
    	)
    	GO
     
    	; WITH T(n) AS (
    		SELECT
    			ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    		FROM master.dbo.spt_values AS S
    	) 
    	, tally(n) AS (
    		SELECT
    			(T2.n - 1) * 100 + T1.n
    		FROM T AS T1
    		CROSS JOIN T AS T2
    		WHERE T1.n <= 100
    		AND T2.n <= 100
    	)
    	INSERT t20130712_tmp
    	SELECT n
    	FROM tally AS T1
    	WHERE n < 10000
    	GO
     
    	; WITH T(n) AS (
    		SELECT
    			ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    		FROM master.dbo.spt_values AS S
    	) 
    	, tally(n) AS (
    		SELECT
    			(T2.n - 1) * 100 + T1.n
    		FROM T AS T1
    		CROSS JOIN T AS T2
    		WHERE T1.n <= 100
    		AND T2.n <= 100
    	)
    	INSERT t20130712_tmp2
    	SELECT T1.n
    	FROM tally AS T1
    	CROSS JOIN T AS T2
    	WHERE T1.n < 10000
    	AND T1.n % 3 <> 0
    	AND T2.n < 1 + T1.n % 15
    	GO
    Tests

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
     
    	SET STATISTICS IO ON
    	SET STATISTICS TIME ON
     
    	SELECT
    		T1.*
    		, T2.X
    	FROM t20130712_tmp AS T1
    	OUTER APPLY (
    		SELECT
    			*
    		FROM t20130712_tmp2 AS T2
    		WHERE T2.ID = T1.ID
    		AND T1.X % 14 = 0
     
    		UNION ALL
     
    		SELECT
    			*
    		FROM t20130712_tmp2 AS T2
    		WHERE T2.ID = T1.ID + 1
    		AND T1.X % 14 = 1
     
    	) AS T2
    	ORDER BY T1.ID
     
    	SELECT
    		T1.*
    		, ISNULL(T2.X, T3.X) AS X
    	FROM t20130712_tmp AS T1
    	LEFT JOIN t20130712_tmp2 AS T2 ON (
    		T2.ID = T1.ID
    		AND
    		T1.X % 14 = 0
    	)
    	LEFT JOIN t20130712_tmp2 AS T3 ON (
    		T3.ID = T1.ID + 1
    		AND
    		T1.X % 14 = 1
    	)
    	ORDER BY T1.ID
     
    	SET STATISTICS TIME OFF
    	SET STATISTICS IO OFF
    Quand je vérifie les query plan, SQL Server indique clairement que la solution avec OUTER APPLY coûte plus que celle avec LEFT JOIN.
    D'ailleurs quand on regarde le IO, la solution avec APPLY fait beacoup plus de reads.
    Pourtant quand on se penche sur les durées la solution OUTER APPLY est légèrement plus rapide (et j'ai déjà fait face à des scénarios (impossibles a restitué ici) où la différence était énorme).

    Du coup, je me demande.

    • Est-ce que je donne trop d'importance aux durées et je sous-estime un autre point (peut-être à l'égard des LOCK) ?
    • Est-ce qu'il y a une autre et meilleure façon d'écrire le query sans APPLY ?
    Most Valued Pas mvp

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 763
    Points : 52 554
    Points
    52 554
    Billets dans le blog
    5
    Par défaut
    1) le coût estimé dans une jointure APPLY eut être très différent de la réalité. Donc comparer le plan avant et après
    2) la durée intrinsèque est une chose. La durée CPU en est une autre... En matière de concurrence il n'est pas toujours facile de trancher !

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Membre éprouvé

    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 448
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 448
    Points : 1 234
    Points
    1 234
    Par défaut
    SET STATISTICS TIME ON n'amène pas une vue complète des durées ?
    Que devrais-je avoir à l'esprit dans le cas présent afin de "trancher" ?
    Most Valued Pas mvp

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 763
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 763
    Points : 52 554
    Points
    52 554
    Billets dans le blog
    5
    Par défaut
    Citation Envoyé par Sergejack Voir le message
    SET STATISTICS TIME ON n'amène pas une vue complète des durées ?
    Oui, mais globale et très imprécise... En effet le time sharing des opérations de MS étant de 31,25 ms, vous aurez au plus une précision de 16 ms env. En dessous c'est zéro, au dessus c'est 31 env.
    De plus cela dépend de la concurrence à listant t auquel je lance ma commande... Donc refaire le test au moins 10 fois pour avoir une moyenne.
    En sus, sur un autre serveur le comportement peut être différent du faite des ressources (parallélisme des CPU, type des CPU, RAM..)

    Que devrais-je avoir à l'esprit dans le cas présent afin de "trancher" ?
    tester plutôt le nombre des IO...

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  5. #5
    Membre chevronné
    Inscrit en
    Août 2009
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Août 2009
    Messages : 1 073
    Points : 1 806
    Points
    1 806
    Par défaut
    Si on s'intéresse aux IO, alors il vaut mieux ne faire qu'un seul scan de la table 2 :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	SELECT
    		T1.*
    		,T2.X AS X2
    	FROM t20130712_tmp AS T1
    	LEFT JOIN t20130712_tmp2 AS T2 ON (T2.ID = T1.ID + T1.X % 14 AND T1.X % 14 IN (0,1))

Discussions similaires

  1. Utiliser Qt peut-il améliorer les performances ?
    Par dourouc05 dans le forum Qt
    Réponses: 29
    Dernier message: 31/08/2009, 19h03
  2. Peut-on donner automatiquement un nom à un enregistrement sous PDF ?
    Par nat44 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 22/07/2008, 14h51
  3. Peut on donner du relief a un Tlabel?
    Par Mickey.jet dans le forum Delphi
    Réponses: 2
    Dernier message: 05/06/2006, 18h59
  4. DB2 Peut-on remplacer le FETCH FIRST par plus performant?
    Par souellet dans le forum Langage SQL
    Réponses: 4
    Dernier message: 26/09/2005, 17h07

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo