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

MS SQL Server Discussion :

La meilleure syntaxe


Sujet :

MS SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    480
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 480
    Par défaut La meilleure syntaxe
    Bonjour à tous,

    Ci-dessous 3 syntaxes différentes pour réaliser la même opération.

    Code SQL : 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
    /* REQUETE 1 */
    SELECT p.id_produit,p.nom,pcb.code_barre 
    FROM produit p 
    left outer join (
          select id_produit, max(ISNULL(code_barre, 0)) as code_barre 
          from Produit_code_barre
          group by id_produit
    ) pcb on pcb.id_produit = p.id_produit
    where  p.id_type_produit = 1
    	and p.id_produit < 5000
     
    /* REQUETE 2 */
    select p.id_produit,p.nom,pcb.code_barre from 
    produit p 
    outer apply (
    		select top 1 sub_pcb.id_produit, sub_pcb.code_barre
    		from Produit_code_barre sub_pcb 
    		where p.id_produit=sub_pcb.id_produit
    		order by sub_pcb.id_produit, sub_pcb.code_barre
    ) pcb
    where  p.id_type_produit = 1
    	and p.id_produit < 5000
     
    /* REQUETE 3 */
    SELECT id_produit,nom,code_barre 
    FROM (
    	SELECT p.id_produit,p.nom,pcb.code_barre, RANK() OVER (PARTITION BY p.id_produit ORDER BY pcb.code_barre DESC) AS RANK
    	FROM produit p 
    	LEFT OUTER JOIN Produit_code_barre pcb
    		ON pcb.id_produit = p.id_produit
    	WHERE p.id_type_produit = 1
    		AND p.id_produit < 5000
    ) T
    WHERE RANK = 1

    Après une rapide analyse, quand je lance les 3 requêtes dans l'estimateur de plan d'exécution, il m'annonce les consommations prévisionnelles suivantes :

    - Requête 1 : 15 %
    - Requête 2 : 67 %
    - Requête 3 : 18 %

    J'aurai pourtant dit, comme ça à l'instinct que la 3 ème requête serait la meilleure...

    Qu'en est-il en terme de lecture/écriture/cpu ? Cette répartition est-elle fiable avec 10 000 exécutions simultanées par exemples ?

    Pourquoi cet ordre là finalement ?

    A quoi sert cette 2ème syntaxe (et plus particulièrement l'instruction OUTER APPLY) si elle peut être remplacée par au moins 2 syntaxes plus performantes ?

    Merci d'avance pour vos suggestions/analyses

  2. #2
    Expert confirmé
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Par défaut
    Que donne l'exécution de ces 3 requêtes avec le plan d'exécution réel ?

    Donner nous aussi les informations relatives à l'activation des options de statistiques suivantes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SET STATISTICS IO ON;
    SET STATISTICS TIME ON;
     
    <requete>
     
    SET STATISTICS IO OFF;
    SET STATISTICS TIME OFF;
    ++

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    480
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 480
    Par défaut
    Voici ce que donne l'analyse dans l'ordre :


    (4989*ligne(s) affectée(s))
    Table 'Produit'. Nombre d'analyses 1, lectures logiques 720, lectures physiques 0, lectures anticipées 0, lectures logiques de données d'objets volumineux 0, lectures physiques de données d'objets volumineux 0, lectures anticipées de données d'objets volumineux 0.
    Table 'Produit_code_barre'. Nombre d'analyses 1, lectures logiques 29, lectures physiques 0, lectures anticipées 0, lectures logiques de données d'objets volumineux 0, lectures physiques de données d'objets volumineux 0, lectures anticipées de données d'objets volumineux 0.

    SQL Server \endash Temps d'exécution*:
    , Temps UC = 47*ms, temps écoulé = 345*ms.

    (4989*ligne(s) affectée(s))
    Table 'Produit_code_barre'. Nombre d'analyses 4989, lectures logiques 15952, lectures physiques 0, lectures anticipées 0, lectures logiques de données d'objets volumineux 0, lectures physiques de données d'objets volumineux 0, lectures anticipées de données d'objets volumineux 0.
    Table 'Produit'. Nombre d'analyses 1, lectures logiques 720, lectures physiques 0, lectures anticipées 0, lectures logiques de données d'objets volumineux 0, lectures physiques de données d'objets volumineux 0, lectures anticipées de données d'objets volumineux 0.

    SQL Server \endash Temps d'exécution*:
    , Temps UC = 31*ms, temps écoulé = 638*ms.

    (4989*ligne(s) affectée(s))
    Table 'Produit_code_barre'. Nombre d'analyses 1, lectures logiques 29, lectures physiques 0, lectures anticipées 0, lectures logiques de données d'objets volumineux 0, lectures physiques de données d'objets volumineux 0, lectures anticipées de données d'objets volumineux 0.
    Table 'Produit'. Nombre d'analyses 1, lectures logiques 720, lectures physiques 0, lectures anticipées 0, lectures logiques de données d'objets volumineux 0, lectures physiques de données d'objets volumineux 0, lectures anticipées de données d'objets volumineux 0.

    SQL Server \endash Temps d'exécution*:
    , Temps UC = 47*ms, temps écoulé = 469*ms.

  4. #4
    Expert confirmé
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Par défaut
    Il manque également la DDL de vos tables et de vos index présents sur celles-ci. Pouvez vous nous les mettre ?

    Il faut savoir également que le comportement et la performance d'une requête peut changer avec la volumétrie.

    ++

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2006
    Messages
    480
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 480
    Par défaut
    Ce sont des table assez grosses (entre 500 000 et 1 000 000 d'enregistrements)

    Pour le détail des tables, considérez simplement :

    PRODUIT :

    id_produit INT -> PK
    nom VARCHAR(250)
    id_type_produit INT


    PRODUIT_CODE_BARRE :

    id_produit INT , code_barre VARCHAR (50) -> PK

  6. #6
    Expert confirmé
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Par défaut
    Pas de foreign key entre vos 2 tables ? Pas d'autres index ?

    ++

  7. #7
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Bonjour,

    sans connaitre les index sur vos tables, ni avoir les plans d’exécution, difficile de répondre précisément.

    que donne cette requête
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    SELECT p.id_produit,p.nom, ISNULL(MAX(pcb.code_barre), 0) as code_barre
    FROM produit p 
    LEFT OUTER JOIN Produit_code_barre pcb
    	ON pcb.id_produit = p.id_produit
    WHERE  p.id_type_produit = 1
    	AND p.id_produit < 5000
    GROUP BY p.id_produit,p.nom

    pour ce qui est des IO et cpu, vous pouvez exécuter ceci :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SET STATISTICS IO ON
    SET STATISTICS TIME ON
    et ensuite exécuter vos requêtes. Ceci vous indiquera le temps et les IO pour chaque requête. vous pouvez poster les résultats.

Discussions similaires

  1. Les meilleurs cours et tutoriels C++
    Par Community Management dans le forum C++
    Réponses: 1
    Dernier message: 13/05/2015, 13h50
  2. Quel est le meilleur script PHP de portail (CMS) ?
    Par Lana.Bauer dans le forum EDI, CMS, Outils, Scripts et API
    Réponses: 187
    Dernier message: 18/10/2012, 07h45
  3. Réponses: 87
    Dernier message: 06/07/2011, 15h33
  4. Quelle est la meilleure syntaxe ?
    Par maggots dans le forum GTK+ avec C & C++
    Réponses: 2
    Dernier message: 02/06/2010, 14h27
  5. La meilleure syntaxe pour les entrées/sorties
    Par Lunixinclar dans le forum Langages de programmation
    Réponses: 2
    Dernier message: 28/03/2007, 13h55

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