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

Langage SQL Discussion :

Nombreuses requete à faire en minimum de temps


Sujet :

Langage SQL

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 32
    Points
    32
    Par défaut Nombreuses requete à faire en minimum de temps
    Bonjour,

    Voila à l'intérieur d'un programme C++ j'effectue des requetes vers SQL Server Express.
    des INSERT UPDATE etc... rien de trop méchant en somme.
    J'ai pourtant un soucis avec une fonction d'UPDATE sur une table qui est défini ainsi:

    champ1| champ2| champ3| champ4| champ5| champ6

    alors je dois faire un update des 2 champs 1&2 en fonction des champs 3,4,5et 6...
    ce qui donne ceci dans mon prog :

    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
     
     for ( i_fur=0; i_fur<NB_FUR; i_fur++)
     {
          // For top and bottom
          for ( i_top=0; i_top<s_furndata[i_fur].top_bot; i_top++)
          {
             // For all thermal profils
             for ( i_thprf=0; i_thprf<s_furndata[i_fur].nb_thprf; i_thprf++)
             {
                // For all points of thermal profil
                for ( i_prf=0; i_prf<N_PROFIL; i_prf++)
                {
                   strcpy(strExec, "UPDATE MaTableSET ");
                   sprintf(temp," champ1= %f", Val1 );
                   strcat(strExec,temp);
                   strcat(strExec, ",");
                   sprintf(temp," champ2 = %f",Val2);
                   strcat(strExec,temp);
                   sprintf(temp," WHERE champ3 = %d",i_fur);
                   strcat(strExec,temp);
                   sprintf(temp," AND champ4 = %d",i_top);
                   strcat(strExec,temp);
                   sprintf(temp," AND champ5 = %d",i_thprf);
                   strcat(strExec,temp);
                   sprintf(temp," AND champ6 = %d",i_prf);
                   strcat(strExec,temp);
     
                   try
                   {
                      // Insere des éléments
                      // ===================
                      HRESULT retour = recordset->Open(strExec,
                         connection.GetInterfacePtr(), adOpenForwardOnly,
                         adLockReadOnly, adCmdText);
                   }
                   catch(_com_error &e)
                   {
                      MessageBox(0, (LPCSTR) e.Description(), 0, 0);
                      status = false;
                   }
                }// For all points of thermal profil
             }// For all thermal profils
          } // For top and bottom
       } // for all furnaces
    Alors le probleme est donc sur les boucles qui vont pour les 3 premieres varier entre 1 et 2 max. mais pr la derniere
    N_PROFIL = 1000
    on se retrouve avec dans mon cas 4000 updates a faire ce qui prend 20secondes ....
    et du coup mon programme prend une sacré claque dans la gueule quand il passe a cet endroit!
    je voudrais savoir si il existe une solution pour faire ces updates plus rapidement: changer la requete SQL par exemple sur les conditions pour qu'elles
    affectent plus d'enregistrements dans une meme requete
    ou carrément si quelqu'un a une idée pour redimensionner ma table (la reconstituer d'une autre maniére)
    peut etre que la solution est la ...

    j'espere que mon POST sera assez explicite, et merci de votre aide future ....

  2. #2
    Membre éprouvé Avatar de Mathusalem
    Profil pro
    IT moa
    Inscrit en
    Décembre 2003
    Messages
    1 008
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : IT moa

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 008
    Points : 1 067
    Points
    1 067
    Par défaut
    J'ai l'impression que ta question est plus algorithmique / C++ que SQL, en tout cas je ne comprends rien à ton code désolé.

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 32
    Points
    32
    Par défaut
    salut& merci,

    mon code est assez simple en fait :
    je fais une update de mes 2 premiers champs qui doivent etre unique et dependant de 4 conditions
    numéro de four, si c'est top ou bot, numéro de profil(1 ou 2) et sur 1000pts

    du coup le premier enregistrement sera : (valeur aléatoire)
    750,900, num four 1 , top, profil1, 1er Pt
    850, 840,num four 1 , top, profil1, 2eme Pt
    ....
    ....
    450, 666,num four 1 , top, profil1, 1000eme Pt

    puis
    450, 666,num four 1 , top, profil2, 1er Pt
    850, 840,num four 1 , top, profil2, 2eme Pt
    ....
    ....
    450, 666,num four 1 , top, profil2, 1000eme Pt

    etc... donc je me retrouve avec 4000 enregistrements a "updater"...
    donc soit ma requete peut etre mieux constituée, soit ma table, soit je suis mal...

    tu vois mieux ou pas?

  4. #4
    Rédacteur/Modérateur

    Avatar de Antoun
    Homme Profil pro
    Architecte décisionnel
    Inscrit en
    Octobre 2006
    Messages
    6 283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Architecte décisionnel
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2006
    Messages : 6 283
    Points : 11 742
    Points
    11 742
    Par défaut
    Normalement, tu dois pouvoir tout faire en une requête. Ceci dit, comme je ne comprends pas mieux que Mathusalem ce que tu veux modifier en fonction de quoi, j'ai du mal à aller plus loin...
    Antoun
    Expert Tableau, Essbase, BO, SQL

    La bible d'Essbase, 2ème édition

  5. #5
    Expert éminent
    Homme Profil pro
    Big Data / Freelance EURL
    Inscrit en
    Mars 2003
    Messages
    2 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Big Data / Freelance EURL

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 124
    Points : 7 291
    Points
    7 291
    Par défaut
    J'ai du relire plusieurs fois ton code d'autant que je ne connais pas le C++. Normalement je t'aurais dit de depioter ton code pour qu'on ne voit que ton code SQL.

    Mais à y regarder de près il y a un gros problème conceptuel. Tu fais faire par ton code C++ ce qui devrait être fait en SQL ensembliste. Tu fais la même erreur que les gens qui utilisent un curseur à tout bout de champ. Les SGBDR, et donc le SQL, sont fait pour traiter un gros volume de données en une requête, UPDATE en ce qui te concerne, et non 4000 UPDATE qui se suivent.

    En d'autre termes tu devrais avoir une requête ressemblant au code ci-dessous (mais il faudrait avoir plus d'infos) qui ferait tout d'un seul coup.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    UPDATE MaTable
    SET
       champ1= Val1,
       champ2 = Val2
    FROM FUR
    left join top_data
       on .... -- jointure à définir entre champ3 et FUR
    left join s_furndata 
       on .... -- jointure à définir entre champ4 et Top
    left join thermal_profils 
       on ... -- -- jointure à définir entre champ5 et thermal_profils 
    left join thermal_profil_points  
       on ... -- -- jointure à définir entre champ6 et thermal_profil_points
    Donc il faudrait réexpliquer ton problème selon ce point de vue.

  6. #6
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 32
    Points
    32
    Par défaut
    bon je vais tenter d'etre plus clair

    j'ai 1000pts a écrire j'écris les coordonnées x et y (champ 1 et 2)
    chacun de ces points dépend d'autre variable et doit etre unique

    donc j'aurais mille pts pr 0,0,0,pt1
    0,0,0,pt2
    0,0,0,pt3
    ......
    0,0,0,pt1000

    puis 0,0,1,pt1
    0,0,1,pt2
    0,0,1,pt3
    ......
    0,0,1,pt1000

    puis 0,1,1,pt1
    0,1,1,pt2
    0,1,1,pt3
    ......
    0,1,1,pt1000

    puis 1,1,1,pt1
    1,1,1,pt2
    1,1,1,pt3
    ......
    1,1,1,pt1000

    etc...
    ce qui me donne dans mon cas 4000 requetes et 20sec pr ttes les faire

  7. #7
    Candidat au Club
    Homme Profil pro
    Architecte de système d'information
    Inscrit en
    Juin 2003
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Architecte de système d'information
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Juin 2003
    Messages : 2
    Points : 2
    Points
    2
    Par défaut
    Salut,

    A voir ton problème je dirais que la cause principale est la façon dont tu exécute ton code SQL.
    Tu utilises la methode Open sur l'object Recordset, ce qui à pour effet de créer une connexion à la DB à chaque passage dans ta boucle.
    Je te conseille de créer un object Connexion et d'utiliser la méthode Execute, ce qui te permettra de te connecter une seule fois avant ta boucle, je pense que ton code sera beaucoup plus rapide.
    Tu peux encore executer par batch de 100 ou 500 tes requetes pour optimizer l'acces a la DB.
    Dernier petit truc tu peux creer un index sur les 4 champs de ta clause where.

    Florian

  8. #8
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 32
    Points
    32
    Par défaut
    ok je vais essayer de faire comme tu dis et de juste executé les requetes ca devrait alléger effectivement...
    mais pour le reste
    " Tu peux encore executer par batch de 100 ou 500 tes requetes pour optimizer l'acces a la DB.
    Dernier petit truc tu peux creer un index sur les 4 champs de ta clause where." je ne suis pas sur de bein saisir
    aurais tu un exemple explicite STP.

    merci les gars en tout cas.

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 32
    Points
    32
    Par défaut
    je reviens sur le premier point : j'effectue une connexion au debut de programme
    comme ceci:
    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
    HRESULT hr;
    	CoInitialize(NULL);
     
    	try
    	{
    		hr = connection.CreateInstance(__uuidof(Connection));
    		//vérifie si réussite
    		if (FAILED(hr))
    		{
    			throw _com_error(hr);
    		}
    		//declare le recordset
    		_RecordsetPtr recordset;
    		hr = recordset.CreateInstance(__uuidof(Recordset));
    		//verifie si reussite
    		if (FAILED(hr))
    		{
    			throw _com_error(hr);
    		}
    		//établi la connection
    		connection->CursorLocation = adUseClient;
          HRESULT retour = connection->Open(CONNEXION_STRING, L"HMI_Admin",L"cmi", -1);     
    	}	
    	catch(_com_error &e)
    	{
    		//std::cout << "Impossible de se connecter au serveur distant";
    		MessageBox(0, (LPCSTR) e.Description(), 0, 0);
    	}
    et ensuite j'effectue différentes requetes comme dans le code + haut avec un recordset. Je ne connais pas super bien ADO c'est la premiere fois que je l'utilise...
    si tu peux m'aiguiller un peu ca serait génial.

  10. #10
    Expert éminent
    Homme Profil pro
    Big Data / Freelance EURL
    Inscrit en
    Mars 2003
    Messages
    2 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Big Data / Freelance EURL

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 124
    Points : 7 291
    Points
    7 291
    Par défaut
    Citation Envoyé par x2thez Voir le message
    "Dernier petit truc tu peux creer un index sur les 4 champs de ta clause where." je ne suis pas sur de bein saisir
    Il veut dire que pour optimiser l'accès aux données il faire sur la table cible un
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    CREATE INDEX MaTable_IDX ON MaTable (champ3, champ4, champ5, champ6)
    Arrêtes de nous balancer ton code en C++ , ici on est dans un forum SQL, on ne pourra pas t'aider en C++. Et même si on avait les connaissances en C++ il y a un minimum de pré-requis à suivre en base de données: on utilise d'abord la puissance du SGBDR avant de réinventer la roue en C++.

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 32
    Points
    32
    Par défaut
    salut,

    bon j'ai tésté l'objet connection avec execute et -->meme resultat.

    phili_b oui c'est pour cela que je suis venu sur ce forum c'est pour avoir une aide de gens plus portés sur le SQL et qui pourront m'aider soit a construire un format de table plus adéquat ou une requete plus precise ...
    CREATE INDEX MaTable_IDX ON MaTable (champ3, champ4, champ5, champ6)

    tu peux m'en dire un peu plus STP, ou faire ca et les consequences vis a vis de ce je veux faire ?

    merci en tout cas!

  12. #12
    Expert éminent
    Homme Profil pro
    Big Data / Freelance EURL
    Inscrit en
    Mars 2003
    Messages
    2 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Big Data / Freelance EURL

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 124
    Points : 7 291
    Points
    7 291
    Par défaut
    Si tu n'as pas les accès aux bases de données il faut que tu te mettes en relation avec un dba pour lancer ce code SQL.

    Mais si tu as le client SQL server qui s'appelle "Query Analyzer", et que tu es en environnement de développement tu pourras y lancer cette commande toi-même.

  13. #13
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 32
    Points
    32
    Par défaut
    oki, j'ai fait ma petite recherche google sur cette requete
    elle permet donc de créer des index permettant un acces plus rapide aux champs

    oki mais je ne vois pas trop en quoi ca m'aiderait dans mon cas?

    comment faire pour modifier 4000 enregistrements d'une seule requete?

  14. #14
    Expert éminent
    Homme Profil pro
    Big Data / Freelance EURL
    Inscrit en
    Mars 2003
    Messages
    2 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Big Data / Freelance EURL

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 124
    Points : 7 291
    Points
    7 291
    Par défaut
    Citation Envoyé par x2thez Voir le message
    oki mais je ne vois pas trop en quoi ca m'aiderait dans mon cas?
    comment faire pour modifier 4000 enregistrements d'une seule requete?
    Ben on est bien d'accord alors. Une requête faite totalement en SQL, sans boucle FOR en C++, serait quasi instantanée avec 4000 enregistrements.

    Ton C++ ne devrait être là que pour appeler cette unique requête. En d'autres termes, comme je l'ai montré dans mon exemple, les données qui sont dans tes boucles FOR devraient être dans des tables de ta base de données.

    Au pire, si tu ne peux pas créer ces tables de façons définitive, il faut qu'au préalable que tu charges ces données dans des tables temporaires, notées #ma_table en sql server, et faire ensuite faire ta requête UPDATE en une seule fois en faisant des jointures avec ces tables.

    L'avantage de ces tables temporaires est qu'elle sont propres à chaque session et se détruisent à la fin de la session automatiquement.

  15. #15
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 32
    Points
    32
    Par défaut
    en fait toutes ces données sont dans des structures de mon C++

    je n'ai pas de table avec ces données la...
    tu me dis "de les charger" mais ces données sont évolutives et changent toutes les 30secondes .... voila pourquoi je dois faire un update ...et aussi pourquoi je ne peux pas faire un UPDATE prennat trop de temps

  16. #16
    Expert éminent
    Homme Profil pro
    Big Data / Freelance EURL
    Inscrit en
    Mars 2003
    Messages
    2 124
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Big Data / Freelance EURL

    Informations forums :
    Inscription : Mars 2003
    Messages : 2 124
    Points : 7 291
    Points
    7 291
    Par défaut
    20 sec/4000=5 millièmes de secondes c'est déjà rapide, mais bon essayes tout de même l'index pour voir.
    Tu dois mettre plus temps à transmettre ta requête SQL server qu'à l'exécuter réellement.
    Et vu que tu peux difficilement, d'après ce que tu dis, charger ces coordonnées dans des tables SQL tu pourrais transmettre un curseur de données C++, ou une variable de type table C++, à une procédure Transact SQL qui récupererai ces données dans une table transact sql ou un curseur.

    ça seraite un truc du style:

    en pseudo code C++:
    création variable ma_variable_table //en fait un tableau
    open (exec Ma_procedure_SQL_server(ma_variable_table));


    En d'autre termes réécrire ta procédure C++ en Transact SQL en lui transmettant une liste de valeur. Mais l'avantage c'est qu'il n'y a pas d'aller et retour entre C++ et SQL server, tout se fait dans le moteur de bases de données.

  17. #17
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2006
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2006
    Messages : 90
    Points : 32
    Points
    32
    Par défaut
    ouais ca me parait pas mal tout ca ...
    je vais fouiller le TSQL

    je t'avoue que moi aussi quand j'ai vu 0.005sec par requete j'étais tout de meme satisfait ;-)
    pour l'instant j'ai trouver une petite parade coté C++ qui me permet d'effectuer moins de requetes et je m'en sors avec 1 ou 2sec max ce qui est deja plus correct pour la suite de mon projet

    ben merci encore pour tout et si je dois me plonger un jour plus amplement dans le SQL je saurais ou aller

Discussions similaires

  1. Réponses: 2
    Dernier message: 28/04/2009, 15h26
  2. comment faire cette fonction de temps
    Par yassin123441 dans le forum C++
    Réponses: 4
    Dernier message: 14/03/2007, 23h19
  3. [Requete] Calcul Somme entre deux temps pour chaque jour
    Par nico33307 dans le forum Requêtes et SQL.
    Réponses: 5
    Dernier message: 21/03/2006, 00h58
  4. Comment faire une mirroir en temps reels de mon ecran?
    Par pointer dans le forum DirectX
    Réponses: 7
    Dernier message: 04/06/2005, 02h56
  5. Réponses: 8
    Dernier message: 18/09/2002, 03h20

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