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 :

Grosses opérations... avez-vous une requête efficace ?


Sujet :

Langage SQL

  1. #1
    Membre averti Avatar de Huntress
    Femme Profil pro
    Inscrit en
    Août 2004
    Messages
    475
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 475
    Points : 402
    Points
    402
    Par défaut Grosses opérations... avez-vous une requête efficace ?
    Bonjour les gens,

    J'ai un gros soucis qui vient de m'arriver, je suis en charge de plusieurs développements et la partie de l'un d'entre eux doit être une sorte de backup.

    En fait je dois dédoubler des données et ce de 2 manières différentes :
    - Partir d'une table d'origine et avoir une table copie (identique).
    - Ou alors partir de plusieurs tables d'origine et arriver à une table copie (qui serait en fait la concaténation des champs de plusieurs autres tables d'originie).

    La première partie est simple à réaliser (même si une optimisation ne serait pas de trop compte tenu du temps d'exécution).
    Quant à la seconde partie, c'est tout bonnemenent une catastrophe.
    >>> Au fait je travaille avec les composants du pack EasyPHP 1.8.

    Je m'explique il me faudrait trouver des requetes qui puissent me permettre de faire ce que j'ai énoncé un peu plus haut. Quelque chose de rapide, parce que mes tables sont très grosses.
    Pour la copie que j'essaye de faire actuellement je dois requeter sur des tables faisant 2.500.000, 225.000, et 2.300 lignes (soit 310 Mo, 40 Mo et 320 Ko). Et tout à l'heure je suis même arrivée à un "MySQL client run out of memory". J'ai bien tenté de rajouter des index sur les champs utilisé dans la clause WHERE, mais bon...

    Donc au delà du PHP j'aimerais connaître un moyen rapide et efficace de faire ce genre d'opération (opération qui sera répétée peut être une fois par jour, en fait il ne s'agit pas vraiment de backup mais plutôt de mise à jour). J'ai vu la commande BACKUP... mais je sais pas vraiment si elle peut m'être utile...

    Merci de m'aider.

  2. #2
    Membre averti Avatar de Huntress
    Femme Profil pro
    Inscrit en
    Août 2004
    Messages
    475
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 475
    Points : 402
    Points
    402
    Par défaut
    J'ai peut être pas été assez précise ?

  3. #3
    Xo
    Xo est déconnecté
    Expert confirmé
    Avatar de Xo
    Inscrit en
    Janvier 2005
    Messages
    2 701
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 701
    Points : 4 238
    Points
    4 238
    Par défaut
    Citation Envoyé par Huntress
    J'ai peut être pas été assez précise ?
    Non, je pense que ça n'est pas le problème :

    Si j'ai bien compris, ton souci n'est pas vraiment le SQL, mais plutôt les performances de ton SGBD (ou de ton serveur ?), voire un utilitaire de sauvegarde sachant extraire des données dans du MySql. Et là, je ne suis pas sûr que ce forum soit le mieux adapté ?

    Perso, j'aurais pensé à une solution du type réplication. J'ai vu qu'il existait des tutos à ce sujet : http://jgrondin.developpez.com/artic...ication_MySQL/

    En espérant que ça te donne des idées

  4. #4
    Membre averti Avatar de Huntress
    Femme Profil pro
    Inscrit en
    Août 2004
    Messages
    475
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 475
    Points : 402
    Points
    402
    Par défaut
    Merci beaucoup de t'interesser à ce post ô combien impopulaire

    Ce lien m'aidera j'espère, en tout cas, je le lirais avec attention ce week end.
    Mais je pense pas que tout puisse se faire comme ça dans ma problématique. Alors je vous mets un exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Table infos
          id | info
     
          1  | nom
          2  | tel
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Table niveau_confidentialite
          id | niveau
     
          1  | sensible
          2  | insensible

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Table personnes
          id | id_info  |   valeur  | sensibilite
     
          1  |    1     | dupont    | 2
          1  |    2     | 01.43...  | 1
     
          2  |    1     | martin    | 2
          2  |    2     | 01.45...  | 1
    Bon j'ai super simplifié le truc hein... et me suis vachement pris la tête à écrire ça...

    Donc voilà pour la structure et les données des tables d'origine.
    Moi je voudrais pouvoir récupérer et mettre dans une autre table ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Table copie
          id | nom | tel

    Ca parait con... et ça l'est peut être mais je vois pas quelle tête la requête pourrait avoir... N'oubliez pas que mes tables sont gigantesques et que j'aimerais faire ça en une seule requête...
    Je crois au père noel ou bien c'est réalisable ?

    Si vous voyez pas ce qui me gêne c'est au niveau du champs id_info de la table personnes... 2 type de données sont stockées dans ce même champ...

  5. #5
    Xo
    Xo est déconnecté
    Expert confirmé
    Avatar de Xo
    Inscrit en
    Janvier 2005
    Messages
    2 701
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 701
    Points : 4 238
    Points
    4 238
    Par défaut
    Citation Envoyé par Huntress
    N'oubliez pas que mes tables sont gigantesques et que j'aimerais faire ça en une seule requête...
    Je crois au père noel ou bien c'est réalisable ?
    Au niveau SQL, ça a l'air assez simple. C'est bien au niveau du volume des données à traiter que ça pose problème !

    Perso, je bosse sous Oracle. J'aurais à faire ce que tu dois faire, je développerais une procédure (PL/SQL donc), dans laquelle je créerai un curseur renvoyant les données à insérer dans copie, et je bouclerai sur ce curseur pour insérer les données, avec un COMMIT régulier (ex : tous les 100 enregistrements).

    A essayer de tout insérer d'un coup, les performances vont se dégrader au fur et à mesure que les segments d'annulation (RollBack segments) se remplissent, et tu risque de les exploser au final ...

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 849
    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 : 21 849
    Points : 52 975
    Points
    52 975
    Billets dans le blog
    6
    Par défaut
    C'est idiot de faire avec un curseur, cela dégradera encore plus les perfs...

    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
    CREATE TABLE T_infos_INF
    (INF_ID   INTEGER,
     INF_INFO VARCHAR(12))
     
    INSERT INTO T_infos_INF VALUES (1, 'nom')
    INSERT INTO T_infos_INF VALUES (2, 'tel')
     
    CREATE TABLE T_niveau_confidentialite_NVC
    (NVC_ID     INTEGER,
     NVC_NIVEAU VARCHAR(12))
     
    INSERT INTO T_niveau_confidentialite_NVC VALUES (1, 'sensible')
    INSERT INTO T_niveau_confidentialite_NVC VALUES (2, 'insensible')
     
    CREATE TABLE T_personne_PRS
    (PRS_ID     INTEGER,
     INF_ID     INTEGER,
     PRS_VALEUR VARCHAR(16),
     NVC_ID     INTEGER)
     
    INSERT INTO T_personne_PRS VALUES (1, 1, 'dupont', 2)
    INSERT INTO T_personne_PRS VALUES (1, 2, '01.43...', 1)
    INSERT INTO T_personne_PRS VALUES (2, 1, 'martin', 2)
    INSERT INTO T_personne_PRS VALUES (2, 2, '01.45...', 1)
    Il veut :

    Solution

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT PS1.PRS_ID as "id", PS1.PRS_VALEUR as nom, PS2.PRS_VALEUR as tel
    FROM   T_personne_PRS PS1
           LEFT OUTER JOIN T_personne_PRS PS2
                ON PS1.PRS_ID = PS2.PRS_ID
    WHERE  PS1.INF_ID = 1
      AND  PS2.INF_ID = 2
    Pour ne pas obtenir des temps de réponse délirant, voir si les colonnes sont indexées.

    Si tu veut alimenter une table (j'en voit pas l'intérêt car redondance...), ajoute au dessus de cette requête un INSERT INTO <nom_table>

    Si l'insertion est longue faire par blocs en découpant par exemple au niveau des id des personnes.

    Exemple : Soit :
    COUNT(DISTINCT PRS_ID) = 30 000
    MIN(PRS_ID) = 1
    MAX(PRS_ID) = 40000
    Et faire cela en 10 lots :

    première requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT PS1.PRS_ID as "id", PS1.PRS_VALEUR as nom, PS2.PRS_VALEUR as tel
    FROM   T_personne_PRS PS1
           LEFT OUTER JOIN T_personne_PRS PS2
                ON PS1.PRS_ID = PS2.PRS_ID
    WHERE  PS1.INF_ID = 1
      AND  PS2.INF_ID = 2
      AND  PS1.PRS_ID BETWEEN 1 AND 4444
    seconde requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT PS1.PRS_ID as "id", PS1.PRS_VALEUR as nom, PS2.PRS_VALEUR as tel
    FROM   T_personne_PRS PS1
           LEFT OUTER JOIN T_personne_PRS PS2
                ON PS1.PRS_ID = PS2.PRS_ID
    WHERE  PS1.INF_ID = 1
      AND  PS2.INF_ID = 2
      AND  PS1.PRS_ID BETWEEN 4445 AND 8888
    ...

    Dernière requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    SELECT PS1.PRS_ID as "id", PS1.PRS_VALEUR as nom, PS2.PRS_VALEUR as tel
    FROM   T_personne_PRS PS1
           LEFT OUTER JOIN T_personne_PRS PS2
                ON PS1.PRS_ID = PS2.PRS_ID
    WHERE  PS1.INF_ID = 1
      AND  PS2.INF_ID = 2
      AND  PS1.PRS_ID BETWEEN 35556 AND 40000
    A +

  7. #7
    Xo
    Xo est déconnecté
    Expert confirmé
    Avatar de Xo
    Inscrit en
    Janvier 2005
    Messages
    2 701
    Détails du profil
    Informations personnelles :
    Âge : 51

    Informations forums :
    Inscription : Janvier 2005
    Messages : 2 701
    Points : 4 238
    Points
    4 238
    Par défaut
    Citation Envoyé par SQLpro
    C'est idiot de faire avec un curseur, cela dégradera encore plus les perfs...
    Le fait d'être compétent donne-t'il le droit d'être désagréable et grossier ?

    Citation Envoyé par SQLpro
    Si l'insertion est longue faire par blocs en découpant par exemple au niveau des id des personnes.
    Oui, d'où la solution via un curseur que je proposais ...

  8. #8
    Membre averti Avatar de Huntress
    Femme Profil pro
    Inscrit en
    Août 2004
    Messages
    475
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 475
    Points : 402
    Points
    402
    Par défaut
    Arpès avoir été impopulaire ce post devient passionné !

    Merci à vous deux et des solutions que vous proposez, j'ai vraiment pas eu le temps et surtout les moyens de les étudier. Il s'agirait maintenant de m'améliorer une p'tit peu en SQL parce que là je me rends compte que c'est bien plus riche que ce que je pensais.

    Encore merci, et je vous tiens au courant.

  9. #9
    Membre averti Avatar de Huntress
    Femme Profil pro
    Inscrit en
    Août 2004
    Messages
    475
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Août 2004
    Messages : 475
    Points : 402
    Points
    402
    Par défaut
    me revalà,

    alors j'avais commencé un traitement par lot de 100 requêtes pour arriver à un total d'à peu près un demi million de lignes... tout tournait à merveille, quand soudain les ordres changèrent... autrement dit, tout ça m'a été utile mais je dois revoir toute la méthodologie du début pour faire ce script.

    Merci à vous.

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

Discussions similaires

  1. Avez vous une date ?
    Par dtavan dans le forum Général Dotnet
    Réponses: 1
    Dernier message: 24/02/2007, 01h27
  2. Plantage de programme : avez-vous une explication ?
    Par tlpwd dans le forum x86 32-bits / 64-bits
    Réponses: 2
    Dernier message: 30/01/2007, 14h10
  3. avez-vous une solution Action script (exemple à l'appuie)
    Par lokis dans le forum ActionScript 1 & ActionScript 2
    Réponses: 4
    Dernier message: 12/01/2007, 16h42
  4. Réponses: 1
    Dernier message: 16/06/2006, 15h34
  5. Réponses: 24
    Dernier message: 20/05/2006, 12h29

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