Problème de requête, CPU à 100%... [résolu] - SQL/NoSQL - Programmation
Marsh Posté le 26-07-2005 à 15:17:55
Tu peux pas la faire sans sous-requête?
du style:
select * from historique_login where login_timestamp < (NOW( ) - INTERVAL 1 MONTH )
Marsh Posté le 26-07-2005 à 15:18:03
Remplace le NOT IN par un NOT EXISTS pour voir.
Code :
|
Marsh Posté le 26-07-2005 à 15:18:33
Beegee a écrit : Remplace le NOT IN par un NOT EXISTS pour voir.
|
Mais !
Marsh Posté le 26-07-2005 à 15:19:08
skeye a écrit : Tu peux pas la faire sans sous-requête? |
Ben non, vu sa demande, il veut pas voir les utilisateurs qui se sont connectés durant le dernier mois
Marsh Posté le 26-07-2005 à 15:19:47
Beegee a écrit : Ben non, vu sa demande, il veut pas voir les utilisateurs qui se sont connectés durant le dernier mois |
c'est pas ce que j'ai écrit?
Marsh Posté le 26-07-2005 à 15:20:54
Non, tu sélectionnes l'historique de plus d'un mois de tous les utilisateurs.
Ce n'est pas la même chose que l'historique complet des utilisateurs non connectés durant le dernier mois.
Marsh Posté le 26-07-2005 à 15:25:11
Beegee a écrit : Non, tu sélectionnes l'historique de plus d'un mois de tous les utilisateurs. |
Exactement.
Sinon en remplaçant le NOT IN par NOT EXISTS j'ai une erreur de syntaxe :
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'EXISTS (SELECT login_loginname FROM historique_login WHERE login_timestamp > (NO' at line 1
Marsh Posté le 26-07-2005 à 15:25:14
Beegee a écrit : Non, tu sélectionnes l'historique de plus d'un mois de tous les utilisateurs. |
ah oui.
Ca empêche pas de le faire sans sous-requête.
select max(login_timestamp), champ2, champ3
from historique_login
where login_timestamp < (NOW( ) - INTERVAL 1 MONTH )
group by (champ2, champ3)
[edit]
encore raté...
Marsh Posté le 26-07-2005 à 15:26:29
bah pourquoi pas ça simplement :
SELECT * FROM historique_login WHERE login_timestamp <= (NOW( ) - INTERVAL 1 MONTH ))
Si tu supprimes les logins de plus d'un mois alors il suffit de garder ceux de moins d'un mois... comment faire simple quand on peut faire compliqué
Marsh Posté le 26-07-2005 à 15:27:17
RaTo a écrit : Exactement. |
essaye d'aliaser ta table dans la requête imbriquée, aussi.
Marsh Posté le 26-07-2005 à 15:27:53
megadub a écrit : bah pourquoi pas ça simplement : |
Bien vu, même connerie que moi!
J'avais pas pensé non plus qu'il conservait tout son historique...
Marsh Posté le 26-07-2005 à 15:31:57
par curiosité, ya combien de lignes dans ta table historique_login?
[edit]
Question subsidiaire : ne serait-ce pas intéressant de la transformer en dernier_login?
Marsh Posté le 26-07-2005 à 15:32:33
Vérifie déjà que dans ta version de MySQL y'a bien le EXISTS qui est supporté. Apparement, il ne l'est pas.
S'il ne supporte pas, alors change de version (super, j'adore ce SGBD ) ou tu peux aussi d'apporter une légère optimisation à ton NOT IN en résuidant la liste qu'il retourne :
Code :
|
C'est pas forcément énorme comme optimisation, mais ça devrait aider.
Ensuite, n'oublie pas de créer deux index :
historique_login(login_timestamp, login_loginname)
historique_login(login_loginname)
Le premier devant pouvoir être unique (en comptant qu'une personne ne se logue normalement pas deux fois dans la même milli-seconde.
Marsh Posté le 26-07-2005 à 15:32:50
En balaçant la requête :
Code :
|
Même résultat qu'avec la mienne, plantage de mysql...
Marsh Posté le 26-07-2005 à 15:34:09
Autre question qui va avec : y a-t-il un index sur login_loginname ?
Marsh Posté le 26-07-2005 à 15:36:10
skeye a écrit : Bien vu, même connerie que moi! |
ha oui, alors :
Code :
|
ça devrait le faire ça non ?
Marsh Posté le 26-07-2005 à 15:36:26
skeye a écrit : par curiosité, ya combien de lignes dans ta table historique_login? |
22 116
skeye a écrit : Question subsidiaire : ne serait-ce pas intéressant de la transformer en dernier_login? |
Marsh Posté le 26-07-2005 à 15:37:17
Vu que EXISTS ne semble pas supporté, passage par jointure externe, comme d'hab'
Code :
|
Il suffit d'avoir un index sur login_loginname.
edit: si tu veux juste les logins et que tu n'as pas besoin de l'historique, alors tu peux faire ça aussi :
Code :
|
Marsh Posté le 26-07-2005 à 15:37:21
megadub a écrit : ha oui, alors :
|
c'est le genre de trucs que j'ai proposé aussi...tu vas avoir pour tous les utilisateurs le plus récent login ayant plus d'un mois...
Marsh Posté le 26-07-2005 à 15:37:41
A mon avis, il faut surtout un group by (pour faire un distinct) dans la sous-requête.
En effet, même si ce sont des doublons, un NOT IN pourtant sur des milliers de valeurs, ben ça fait tout tomber. Avec un distinct, y'en aura forcément infiniment moins, et ça devrait grandement améliorer l'éxécution du NOT IN
Marsh Posté le 26-07-2005 à 15:39:20
Bah ça a un intérêt de garder l'historique complet de tous les logins de tes utilisateurs, en vrai?
Parce-que si non, tu gardes la date du dernier login pour chaque utilisateur, et basta...ce qui résoud aussi le pb...
Marsh Posté le 26-07-2005 à 15:39:51
Arjuna a écrit : Vérifie déjà que dans ta version de MySQL y'a bien le EXISTS qui est supporté. Apparement, il ne l'est pas. |
Je pense que le EXISTS est bien dans la version de MySQL que j'utilise, car j'arrive à faire des requêtes du style "DROP TABLE IF EXISTS..."
La version : 4.1.10a
Marsh Posté le 26-07-2005 à 15:41:42
Je t'ai donné 2 requêtes qui devraient marcher, juste au-dessus, y a pas besoin de EXISTS de toute façon.
Marsh Posté le 26-07-2005 à 15:42:43
skeye a écrit : Bah ça a un intérêt de garder l'historique complet de tous les logins de tes utilisateurs, en vrai? |
Oui. (enfin c'est une exigence de mon supérieur, donc je ne peux pas modifier ça)
Marsh Posté le 26-07-2005 à 15:43:10
skeye a écrit : c'est le genre de trucs que j'ai proposé aussi...tu vas avoir pour tous les utilisateurs le plus récent login ayant plus d'un mois... |
exact
Marsh Posté le 26-07-2005 à 15:43:18
bon, alors voir plus haut les suggestions de beegee et arjuna...
Marsh Posté le 26-07-2005 à 15:44:37
Je pense que la bonne piste effectivement c'est de réduire au max le nombre de réponses de la sous-requête...
Marsh Posté le 26-07-2005 à 15:54:48
Arjuna a écrit : Personne veut suivre ma requête |
J'ai créé les index et balancé ta requête, ça tourne là, ça à l'air de ramer tout autant...
Je crois que le problème c'est en fait les 22 000 lignes.
Marsh Posté le 26-07-2005 à 15:55:50
RaTo a écrit : J'ai créé les index et balancé ta requête, ça tourne là, ça à l'air de ramer tout autant... |
22000 c'est pas la mer à boire non plus...à moins que le serveur soit vraiment juste ya pas de raison que ce soit si lent!
Marsh Posté le 26-07-2005 à 15:59:31
RaTo a écrit : J'ai créé les index et balancé ta requête, ça tourne là, ça à l'air de ramer tout autant... |
ça tourne toujours..
Marsh Posté le 26-07-2005 à 18:37:25
C'est étrange que ça ramme autant, t'as combien de login différents ?
Parcequ'un IN, c'est lent, certes, mais à la base, si le nombre est limité, ça doit quand même pas prendre des siècles... Idem pour un group by sur 22000 lignes, ça représente pas un gros volume.
Une requête normale fonctionne ?
Marsh Posté le 26-07-2005 à 19:52:10
Bonsoir les amis,
Je vous réponds juste, je continuerai à tester demain au boulot, là je ne peux pas, merci de votre aide.
Marsh Posté le 27-07-2005 à 09:36:32
Arjuna a écrit : C'est étrange que ça ramme autant, t'as combien de login différents ? |
582.
Arjuna a écrit : |
Oui.
Marsh Posté le 26-07-2005 à 15:12:51
Je dois écrire une requête qui me retourne la liste des personnes non connectées depuis 1 mois (à un réseau).
La requête que j'ai écris :
SELECT * FROM historique_login WHERE login_loginname NOT IN (SELECT login_loginname FROM historique_login WHERE login_timestamp > (NOW( ) - INTERVAL 1 MONTH ))
Quand je lance la requête dans phpMyAdmin, la page se charge très lentement et se bloque. Je n'arrive pas à afficher de résultats. Le processus mysqld-nt.exe consomme à ce moment 99% du CPU et met longtemps à redescendre, même quand je tente d'arrêter l'exécution de la requête.
Qu'est-ce qui cloche dans cette requête ?
Message édité par RaTo le 27-07-2005 à 11:28:08