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

ASP.NET Discussion :

CommandType.StoredProcedure moins rapide que CommandType.Text. Où est l'erreur?


Sujet :

ASP.NET

  1. #1
    Expert confirmé
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Par défaut CommandType.StoredProcedure moins rapide que CommandType.Text. Où est l'erreur?
    Salut,

    Je suis un peu abasourdi, pour ne pas diresur le c**.

    J'ai récupéré les source de ce site pour voir un peu de LINQ ou SQL celui qui est le plus performant. Mes test correspondent bien à ce que trouve l'auteur, jusque là ça va. Dans son code il utilise des requetes SQL de type CommandType.Text. Je me suis dit se serait interessant de voir ce que ça donne avec des procédures stockées. Mais là catastrophe! Les procédures stockées seraient moins rapides sur un simple SELECT qu'une commande text!!

    Afin de vous permettre de vous faire votre propre jugement je vous laisse les sources. J'ai peut-être fait des erreurs...
    1. Telecharger et installer AdventureWorks
    2. Ajouter à la base la procédure stockée suivante:
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      CREATE PROCEDURE uspSelectCustomers 
      AS
      BEGIN
       
          SELECT * FROM [AdventureWorks].[Sales].[Customer]
       
      END
      GO
    3. Le programme à console executer:
      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
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      using System;
      using System.Data;
      using System.Data.SqlClient;
      using System.Diagnostics;
      using System.Xml.XPath;
       
      namespace RetrieveUsingADO
      {
          class Program
          {
              private static string connectionstring = @"Server=NOM_MACHINE\MSSQL01;Database=AdventureWorks;user id=sa;password=;Connection timeout = 5 ;Pooling='false';";
       
              static void Main(string[] args)
              {
                  displaySettings();
                  Console.WriteLine("Executing GatherDataADORead");
                  GatherDataADORead();
              } // end of main
       
              # region GatherData
              public static void GatherDataADORead()
              {
                  using (DataSet dataSet = new DataSet())
                  {
                      using (DataTable dt = new DataTable("ADORead"))
                      {
                          dt.Columns.Add(new DataColumn("Pass", typeof(Int32)));
                          dt.Columns.Add(new DataColumn("SP", typeof(Int64)));
                          dt.Columns.Add(new DataColumn("TEXT", typeof(Int64)));
                          dataSet.Tables.Add(dt);
       
                          DataRow dr;
                          Stopwatch sw = new Stopwatch();
                          for (int i = 0; i <= 500; i++)
                          {
                              dr = dt.NewRow();
                              dr[0] = i;
                              sw.Start();
                              ADOReadingStoredProc();
                              dr[1] = ((long)(sw.ElapsedTicks / 100));
                              sw.Reset();
                              sw.Start();
                              ADOReadingText();
                              dr[2] = ((long)(sw.ElapsedTicks / 100));
                              sw.Reset();
                              dt.Rows.Add(dr);
                          } //end of for
                      }
                      dataSet.WriteXml(string.Format("c:\\temp\\{0}_ADORead.xml", DateTime.Now.ToString("yyyy-MM-ddThh-mm-ss")));
                  }
              }
       
              # endregion GatherData
       
              # region ActualFunctions
              /// <summary>
              /// This function reads from customer table using ado and then sums up the values of the first column.
              /// </summary>
              private static void ADOReadingText()
              {
                  using (SqlConnection Conn = new SqlConnection(connectionstring))
                  {
                      Conn.Open();
       
                      using (SqlCommand cmd = new SqlCommand("SELECT * FROM [AdventureWorks].[Sales].[Customer]", Conn))
                      {
                          cmd.CommandType = CommandType.Text;
                          double i = 0;
                          using (SqlDataReader dr = cmd.ExecuteReader())
                          {
                              while (dr.Read())
                              {
                                  i = i + Convert.ToDouble(dr[0]);
                              }
                          }
                      }
                  }
              }//end ADO Reading
       
              private static void ADOReadingStoredProc()
              {
                  using (SqlConnection Conn = new SqlConnection(connectionstring))
                  {
                      Conn.Open();
       
                      using (SqlCommand cmd = new SqlCommand("uspSelectCustomers", Conn))
                      {
                          cmd.CommandType = CommandType.StoredProcedure;
                          double i = 0;
                          using (SqlDataReader dr = cmd.ExecuteReader())
                          {
                              while (dr.Read())
                              {
                                  i = i + Convert.ToDouble(dr[0]);
                              }
                          }
                      }
                  }
              }
       
              # endregion ActualFunctions
       
              # region Helpers
              private static void displaySettings()
              {
                  if (Stopwatch.IsHighResolution)
                  {
                      Console.WriteLine("Operations timed using the system's high-resolution performance counter.");
                  }
                  else
                  {
                      Console.WriteLine("Operations timed using the DateTime class.");
                  }
       
                  long frequency = Stopwatch.Frequency;
                  Console.WriteLine("  Timer frequency in ticks per second = {0}",
                      frequency);
                  long nanosecPerTick = (1000L * 1000L * 1000L) / frequency;
                  Console.WriteLine("  Timer is accurate within {0} nanoseconds",
                      nanosecPerTick);
              }
              # endregion Helpers
          }
      }
    4. Analyser avec Excel les fichiers Xml générés dans le repertoire temp. Attention l'unité de mesure du temps (Axe y) est en ElapsedTicks. Cela ne gène pas la comparaison.


    D'avance merci de votre analyse.

    A+
    Images attachées Images attachées  
    "Winter is coming" (ma nouvelle page d'accueil)

  2. #2
    Membre chevronné Avatar de MetalGeek
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    412
    Détails du profil
    Informations personnelles :
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 412
    Par défaut
    Salut,

    il me semble que c'est normal, par contre sur plusieurs exécutions d'affilée la procédure stockée, mise en cache par la BD, gagne en perfs.

  3. #3
    Membre confirmé
    Inscrit en
    Décembre 2009
    Messages
    26
    Détails du profil
    Informations forums :
    Inscription : Décembre 2009
    Messages : 26
    Par défaut
    En appelant une requête avec la classe SqlCommand, la base de données va exécuter la procédure stockée 'sp_executesql' qui met le Transact SQL produit pour la requête en cache. Je ne sais pas pour quoi la méthode avec une procédure stockée est moins rapide mais ça explique pour quoi les deux méthodes nécessitent des temps similaires.

    http://msdn.microsoft.com/en-us/library/ms188001.aspx

    Pour un autre test tu peut appeler ADOReadingStoredProc 500 fois à la suite après 500 appels à ADOReadingText

  4. #4
    Expert confirmé
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Par défaut
    Citation Envoyé par MetalGeek Voir le message
    Salut,

    il me semble que c'est normal, par contre sur plusieurs exécutions d'affilée la procédure stockée, mise en cache par la BD, gagne en perfs.
    Normal? Je me suis toujours laissé dire que les SP étaient plus rapides. De plus, la SP reste toujours moins performante à la requete texte... Bizarre non?

    En PJ j'ai ajouter des données de LINQ. J'ai pris soin de retirer les données de l'execution de la première requête qui est tellement peu performante qu'elle prend trop d'importance par rapport au reste du graphique et le rend illisible.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      <Read>
        <Pass>0</Pass>
        <SP>42912</SP>
        <TEXT>14228</TEXT>
        <LINQ>39435</LINQ>
      </Read>
    A+
    Images attachées Images attachées  
    "Winter is coming" (ma nouvelle page d'accueil)

  5. #5
    Expert confirmé
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Par défaut
    Citation Envoyé par AndreiS Voir le message
    Pour un autre test tu peut appeler ADOReadingStoredProc 500 fois à la suite après 500 appels à ADOReadingText
    Test fait cf. image jointe. Resultat:
    1. Text (meilleurs temps)
    2. SP (temps plus constants)
    3. LINQ (sans commentaires... )

    Premiere execution toujours lente:
    1. /Read/TEXT 32401
    2. /Read/SP 39313
    3. /Read/LINQ 44926


    A+
    Images attachées Images attachées  
    "Winter is coming" (ma nouvelle page d'accueil)

  6. #6
    Expert confirmé
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Par défaut
    Les tests ont été réalisé sur mon PC perso.
    Je les ai donc refait dans l'environnement du boulot sur un serveur web séparé du serveur de base de données.
    Le résultat indique que la procédure stockée est légèrement plus rapide. Ouf!
    Peut-être que cette différence s'accentue quand les requêtes deviennent plus complexes.

    Par contre, je confirme que LINQ est plus lent. Il y a cependant des aspects que je n'ai pas encore tésté:
    • Requete LINQ précompilées
    • Requête LINQ sur une procédure stockée (utilisation du contexte de données simplement).

    A tester.

    A+
    "Winter is coming" (ma nouvelle page d'accueil)

  7. #7
    Expert confirmé
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Par défaut
    J'ai testé les requête précompilées. Les performance sont très proches de celles des requête texte et procédures stockées. Un conseil n'utilisez pas les requêtes LINQ non compilées. Et gardez un oeil sur le nombre de DataContext que vous instanciez. Cela allonge le temps de traitement.

    A+
    "Winter is coming" (ma nouvelle page d'accueil)

  8. #8
    Rédacteur
    Avatar de WOLO Laurent
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Mars 2003
    Messages
    2 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Congo-Brazzaville

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 741
    Par défaut
    C'est vrai que ca date de 2009 mais ma rigueur me conduit à vous demander de toujours acetiver le pool de connexion :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    private static string connectionstring = @"Server=NOM_MACHINE\MSSQL01;Database=AdventureWorks;user id=sa;password=;Connection timeout = 5 ;Pooling='true';";
    Et l'usage du compte sa sans mot de passe même si c'est seulement sur ton portable, tu connais les dégats que ça peut engendrer !

    Découvrez la FAQ de MS SQL Server.
    La chance accorde ses faveurs aux esprits avertis !

  9. #9
    Expert confirmé
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Par défaut
    Citation Envoyé par WOLO Laurent Voir le message
    C'est vrai que ca date de 2009 mais ma rigueur me conduit à vous demander de toujours acetiver le pool de connexion
    En .Net il est toujours activé par défaut. Pour ce qui est du mot de passe qu'est-ce qui te dit que je n'en ai pas mis un puis simplement retiré?

    Pour plus de sécurité tu devrais plutôt suggérer d'utiliser la sécurité intégrée. Tout du moins, suggérer l'utilisation d'un autre compte que "sa".
    "Winter is coming" (ma nouvelle page d'accueil)

  10. #10
    Rédacteur
    Avatar de WOLO Laurent
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Mars 2003
    Messages
    2 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Congo-Brazzaville

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : Finance

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 741
    Par défaut
    Citation Envoyé par Immobilis Voir le message
    En .Net il est toujours activé par défaut. Pour ce qui est du mot de passe qu'est-ce qui te dit que je n'en ai pas mis un puis simplement retiré?

    Pour plus de sécurité tu devrais plutôt suggérer d'utiliser la sécurité intégrée. Tout du moins, suggérer l'utilisation d'un autre compte que "sa".
    Rien justement ne le dira a un lecteur et la personne peut recopier simplement et coller ce code croyant que ca ne pose aucun problème !

    Citation Envoyé par Immobilis Voir le message
    Pour plus de sécurité tu devrais plutôt suggérer d'utiliser la sécurité intégrée. Tout du moins, suggérer l'utilisation d'un autre compte que "sa".
    En fait c'est ce que j'allais te dire mais j'ai voulu faire d'une pierre deux coups en faisant remarquer ton compte sa sans mot de passe

    Découvrez la FAQ de MS SQL Server.
    La chance accorde ses faveurs aux esprits avertis !

  11. #11
    Expert confirmé
    Avatar de Immobilis
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Mars 2004
    Messages
    6 559
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Mars 2004
    Messages : 6 559
    Par défaut
    Citation Envoyé par WOLO Laurent Voir le message
    croyant que ca ne pose aucun problème !
    Il faut que ces personnes commencent à réfléchir. Il n'y a rien de plus dangereux que le copié collé.
    "Winter is coming" (ma nouvelle page d'accueil)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Autre] Le HTML5, entre 6 et 10 fois moins rapide sur mobiles que sur bureau
    Par Gordon Fowler dans le forum Publications (X)HTML et CSS
    Réponses: 29
    Dernier message: 04/06/2012, 10h46
  2. Le HTML5, entre 6 et 10 fois moins rapide sur mobiles que sur bureau
    Par Gordon Fowler dans le forum Balisage (X)HTML et validation W3C
    Réponses: 29
    Dernier message: 04/06/2012, 10h46
  3. Réponses: 2
    Dernier message: 16/12/2009, 18h14
  4. Réponses: 4
    Dernier message: 10/09/2008, 23h03
  5. Insertion dans fichier texte + rapide que TStringList ?
    Par benj63 dans le forum C++Builder
    Réponses: 8
    Dernier message: 26/02/2004, 11h34

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