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

C# Discussion :

GetValue assez lent pour récupérer un champ CLOB d'ORACLE


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre Expert


    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 970
    Par défaut GetValue assez lent pour récupérer un champ CLOB d'ORACLE
    Bonjour,

    Dans un programme de statistique, je dois passez en revue une certaine quantité de ligne d'une table Oracle pour effectuer des stats.

    Il s'agit d'une ré écriture d'un code VB6 donc j'ai les 2 versions pour comparer les performances.

    En gros mon code en c# est le suivant :

    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
     
    DbCommand cmdBio;
    DbDataReader drBio;
     
    cmdBio = varGlobals.connection.CreateCommand();
     
    cmdBio.CommandText = "SELECT * FROM bio_contenu WHERE numpat="  + NumPat.ToString() + " AND dtebio < '" + varGlobals.dteEnd.AddDays(31).ToShortDateString() + "' AND dtebio >= (SELECT max(dtebio) FROM bio_contenu WHERE numpat=" + NumPat.ToString() + " AND dtebio <= '" + FirstSeanceDate.Value.ToShortDateString() + "') ORDER BY dtebio DESC";
     
    cmdBio.CommandType = System.Data.CommandType.Text;
    cmdBio.CommandTimeout = 120;
     
    drBio = cmdBio.ExecuteReader();
     
    string sValeur = ""; 
    while (drBio.Read())
    {
        sValeur  = drBio.GetValue(drBio.GetOrdinal("compterendu").ToString();
    }
    Sur 120 enregistrement ce code prend environ 10 secondes contre 2 pour son équivalent VB6

    En VB6 c'est ADO qui est utilisé avec un client oracle 11 et une DB oracle 11.

    En C# j'utilise les classes style DbProviderFactory car j'ai créé une librairie me permettant de me connecter à plusieurs type de DB. Le provinder utilisé dans ce cas provient de la dll system.data.oracleclient (également via un client oracle 11 sur la même db).

    Quelqu'un aurait il une idée pour améliorer les performances ?
    Articles sur les technologies .NET

    Une réponse vous a aidé ? utilisez le bouton

    Votre problème est résolu ? utilisez le bouton

  2. #2
    Membre Expert Avatar de sisqo60
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Février 2006
    Messages
    754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Février 2006
    Messages : 754
    Par défaut
    Bonjour,

    As-tu chronométré les différents bouts de code. Là, tu nous fournis un bout de code standard (je ne me permettrais pas de juger la requête SQL qui ne me semble pas très optimisée, mais je ne connais pas la base de données). En plus tu récupère tes données mais tu n'en fait rien (sauf si tu as supprimé ce bout de code aussi).

    Bref, on ne peut pas vraiment t'aider avec ce peu de données.

  3. #3
    Membre Expert


    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 970
    Par défaut
    Bonjour et merci pour la réponse rapide.

    Effectivement la requête n'est pas vraiment optimisée mais n'est pas de moi et au niveau DB c'est assez conséquent (plus de 1200 tables avec des millions d'enregistrements). Effectivement j'ai retiré une partie du code par soucis de confidentialité.

    En fait le champ qu'on récupère dans le CLOB est un XML qui est parser par après. J'ai effectivement chronométré les différentes parties du code pour me rendre compte que c'était au niveau du

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    sValeur  = drBio.GetValue(drBio.GetOrdinal("compterendu").ToString();
    que cela prenait du temps. Chronométrage effectué avec l'équivalent du code VB et avec le code C#.

    J'ai supposé que le problème provenait du fait que je ne passais pas par les objets OracleConnection et CO et j'ai donc effectué un test à la maison (même table mais beaucoup moins d'enregistrements et surtout pas 1500 utilisateurs sur la DB ;-) ). Pour avoir un test concluant je travaille sur la même table (qui contient bcp moins d'enregistrement sur ma DB de test) et au lieu de récupérer 120 enregistrements j'en récupère 1000 en 10 sec avec mon code original. J'ai donc essayé avec les objets de system.data.oracleclient.dll.

    Voici le code :

    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
     
    OracleConnection con = new OracleConnection("Data Source=SQL_LOCAL;User Id=X;Password=X;");
     
    // Connextion à la DB
    try
    {
       con.Open();
    }
    catch (Exception ex)
    {
       MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
       return;
    }
     
    try
    {
       OracleCommand cmd = con.CreateCommand();
       cmd.CommandText = "SELECT * FROM BIOLOGIE where NumPat <= 115076";
       cmd.CommandType = CommandType.Text;
     
       OracleDataReader odr = cmd.ExecuteReader(); 
     
       System.IO.StreamWriter sw = new System.IO.StreamWriter("d:/TestOracle.txt", false, Encoding.UTF8);
    sw.WriteLine("Début : " + DateTime.Now.ToString());
     
       Int32 NbCount = 0;
       string sCompteRendu = "";
       OracleLob myLob = null;
       while (odr.Read())
       {
           myLob = odr.GetOracleLob(odr.GetOrdinal("COMPTERENDU"));
           if(!myLob.IsNull )
              sCompteRendu = myLob.Value.ToString(); 
     
           NbCount++;
        }
     
        sw.WriteLine("Count : " + NbCount.ToString());
        sw.WriteLine("Fin : " + DateTime.Now.ToString());
        sw.Close();
        odr.Close();
        odr.Dispose();
        cmd.Dispose();
    }
    catch (Exception ex)
    {
       MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.OK,    MessageBoxIcon.Error);
       return;
    }
    finally
    {
       con.Close();
    }
     
    MessageBox.Show("Fin du traitement", "Information", MessageBoxButtons.OK, MessageBoxIcon.Information);
    Si je retire les 2 lignes :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if(!myLob.IsNull )
       sCompteRendu = myLob.Value.ToString();
    Je passe de 11 secondes à 1. J'ai donc l'impression que le problème vient de la conversion de la valeur en string.

    Mais je ne vois pas comment amélioré cela. Une idée ?
    Articles sur les technologies .NET

    Une réponse vous a aidé ? utilisez le bouton

    Votre problème est résolu ? utilisez le bouton

  4. #4
    Membre Expert Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Par défaut
    Hello,

    as-tu besoin de convertir en string ? Quel est le type de myLob.Value ?


    Par ailleurs, je t'invite à éviter de fabriquer des requêtes par concaténation de chaînes; c'est une faille de sécurité énorme (nommée injection sql), la bonne façon de faire est décrite ici.

  5. #5
    Membre Expert


    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 970
    Par défaut
    le contenu de la valeur du clob est en fait une arborescence XML qui sera parser par après. Donc je pense que je n'ai pas le choix que de passer par un string.

    Par contre merci pour l'info au niveau de la formation des requêtes, ici c'est un programme que je retraduis d'un prog VB6 et dont j'essaie de garder un max de la logique identique même si j'utilise un max les classes.

    Mais je vais en profiter pour revoir les requêtes même si c'est pas mon problème principal pour l'instant.
    Articles sur les technologies .NET

    Une réponse vous a aidé ? utilisez le bouton

    Votre problème est résolu ? utilisez le bouton

  6. #6
    Membre Expert


    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 970
    Par défaut
    Citation Envoyé par Guulh Voir le message
    Hello,

    as-tu besoin de convertir en string ? Quel est le type de myLob.Value ?


    Par ailleurs, je t'invite à éviter de fabriquer des requêtes par concaténation de chaînes; c'est une faille de sécurité énorme (nommée injection sql), la bonne façon de faire est décrite ici.
    Tutoriel très intéressant d'autant plus que j'utilise effectivement les DB.... et régulièrement les requêtes paramétrées. Mais je pense que le "régulièrement" va devenir "tous le temps".
    Articles sur les technologies .NET

    Une réponse vous a aidé ? utilisez le bouton

    Votre problème est résolu ? utilisez le bouton

  7. #7
    Membre Expert


    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2006
    Messages
    970
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 970
    Par défaut
    J'ai trouvé une solution qui me donne un temps d’exécution proche du VB6, c'est d'utiliser les objets Oracle. Mais hélas je ne sais pas utiliser ma librairie qui me permettait d'utiliser les objets génériques et donc d'être compatible avec plusieurs DB. Dans ce cas-ci cette application ne tournera jamais que sur Oracle mais si quelqu'un à une autre solution je suis preneur.

    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
     
    try
    {
       OracleCommand cmd = con.CreateCommand();
       cmd.CommandText = "SELECT * FROM BIOLOGIE where NumPat <= 115076";
       cmd.CommandType = CommandType.Text;
     
       OracleDataReader odr = cmd.ExecuteReader(); 
     
       string sCompteRendu = "";
       OracleLob myLob = null;
     
       while (odr.Read())
       {
           myLob = odr.GetOracleLob(odr.GetOrdinal("COMPTERENDU"));
     
           if (!myLob.IsNull)
           {
               byte[] b = new byte[myLob.Length];
               myLob.Read(b, 0, (int)myLob.Length);
     
               sCompteRendu = b.ToString();
           }
     
           NbCount++;
       }
     
       odr.Close();
       odr.Dispose();
       cmd.Dispose();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Erreur", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return;
    }
    Articles sur les technologies .NET

    Une réponse vous a aidé ? utilisez le bouton

    Votre problème est résolu ? utilisez le bouton

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

Discussions similaires

  1. [XL-2007] Problème pour récupérer un champ Word dans excel
    Par Jackfly dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 02/04/2013, 08h45
  2. [MySQL] Comment écrire un service web pour récupérer un champ d'une base de données
    Par mallsoul dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 04/10/2012, 18h23
  3. Mettre a jour un champ CLOB d'Oracle par un RowSet
    Par SuperPat dans le forum JDBC
    Réponses: 0
    Dernier message: 23/06/2009, 17h19
  4. [MySQL] Problème pour récupèrer les champs d'un formulaire qui se trouve dans un while
    Par mademoizel dans le forum PHP & Base de données
    Réponses: 18
    Dernier message: 21/03/2008, 14h59
  5. [MySQL] je cherche une aide pour récupérer des champs d'une base de donnée
    Par maya24 dans le forum PHP & Base de données
    Réponses: 2
    Dernier message: 23/09/2007, 12h14

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