Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2390 connectés 

  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [MySQL] Besoin d'aide - Optimisation d'une requête très lourde

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

[MySQL] Besoin d'aide - Optimisation d'une requête très lourde

n°1201795
nero27
Posté le 18-09-2005 à 13:01:06  profilanswer
 

Bonjour à tous,
 
Voilà mon problème :
J'ai une très lourde requête qui fait planter Apache toutes les nuits car elle est loin d'être optimisée.
Voilà la requête :

Code :
  1. DELETE FROM action_historique WHERE idm NOT IN (SELECT idm FROM membre) OR idc NOT IN (SELECT idc FROM chval)


 
Le but de la requête est de supprimer tous les enregistrements d'action_historique qui sont liés à un membre qui n'existe pas ou à un chval qui n'existe pas.
Auriez-vous une idée pour optimiser cette requête ?
 
Merci d'avance :jap:

Message cité 2 fois
Message édité par nero27 le 18-09-2005 à 13:02:00
mood
Publicité
Posté le 18-09-2005 à 13:01:06  profilanswer
 

n°1201798
KangOl
Profil : pointeur
Posté le 18-09-2005 à 13:11:20  profilanswer
 

mettre des index sur les id dans tes tables :o


---------------
Nos estans firs di nosse pitite patreye...
n°1201804
betsamee
Asterisk Zeperyl
Posté le 18-09-2005 à 13:27:35  profilanswer
 

KangOl a écrit :

mettre des index sur les id dans tes tables :o


+1

n°1201911
Beegee
Posté le 18-09-2005 à 19:18:49  profilanswer
 

Index, et remplacer les NOT IN par des NOT EXISTS peut aider également.
 
DELETE FROM action_historique ah
WHERE NOT EXISTS (SELECT 1 FROM membre WHERE idm = ah.idm)
OR NOT EXISTS (SELECT 1 FROM chval WHERE idc = ah.idc);

n°1202021
nero27
Posté le 19-09-2005 à 00:03:42  profilanswer
 

Beegee a écrit :

Index, et remplacer les NOT IN par des NOT EXISTS peut aider également.
 
DELETE FROM action_historique ah
WHERE NOT EXISTS (SELECT 1 FROM membre WHERE idm = ah.idm)
OR NOT EXISTS (SELECT 1 FROM chval WHERE idc = ah.idc);


En sachant que la table contient plusieurs centaines de millions d'enregistrements, tu penses que c'est raisonnable une telle requête ?
Quand vous parlez d'index, vous voulez dire quoi ? (je ne vois pas ce que viennent faire les index là)


Message édité par nero27 le 19-09-2005 à 00:04:12
n°1202042
betsamee
Asterisk Zeperyl
Posté le 19-09-2005 à 07:23:39  profilanswer
 

ben si t'indexes les champs contenus dans tes clauses ca ira forcement plus vite
mais des centaines de milions d'enregistrements avec MySQL :ouch:

n°1202045
Koyomi
www.sebastiengilles.com
Posté le 19-09-2005 à 07:45:16  profilanswer
 

pour les index c'est une des bases de l'approche des bases de données.
 
les index permettent de diminué enormément les temps de requette sur des champs comme des id
 
 
pour ce qui est de centaines de million d'enregistrement sur mysql, comme le fait remarquer betsamee faut pas avoir peur  :D  ce sgbd ne tiens pas la route pour de tels quantités d'enregistrements

n°1202067
casimimir
Posté le 19-09-2005 à 09:21:57  profilanswer
 

effectivement un index devrait fortement améliorer les choses, car l'on peut considérer que l'on ne devra deleter qu'un nombre d'enregistrement minime par rapport au nombre total de la total,
donc, un index sur idm et un sur idc, suivant le ratio (distinct idm/nbr total enregistrement) peut-etre même un index bitmap (si ca existe en mysql)
 
et vu la taille de la table, peut-etre ne pas lancer la création d'index en journée ^^

n°1202263
nero27
Posté le 19-09-2005 à 11:44:26  profilanswer
 

J'ai dit une bêtise, pour cette table, on en est à 40 000 000 d'enregistrements.
 
Sinon, je vais regarder la doc à propos des index ;)

n°1202754
Arjuna
Aircraft Ident.: F-MBSD
Posté le 19-09-2005 à 19:54:17  profilanswer
 

40 millions ça semble plus raisonable, même si ça reste un peu gros ;)
 
sinon ++ à tout ce qui a été dit : index + not exists devrait considérablement améliorer les perfs.

mood
Publicité
Posté le 19-09-2005 à 19:54:17  profilanswer
 

n°1202812
nero27
Posté le 19-09-2005 à 21:47:11  profilanswer
 

Etant donné que idc et idm sont des clés primaires entières en auto increment, pensez-vous que des index puissent vraiment améliorer les perfs ? Il faudra quand même passer tous les enregistrements, non ?

n°1202820
Arjuna
Aircraft Ident.: F-MBSD
Posté le 19-09-2005 à 21:59:34  profilanswer
 

C'est pas dans les tables membre et chval qu'il faut mettre les index, mais dans la table action_historique.
 
Crée un index portant sur idm et idc dans cette table.

n°1202822
Arjuna
Aircraft Ident.: F-MBSD
Posté le 19-09-2005 à 22:00:35  profilanswer
 

Au fait, pourquoi n'as-tu pas fait des FK avec comme conditions sur le delete "cascade" ?
 
Ca aurait permis d'éviter cette requête, et ainsi ne traîter qu'une ligne à la fois, ce qui serait bien plus rapide ! (couple imd,idc dans un index, peut-être même unique !)

n°1202823
betsamee
Asterisk Zeperyl
Posté le 19-09-2005 à 22:01:06  profilanswer
 

nero27 a écrit :

Etant donné que idc et idm sont des clés primaires entières en auto increment, pensez-vous que des index puissent vraiment améliorer les perfs ? Il faudra quand même passer tous les enregistrements, non ?


 
non ca va pas etre terrible alors
 
essaies de lancer un optimize sur tes tables de temps en temps

n°1202824
Arjuna
Aircraft Ident.: F-MBSD
Posté le 19-09-2005 à 22:01:51  profilanswer
 

ou bien des triggers, peut importe. c'est quand même plus rapide de ne traîter qu'un nombre réduit de lignes en n'utilisant qu'une valeur unique dans un index plutôt que d'aller chercher une liste de valeurs qui n'existent pas dans deux autres tables qui peuvent être volumineuses !

n°1202825
betsamee
Asterisk Zeperyl
Posté le 19-09-2005 à 22:02:26  profilanswer
 

Arjuna a écrit :

Au fait, pourquoi n'as-tu pas fait des FK avec comme conditions sur le delete "cascade" ?
 
Ca aurait permis d'éviter cette requête, et ainsi ne traîter qu'une ligne à la fois, ce qui serait bien plus rapide ! (couple imd,idc dans un index, peut-être même unique !)


 
si ses tables sont en MyISAM alors c'est mort pour le FK

n°1202826
betsamee
Asterisk Zeperyl
Posté le 19-09-2005 à 22:03:07  profilanswer
 

Arjuna a écrit :

ou bien des triggers, peut importe.


tu parles de MySQL la  :D

n°1202827
Arjuna
Aircraft Ident.: F-MBSD
Posté le 19-09-2005 à 22:03:13  profilanswer
 

betsamee a écrit :

non ca va pas etre terrible alors
 
essaies de lancer un optimize sur tes tables de temps en temps


je pense surtout qu'il ne cherche pas à mettre l'index au bon endroit

n°1202828
Arjuna
Aircraft Ident.: F-MBSD
Posté le 19-09-2005 à 22:03:35  profilanswer
 

betsamee a écrit :

tu parles de MySQL la  :D


ah ouais c'est vrai, j'oubliait qu'il y avait des maso sur ce forum :ange:

n°1202832
betsamee
Asterisk Zeperyl
Posté le 19-09-2005 à 22:10:21  profilanswer
 

pour en revenir au probleme meme indexe a mort ca me parait pas viable une requete avec deux not in sur deux sous requetes , avec MySQL et des dizaines de milions d'enregistrements

n°1202835
Arjuna
Aircraft Ident.: F-MBSD
Posté le 19-09-2005 à 22:12:09  profilanswer
 

Bah c'est sur que y'a comme qui dirait un léger problème.
 
Faut dire qu'il n'y a pas que MySQL qui aura du mal, n'importe quel SGBD n'aime pas ce genre de requêtes.
D'où l'intérêt absolu d'utiliser des FK avec "ON DELETE CASCADE". (ou des triggers quand on travaille avec des vrais outils :D)


Message édité par Arjuna le 19-09-2005 à 22:12:52
n°1202850
nero27
Posté le 19-09-2005 à 22:46:35  profilanswer
 

Après vérification, il y a déjà un index sur idm et sur idc dans action_historique.
 
Je vais regarder du côté des FK (j'avoue que je ne sais pas ce que c'est [:totoz]) : ça me parait pas mal. Si je comprends bien, ça permet de supprimer tous les champs correspondant au même idm, c'est ça ?
C'est-à-dire, on trouve un enregistrement dans a_h pour un idm=1 dont l'idm n'existe pas dans membre, ça va tout de suite supprimer tous les enregistrements dont l'idm est 1 dans a_h en évitant de faire la recherche dans membre à chaque ligne : j'ai juste ?

n°1202856
Arjuna
Aircraft Ident.: F-MBSD
Posté le 19-09-2005 à 23:02:09  profilanswer
 

la FK permet, en temps normal, de s'assurer que lorsqu'on insère une ligne dans action_historique, que la valeur de IDM existe dans la table membre, et IDC dans la table chval.
 
Mais elle permet aussi de faire dans l'autre sens : si tu supprimes une ligne dans membre, alors ça vérifie qu'il n'y a aucune ligne avec cet IDM dans ta table d'historique.
Par défaut, si au moins une ligne en question existe, alors ça plante.
Avec la propriété "ON DELETE CASCADE", alors à ce moment, lorsque tu supprimes un membre, ça supprime toutes les lignes de action_historique faisant référence à son IDM.

n°1203079
tomlameche
Et pourquoi pas ?
Posté le 20-09-2005 à 11:17:53  profilanswer
 

Peut être une piste pour gagner en perf :
- créer une table temporaire résultat de select action_historique.* from action_historique inner join  membre inner join cheval  
- remplacer action_historique par ta table tempon (drop table + rename)
 
Donc au lieu de faire des delete, tu fait le select des enregistements qui vont bien, en général c'est plus performant.
Attention : ne pas oublier de recréer tes index après la manip


---------------
Gérez votre collection de BD en ligne ! ---- Electro-jazzy song ---- Dazie Mae - jazzy/bluesy/cabaret et plus si affinité
n°1203109
betsamee
Asterisk Zeperyl
Posté le 20-09-2005 à 11:30:31  profilanswer
 

tomlameche a écrit :

Peut être une piste pour gagner en perf :
- créer une table temporaire résultat de select action_historique.* from action_historique inner join  membre inner join cheval  
- remplacer action_historique par ta table tempon (drop table + rename)
 
Donc au lieu de faire des delete, tu fait le select des enregistements qui vont bien, en général c'est plus performant.
Attention : ne pas oublier de recréer tes index après la manip


 
 :ouch:  
c'est assez incroyable mais j'etais en train  de poster le meme conseil
 

n°1203116
Arjuna
Aircraft Ident.: F-MBSD
Posté le 20-09-2005 à 11:33:16  profilanswer
 

spa bête en effet. (mais qu'est-ce que vous êtes gores les gars :o)

n°1203150
betsamee
Asterisk Zeperyl
Posté le 20-09-2005 à 11:47:32  profilanswer
 

tomlameche a écrit :

Attention : ne pas oublier de recréer tes index après la manip


 
en revanche cette etape risque d'etre la plus longue

n°1203161
tomlameche
Et pourquoi pas ?
Posté le 20-09-2005 à 11:54:10  profilanswer
 

betsamee a écrit :

en revanche cette etape risque d'etre la plus longue


 :jap: d'où le "en général c'est plus performant", parfois la recréation des index est trop longue  :D


---------------
Gérez votre collection de BD en ligne ! ---- Electro-jazzy song ---- Dazie Mae - jazzy/bluesy/cabaret et plus si affinité
n°1203164
Arjuna
Aircraft Ident.: F-MBSD
Posté le 20-09-2005 à 11:57:41  profilanswer
 

ben ça dépend comment MySQL gère ça. S'il fait comme Oracle ou SQL Server, la création de l'index est instantannée, et il le reconstruit réellement en tâche de fond, donc ça n'influe pas sur les temps de réponse (par contre tant que les index ne sont pas fini d'être régénérés, bah... il peut pas les utiliser :D)

n°1203166
Beegee
Posté le 20-09-2005 à 11:57:57  profilanswer
 

Ce serait intéressant de savoir combien il y a de lignes dans chaque table (40 millions pour action_historique, mais combien pour les autres tables : membre/chval ?)
 
edit: et une approximation du nombre de lignes qu'on pense effacer.

Message cité 1 fois
Message édité par Beegee le 20-09-2005 à 11:58:52
n°1203172
chrisbk
-
Posté le 20-09-2005 à 12:04:54  profilanswer
 

nero27 a écrit :

Bonjour à tous,
 
Voilà mon problème :
J'ai une très lourde requête qui fait planter Apache toutes les nuits car elle est loin d'être optimisée.
Voilà la requête :

Code :
  1. DELETE FROM action_historique WHERE idm NOT IN (SELECT idm FROM membre) OR idc NOT IN (SELECT idc FROM chval)




 
40 000 000 enregistrements la dessus ? bin ca en fait un paquet de bourricot

n°1203208
tomlameche
Et pourquoi pas ?
Posté le 20-09-2005 à 12:32:21  profilanswer
 

Arjuna a écrit :

ben ça dépend comment MySQL gère ça. S'il fait comme Oracle ou SQL Server, la création de l'index est instantannée, et il le reconstruit réellement en tâche de fond, donc ça n'influe pas sur les temps de réponse (par contre tant que les index ne sont pas fini d'être régénérés, bah... il peut pas les utiliser :D)


Ah bon ?
A l'époque ou je faisait bcp de ce genre de traitement, la création des indexs ne se faisait pas comme ça, ça prenait réellement un certain temps (pour ne pas dire un temps certain). Ca marche comme ça depuis Oracle 9 ? Ou alors c'est un paramétrage de l'instance et/ou de la commande create index ? Ou alors ça depend du type d'index ?


---------------
Gérez votre collection de BD en ligne ! ---- Electro-jazzy song ---- Dazie Mae - jazzy/bluesy/cabaret et plus si affinité
n°1203218
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-09-2005 à 12:56:04  profilanswer
 

nero27 a écrit :

Bonjour à tous,
 
Voilà mon problème :
J'ai une très lourde requête qui fait planter Apache toutes les nuits car elle est loin d'être optimisée.
Voilà la requête :

Code :
  1. DELETE FROM action_historique WHERE idm NOT IN (SELECT idm FROM membre) OR idc NOT IN (SELECT idc FROM chval)


 
Le but de la requête est de supprimer tous les enregistrements d'action_historique qui sont liés à un membre qui n'existe pas ou à un chval qui n'existe pas.
Auriez-vous une idée pour optimiser cette requête ?
 
Merci d'avance :jap:


remplace tes sous requetes par des tables temporaires. je suppose que ton sgbd est mysql, les sous requetes relevent du masochisme avec mysql
 
edit: [:benou_grilled]

Message cité 1 fois
Message édité par Harkonnen le 20-09-2005 à 12:56:40
n°1203254
betsamee
Asterisk Zeperyl
Posté le 20-09-2005 à 13:31:45  profilanswer
 

Harkonnen a écrit :

les sous requetes relevent du masochisme avec mysql
edit: [:benou_grilled]


 
pas forcement ca depend de l'utilisation qu'on en fait
et comme le disait Arjuna meme un SGBD plus "professionnel" aurait certainement du mal a realiser une requete pareille

n°1203262
cooltwan
Posté le 20-09-2005 à 13:36:33  profilanswer
 

sous mysql 5 je pense que ca doit etre mieux en tout cas

n°1203267
betsamee
Asterisk Zeperyl
Posté le 20-09-2005 à 13:38:12  profilanswer
 

le 4.1.9 fait ca tres bien aussi


Message édité par betsamee le 20-09-2005 à 13:38:35
n°1203277
betsamee
Asterisk Zeperyl
Posté le 20-09-2005 à 13:44:26  profilanswer
 

le principe est de chercher a mettre la sous requete dans le From si possible et non pas le where

n°1203366
Arjuna
Aircraft Ident.: F-MBSD
Posté le 20-09-2005 à 14:26:48  profilanswer
 

tomlameche a écrit :

Ah bon ?
A l'époque ou je faisait bcp de ce genre de traitement, la création des indexs ne se faisait pas comme ça, ça prenait réellement un certain temps (pour ne pas dire un temps certain). Ca marche comme ça depuis Oracle 9 ? Ou alors c'est un paramétrage de l'instance et/ou de la commande create index ? Ou alors ça depend du type d'index ?


Ben chais pas, quand j'étais chez GE (avec un Serveur HP sous SunOS / Oracle 8i) la création d'un index était rigoureusement instantannée (ou ça prenait une petite dizaine de secondes).
Puis ensuite si on faisait une requête tapant normalement dans l'index, il ne l'utilisait pas. Avec un table hint, on obtenait une erreur comme quoi l'index n'était pas prêt.
Puis au bout de quelques minutes ça marchait.
 
Par contre, maintenant que tu m'y fait penser c'est vrai que... il fallait faire une oppération spéciale pour que ça marche... me souvient plus du tout quoi ! Parceque dans TOAD ça mettait un peu plus de temps. Et vu que la machine était quelque peut grosse (pintaprocesseur - me demandez pas pourquoi 5 et pas un multiple de deux :D avec deux SAN dédiés aux bases et quelque 4 Go de mémoire par CPU) donc forcément, même un index sur 25 champ sur une table de 50 000 000 lignes ça mettait pas très longtemps à se créer...
M'enfin sur et certain, dans notre batch de réplication de la base depuis le serveur de l'ERP vers la base dédiée au Web, via SQL Loader, (suppression des index, truncate, allimentation puis indexation), l'indexation qui suivait était rigoureusement instantannée, et pourtant le volume des données était pire (dénormalisation et duplication des valeurs de référence pour de meilleures performances en lecture) alors que le serveur était... le même :D

Message cité 1 fois
Message édité par Arjuna le 20-09-2005 à 14:31:09
n°1203369
Arjuna
Aircraft Ident.: F-MBSD
Posté le 20-09-2005 à 14:27:37  profilanswer
 

tomlameche a écrit :

Ah bon ?
A l'époque ou je faisait bcp de ce genre de traitement, la création des indexs ne se faisait pas comme ça, ça prenait réellement un certain temps (pour ne pas dire un temps certain). Ca marche comme ça depuis Oracle 9 ? Ou alors c'est un paramétrage de l'instance et/ou de la commande create index ? Ou alors ça depend du type d'index ?


PS: c'était de bêtes "create index", sans spécifier le type

n°1203382
nero27
Posté le 20-09-2005 à 14:33:23  profilanswer
 

Beegee a écrit :

Ce serait intéressant de savoir combien il y a de lignes dans chaque table (40 millions pour action_historique, mais combien pour les autres tables : membre/chval ?)
 
edit: et une approximation du nombre de lignes qu'on pense effacer.


Environ 150 000 pour membre et 190 000 pour chval.
Il y a, je pense quelques centaines d'enregistrements à effacer.
 
Pour info, la version de MySQL est la 4.1.13
Le serveur est un bi-Xeon (2.8 ou 3GHz, je ne sais plus) avec 2Go de RAM, SCSI+Raid1.


Message édité par nero27 le 20-09-2005 à 14:40:20
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  SQL/NoSQL

  [MySQL] Besoin d'aide - Optimisation d'une requête très lourde

 

Sujets relatifs
[réglé]Besoin d'aide avec SQL d'OracleProbleme de requete et de texte en php [Résolu, euh en fait non]
Besoin de conseils pour oracle 10gurl rewriting... besoin de conseils pour ma page
Pb "too connection" a mon serveur mysqlResultat d'une requete parametre dans zone de liste !!
petit pb requeteProbleme de requete
MySQL aide pour select 
Plus de sujets relatifs à : [MySQL] Besoin d'aide - Optimisation d'une requête très lourde


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR