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 :

Optimiser résultat requête SQL OracleDataReader


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Développeur UNIFACE, C, C++, C#, Java
    Inscrit en
    Janvier 2012
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur UNIFACE, C, C++, C#, Java
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2012
    Messages : 71
    Par défaut Optimiser résultat requête SQL OracleDataReader
    Bonjour,
    Je rencontre un problème lors de l'affichage d'une requête avec beaucoup de données (environs 300 000 lignes)
    Le temps de recherche est correct lorsque j'affiche une 100énes de lignes mais quand je charge le tout il faut attendre une bonne 10ènes de minutes.

    L'application consiste à afficher une liste de correspondant en fonction des paramètres remplis ou non.

    Quand je lance une recherche sans renseigner de champ, j’affiche la totalité de la table soit 300 000 lignes.

    J’utilise la commande OracleDatareader pour executer mes requêtes.

    Voici la partie connexion et exécution :

    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
      private void button1_Click(object sender, EventArgs e)
            {
                listView1.Clear();
     
                    // Set the view to show details.
                    listView1.View = View.Details;
                    // Allow the user to edit item text.
                    // listView1.LabelEdit = true;
                    // Allow the user to rearrange columns.
                    listView1.AllowColumnReorder = true;
                    // Display check boxes.
                    listView1.CheckBoxes = true;
                    // Select the item and subitems when selection is made.
                    listView1.FullRowSelect = true;
                    // Display grid lines.
                    listView1.GridLines = true;
                    // Sort the items in the list in ascending order.
                    listView1.Sorting = SortOrder.Ascending;
     
                    listView1.Columns.Add("", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("Titre", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("Nom", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("Prénom", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("Nom Marital", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("Sexe", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("Commune", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("CP", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("Crée le", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("Service", -2, HorizontalAlignment.Left);
                    listView1.Columns.Add("Matricule", -2, HorizontalAlignment.Left);
     
                    string oradb = "Data Source=ma source;User Id=mon id;Password=mon mdp;";
                    OracleConnection conn = new OracleConnection(oradb);  
                    conn.Open();
                    OracleCommand cmd = new OracleCommand();
                    cmd.Connection = conn;
     
                    cmd.CommandText = "select ma requete from ma table'";
                    cmd.CommandType = CommandType.Text;
                    OracleDataReader dr = cmd.ExecuteReader();
                    ListViewItem it = new ListViewItem();
                    int i = 0;
                    int j = 0;
                    while (dr.Read())
                    {
     
                        ListViewItem items = new ListViewItem("", i);  //Ajoute un item 
     
                        for (j = 0; j <= dr.FieldCount - 1; j++)
                        {
     
                            if (dr[j] != DBNull.Value)
                            {
     
     
                                    items.SubItems.Add(dr.GetString(j).ToString()); //Ajoute le champ i dans item i
     
                            }
                            else
                            {
                                items.SubItems.Add("");
                            }
     
                        }
     
                        listView1.Items.AddRange(new ListViewItem[] { items });
     
                        i++;
                    }
     
     
                    foreach (ColumnHeader column in listView1.Columns)
                    {
                        column.Width = -2;
                    }
     
                    conn.Close();
     
     
            }

    Y-a-t-il un moyen d'optimiser cette connexion ?

    merci d'avance

  2. #2
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 218
    Par défaut
    Ma réponse portera sur un ralentissement du au contrôle listview, ce qui est le plus probable.


    Tu peut activer le doublebuffer ça ne mange pas de pain et ça servira plus tard pour l'affichage.
    Voici une méthod d'extension pour ce faire (non testé mais ça ressemble à ce que j'utilise)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public static class ControlExtensions
    {
        public static void DoubleBuffering(this Control control, bool enable)
        {
            var method = typeof(Control).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic);
            method.Invoke(control, new object[] { ControlStyles.OptimizedDoubleBuffer, enable });
        }
    }

    Pour le remplissage il ne faut pas que le control fasse une mise à jour de l'affichage à chaque insertion.
    Je te conseil d'utiliser "BeginUpdate" et "EndUpdate"
    https://msdn.microsoft.com/en-us/lib...vs.110%29.aspx


    Je constate que tu utilise déjà le "addrange" qui est une bonne chose, mais il est préférable de l'utiliser un minimum de fois pour maximiser les performances.
    Le mieux serait après ton traitement, c'est à dire juste avant
    foreach (ColumnHeader column in listView1.Columns)
    pour ajouter la totalité, quitte à créer une liste d'item.

  3. #3
    Membre confirmé
    Homme Profil pro
    Développeur UNIFACE, C, C++, C#, Java
    Inscrit en
    Janvier 2012
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur UNIFACE, C, C++, C#, Java
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2012
    Messages : 71
    Par défaut
    Bonjour ericlm,
    Merci pour ta réponse, j'ai suivi ton conseil et passé la méthode d'extension pour le double buffer, c'est vrai que ça peut toujours servir

    Concernant le "BeginUpdate" et "EndUpdate", je dois donc commencer mon BeginUpdate dans la boucle et le finir or de la boucle ?
    Comment remplir une list d'items dans la boucle et mettre a jour la listview ensuite ?

    Merci pour ton aide.

  4. #4
    Membre Expert Avatar de jopopmk
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2011
    Messages
    1 856
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

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

    Informations forums :
    Inscription : Mars 2011
    Messages : 1 856
    Par défaut
    Salut,

    réponse beaucoup moins technique que celle de ericlm128 (et même plutôt philosophique et qui n'engage que moi) : si trop de donnée fait ramer lâche l'affaire. Dans un premier temps tu tartouilles ta requête pour faire un COUNT et si ça dépasse un certain seuil t'avertis l'utilisateur. Une interface qui affiche ne serait-ce que 1000 lignes est une interface qui ne sert à rien, aucun utiilisateur ne parcourera jamais toutes ces lignes. C'est pour moi un échec du job attendu pour outil informatique de gestion, à savoir compulser des masses d'info pour en extraire la donnée utile.

  5. #5
    Membre confirmé
    Homme Profil pro
    Développeur UNIFACE, C, C++, C#, Java
    Inscrit en
    Janvier 2012
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur UNIFACE, C, C++, C#, Java
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2012
    Messages : 71
    Par défaut
    Citation Envoyé par jopopmk Voir le message
    Salut,

    réponse beaucoup moins technique que celle de ericlm128 (et même plutôt philosophique et qui n'engage que moi) : si trop de donnée fait ramer lâche l'affaire. Dans un premier temps tu tartouilles ta requête pour faire un COUNT et si ça dépasse un certain seuil t'avertis l'utilisateur. Une interface qui affiche ne serait-ce que 1000 lignes est une interface qui ne sert à rien, aucun utiilisateur ne parcourera jamais toutes ces lignes. C'est pour moi un échec du job attendu pour outil informatique de gestion, à savoir compulser des masses d'info pour en extraire la donnée utile.
    Salut Jopopmk,
    Justement c'est une application aujourd'hui utilisé (sous un ancien langage), à peu près 150 000 lignes ont été mis à jour depuis le début d'année, donc malheureusement je dois trouver une solution pour accélérer cet affichage

  6. #6
    Expert confirmé

    Homme Profil pro
    Responsable déploiement (SCCM, InTune, GPO)
    Inscrit en
    Juillet 2014
    Messages
    3 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Responsable déploiement (SCCM, InTune, GPO)
    Secteur : Transports

    Informations forums :
    Inscription : Juillet 2014
    Messages : 3 218
    Par défaut
    Tu doit effectuer un BeginUpdate avant toutes modifications de la listview (ligne 3) et le EndUpdate après la dernière modification (ligne 79).
    Laisse le addrange tel qu'il ai et test. Si tu fige la listview (Begin ...End) peut être que ce dernier point aura un impact minime ou null.

  7. #7
    Membre confirmé
    Homme Profil pro
    Développeur UNIFACE, C, C++, C#, Java
    Inscrit en
    Janvier 2012
    Messages
    71
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur UNIFACE, C, C++, C#, Java
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2012
    Messages : 71
    Par défaut
    Je viens de faire le test sur une requête pas trop lourde je gagne 0.5Sec

    Sans le begin ... End => 2.03 secondes
    Avec le begin ... End => 1.55 secondes


    sur une requête qui retoune que 872 lignes.

    Si non il faut que je trouve le moyen d'afficher 1/1000 des infos et une fois la scroll bar arrivée à 300 je charge les 300 suivants.
    Reste à réfléchir à l'algo

Discussions similaires

  1. [MySQL] Affichage résultat requête SQL dans page HTML comme un tableau
    Par joxbl dans le forum PHP & Base de données
    Réponses: 13
    Dernier message: 14/03/2011, 14h26
  2. Réponses: 13
    Dernier message: 28/09/2007, 11h55
  3. résultat requêtes sql
    Par mmb04 dans le forum JDBC
    Réponses: 11
    Dernier message: 22/03/2007, 16h06
  4. Optimisation de requêtes SQL - utilisation de IN SELECT
    Par cfeltz dans le forum Langage SQL
    Réponses: 3
    Dernier message: 20/12/2006, 09h28
  5. Optimiser une requête SQL d'un moteur de recherche
    Par kibodio dans le forum Langage SQL
    Réponses: 2
    Dernier message: 06/03/2005, 20h55

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