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 :

Performance versus INNER JOIN et MAX


Sujet :

Développement SQL Server

  1. #1
    Membre averti
    Inscrit en
    Juillet 2003
    Messages
    37
    Détails du profil
    Informations forums :
    Inscription : Juillet 2003
    Messages : 37
    Par défaut Performance versus INNER JOIN et MAX
    Bonjour à tous,

    Tout d’abord désolé si un sujet semblable a déjà été posté, j’ai fais quelques recherches et j’ai trouvé des indices, mais rien précisément qui répondait exactement à ma question.

    En fait j’aimerais avoir vos conseils par rapport à la formulation de cette requête :


    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
    DECLARE @client# XML
    SET @client# = '<clients><id>234</id><id>231</id><id>228</id><id>1618</id><id>224</id><id>223</id><id>217</id><id>205</id></clients>'
     
    DECLARE @DateDebut# DATETIME
    SET @DateDebut# = '2010-07-27'
     
    DECLARE @DateFin# DATETIME
    SET @DateFin# = '2010-08-27'
     
     
    SELECT  ParamValues.ID.value('.', 'INT') AS ID
    INTO    #clientList
    FROM    @client#.nodes('/clients/id') AS ParamValues ( ID )
     
     
    SELECT  o.OperationID ,
            s.FKModuleID ,
            c.ClientID
    FROM    dbo.Operation o
            INNER JOIN dbo.clients c ON c.ClientID = o.FKClientID
                                          AND o.OperationType IN ( 1, 10 )
                                          AND o.OperationState IN ( 0, 3 )
                                          AND c.Update = 1
                                          AND o.Update = 1
                                          AND ISNULL(c.Dead, 0) = 0
            INNER JOIN dbo.Stages s ON s.FkOperationID = o.OperationID
                                         AND s.UniqueID = ( SELECT  ISNULL(MAX(UniqueID), -1) AS ID
                                                            FROM    Stages
                                                            WHERE   FKOperationID = o.OperationID
                                                                    AND StageState = 0
                                                          )
                                         AND s.DateStage >= @DateDebut#
                                         AND s.DateStage <= @DateFin#
            INNER JOIN #clientList pl ON pl.ID = c.ClientID
     
     
    DROP TABLE #clientList

    La partie dans le 2e « INNER JOIN » :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    AND s.UniqueID = ( SELECT  ISNULL(MAX(UniqueID), -1) AS ID
                                                            FROM    Stages
                                                            WHERE   FKOperationID = o.OperationID
                                                                    AND StageState = 0
                                                          )
    Cette partie, lorsque je passe une longue liste de clients, mais surtout lorsque j’allonge raisonnablement l’intervalle de dates, ralentit énormément le temps de réponse de la requête. Je me demandais, remarquez-vous quelque chose au niveau de la syntaxe qui pourrait être optimisé? Car à priori je semble procéder de la bonne façon, peut-être dois-je juste me résoudre à l’idée que le traitement prendra toujours un temps considérable en fonction de l’intervalle de dates et de la liste de clients.

    Merci à l’avance des conseils que vous pourrez m’apporter à ce sujet!

  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
    22 002
    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 : 22 002
    Billets dans le blog
    6
    Par défaut
    Si vous voulez des performances il faut abandonner tout ce qui est itératif et ne faire que de l'ensembliste. De plus utilisez des tables instanciées et non des table temporaires ou des variables tables

    Donc débarrassez vous :
    1) du XML
    2) de la table #clientList

    Pour faire passer votre liste d'argument, vous pouvez opérer comme ceci :
    1) créez une table dans la base de données, structurée comme suit :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    CREATE TABLE dbo.T_PARA_LIST_TPL
    (TPL_ID            BIGINT IDENTITY NOT NULL PRIMARY KEY,
     TPL_USER_TRAN     UNIQUEIDENTIFIER NOT NULL,
     TPL_USER_VALUE    INT NOT NULL);
     
    CREATE INDEX X_TPL_RN_VLU ON dbo.T_PARA_LIST_TPL (TPL_USER_TRAN, TPL_USER_VALUE);
    2) Au niveau du client, calculez un GUID (par exemple EDA006BC-C661-48CD-A091-B8116E02851F) et insérez les valeurs dans cette table comme suit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    INSERT INTO dbo.T_PARA_LIST_TPL 
           (TPL_USER_TRAN,                          TPL_USER_VALUE)
    VALUES ('EDA006BC-C661-48CD-A091-B8116E02851F', 123),
           ('EDA006BC-C661-48CD-A091-B8116E02851F', 456),
           ('EDA006BC-C661-48CD-A091-B8116E02851F', 789),       
           ...
           ('EDA006BC-C661-48CD-A091-B8116E02851F', 951);
    3) Dans votre proc stock, passez en argument le GUID (EDA006BC-C661-48CD-A091-B8116E02851F), et récrivez la comme suit :

    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
    CREATE PROCEDURE dbo.P_SELECT_OPERATION_CLIENTS
           @GUID_TRAN UNIQUEIDENTIFIER,
           @DateDebut DATETIME,
           @DateFin   DATETIME      
    AS
     
    SELECT  o.OperationID ,
            s.FKModuleID ,
            c.ClientID
    FROM    dbo.Operation o
            INNER JOIN dbo.clients c ON c.ClientID = o.FKClientID
                                          AND o.OperationType IN ( 1, 10 )
                                          AND o.OperationState IN ( 0, 3 )
                                          AND c.UPDATE = 1
                                          AND o.UPDATE = 1
                                          AND ISNULL(c.Dead, 0) = 0
            INNER JOIN dbo.Stages s ON s.FkOperationID = o.OperationID
                                         AND s.UniqueID = ( SELECT  ISNULL(MAX(UniqueID), -1) AS ID
                                                            FROM    Stages
                                                            WHERE   FKOperationID = o.OperationID
                                                                    AND StageState = 0
                                                          )
                                         AND s.DateStage >= @DateDebut
                                         AND s.DateStage <= @DateFin
            INNER JOIN dbo.T_PARA_LIST_TPL AS pl 
                  ON pl.TPL_USER_VALUE = c.ClientID
    WHERE   TPL_USER_TRAN = @GUID_TRAN;
     
    DELETE FROM dbo.T_PARA_LIST_TPL
    WHERE  @GUID_TRAN; 
     
    GO
    4) Lancez la avec les paramètres adéquats, par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    EXECUTE dbo.P_SELECT_OPERATION_CLIENTS 'EDA006BC-C661-48CD-A091-B8116E02851F', '2010-07-27', '2010-08-27';
    Enfin, suivez les articles que j'ai écrit à ce sujet pour bien indexer les données de vos tables eut égard à cette requête :
    http://sqlpro.developpez.com/cours/quoi-indexer/
    http://sqlpro.developpez.com/optimisation/indexation/
    http://sqlpro.developpez.com/cours/optimiser/
    http://sqlpro.developpez.com/optimisation/

    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/ * * * * *

Discussions similaires

  1. Max() et inner join
    Par laloune dans le forum MS SQL Server
    Réponses: 18
    Dernier message: 06/11/2012, 18h09
  2. Performances : INNER JOIN vs WHERE
    Par zeclubbeur dans le forum Débuter
    Réponses: 2
    Dernier message: 12/02/2012, 17h52
  3. Réel gain de performance lors d'un INNER JOIN ?
    Par Bktero dans le forum Langage SQL
    Réponses: 7
    Dernier message: 17/03/2011, 19h37
  4. Mysql Inner join
    Par ..:: Atchoum ::.. dans le forum Requêtes
    Réponses: 3
    Dernier message: 25/10/2007, 12h21
  5. Inner Join & Select
    Par bakaneko dans le forum Langage SQL
    Réponses: 7
    Dernier message: 10/02/2004, 10h48

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