Précédent   Forum des professionnels en informatique > Bases de données > MySQL > Requêtes
Requêtes Forum d'entraide sur les requêtes MySQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 25/04/2011, 15h47   #1
Membre à l'essai
 
Inscription : novembre 2006
Messages : 121
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 121
Points : 22
Points : 22
Par défaut Performance catastrophique requête imbriquée

Bonjour,

J'ai une requête composée qui prend anormalement beaucoup de temps :

Code :
1
2
3
4
5
6
7
8
9
 
SELECT user_id, username, user_type, user_posts
FROM phpbb_users
WHERE user_id IN(
	SELECT DISTINCT topic_poster AS user_id
	FROM phpbb_topics
	WHERE forum_id = 33
)
-- Affichage des enregistrements 0 - 29 (57 total, Traitement en 23.9452 sec.)
Alors j'ai testé les deux requêtes séparément, et là elles s'exécutent normalement (très rapide) :


Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
/*
 * Requête principale
 */
SELECT user_id, username, user_type, user_posts
FROM phpbb_users
WHERE user_id IN(
	1622, 1668, 1691, 1701, 1720, 1696, 1767, 1763, 1822, 1855, 1889, 1874,
	1908, 1916, 1920, 1925, 1909, 1955, 1956, 1975, 1991, 2576, 2671, 2667,
	2668, 2713, 2724, 2726, 2738, 2740, 2750, 2751, 2755, 2758, 2759, 2753,
	2771, 2772, 2773, 2775, 2782, 2813, 2848, 2851, 2868, 2879, 2899, 2814,
	2910, 2922, 2909, 2897, 2709, 2893, 2933, 2754, 2923
)
-- Affichage des enregistrements 0 - 29 (57 total, Traitement en 0.0008 sec.)
 
 
/*
 * Sous-requête
 */
SELECT DISTINCT topic_poster AS user_id
FROM phpbb_topics
WHERE forum_id = 33
-- Affichage des enregistrements 0 - 29 (57 total, Traitement en 0.0015 sec.)

Ensuite j'ai lancé un profilage de ma requête, et ça crache de partout, je vois plein de "Copying to tmp table", vous pouvez voir tout le profilage ici.

Comment faire pour corriger ce problème ?

Merci
Galdon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/04/2011, 17h05   #2
Rédacteur/Modérateur

 
Avatar de SQLpro
 
Homme Frédéric BROUARD
Expert SGBDR & SQL
Inscription : mai 2002
Messages : 10 953
Détails du profil
Informations personnelles :
Nom : Homme Frédéric BROUARD
Localisation : France

Informations professionnelles :
Activité : Expert SGBDR & SQL
Secteur : Conseil

Informations forums :
Inscription : mai 2002
Messages : 10 953
Points : 17 773
Points : 17 773
Malheureusement MySQL n'a jamais été conçu pour avoir de bonnes performances sur les requêtes, contrairement à une idée reçue...
Voici ce que je Pense de MySQL : http://blog.developpez.com/sqlpro/p9...udre-aux-yeux/
Et voici un Benchmark : http://blog.developpez.com/sqlpro/p9...lles-en-sql-1/
Bref, si vous voulez réellement des performances, prenez un vrai SGBD relationnel et non ersatz.... Regardez par exemple du côté de PostGreSQL ou mieux SQL Server (version gratuite avec Express 2008 R2)...

Dans l'immédiate, avent de passer à un autre SGBDR plus performant, vérifiez cependant que vous avez bien un index sur :
Code :
phpbb_topics (forum_id , topic_poster)
et sur
Code :
phpbb_users (user_id, username, user_type, user_posts)
Si c'est possible !

A +
__________________
Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
Site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
Blog SQL, SQL Server, modélisation données : http://blog.developpez.com/sqlpro
http://www.sqlspot.com : modélisation, conseils, audit, optimisation, formation
* * * * * Enseignant CNAM PACA - ISEN Toulon - CESI Aix en Provence * * * * *
SQLpro est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/04/2011, 17h54   #3
Membre à l'essai
 
Inscription : novembre 2006
Messages : 121
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 121
Points : 22
Points : 22
Je viens de chercher "Copying to tmp table" dans le moteur de recherche interne de ce forum :

http://www.developpez.net/forums/d98...-surtout-vues/
http://www.developpez.net/forums/d86...ichiers-mysql/
http://www.developpez.net/forums/d75...ter-jointures/
http://www.developpez.net/forums/d56...le-temporaire/
http://www.developpez.net/forums/d19...lus-courantes/
http://www.developpez.net/forums/d28...ation-requete/
http://www.developpez.net/forums/d11...le-manque-ram/
http://www.phpbb.com/community/viewtopic.php?t=369256
http://www.developpez.net/forums/d11...requete-phpbb/

Et j'ai remarqué que dans beaucoup de ces topics, des tables phpbb sont impliquées. Ça ne va pas être simple je crois, je vais faire des tests avec les tables phpbb_users et phpbb_topics, en ajoutant ou en supprimant des index, en changeant de moteur...
Galdon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/04/2011, 18h01   #4
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 843
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
Localisation : France, Isère (Rhône Alpes)

Informations professionnelles :
Activité : Développeur informatique
Secteur : High Tech - Multimédia et Internet

Informations forums :
Inscription : avril 2011
Messages : 843
Points : 1 318
Points : 1 318
Salut,

si ton champ forum_id n'est pas indexé, ça peut expliquer la lenteur mais normalement phpbb le fait. j'avoue que phpbb est plutot pas très bien programmé sur certains trucs

Il semble que mysql refasse la recherche de la sous requête (d'où le re-remplissage de la table temporaire autan de fois) pour chaque itération de la requête principale. Le problème c'est que c'est pas documenté.

Au pire tu peux faire la requête temporaire à la main et de faire ta sous requête avec elle du genre:
Code sql :
1
2
3
4
5
6
7
8
CREATE tempory TABLE tmp
SELECT DISTINCT topic_poster AS user_id
	FROM phpbb_topics
	WHERE forum_id = 33;
SELECT user_id, username, user_type, user_posts
FROM phpbb_users
WHERE user_id IN(
SELECT user_id FROM tmp);

Idéalement le mieux est de faire un procédure stockée qui encapsule tout ça :

Code sql :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
USE bidule;
DROP procedure IF exist get_poster;
delimiter |
CREATE procedure get_poster(IN f_id int(4))
begin
CREATE tempory TABLE tmp
SELECT DISTINCT topic_poster AS user_id
	FROM phpbb_topics
	WHERE forum_id = f_id;
SELECT user_id, username, user_type, user_posts
FROM phpbb_users
WHERE user_id IN(
SELECT user_id FROM tmp);
DROP TABLE tmp;
end|
delimiter ;

Bidule est le nom de la bd où tu as mis phpbb. Pour le résultat:

Code sql :
call get_poster(33);
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/04/2011, 19h18   #5
Membre à l'essai
 
Inscription : novembre 2006
Messages : 121
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 121
Points : 22
Points : 22
Merci, sinon on m'a proposé une requête qui fonctionne impec sur un autre forum :

Code :
1
2
3
4
5
6
7
8
SELECT phpbb_users.user_id, username, user_type, user_posts
FROM phpbb_users
INNER JOIN (
    SELECT DISTINCT topic_poster
      FROM phpbb_topics
    WHERE forum_id = 33
) x
ON x.topic_poster = phpbb_users.user_id
Apparemment le problème viendrait de l'analyseur de requête MySQL qui a parfois de drôles d'interprétations.
Galdon est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 25/04/2011, 19h27   #6
Membre Expert
 
Homme Eric Dureuil
Développeur informatique
Inscription : avril 2011
Messages : 843
Détails du profil
Informations personnelles :
Nom : Homme Eric Dureuil
Localisation : France, Isère (Rhône Alpes)

Informations professionnelles :
Activité : Développeur informatique
Secteur : High Tech - Multimédia et Internet

Informations forums :
Inscription : avril 2011
Messages : 843
Points : 1 318
Points : 1 318
oui c'est assez mal documenté

faut parfois forcer les choses, comme l'obliger à choisir tel index...

en tout cas, l'utilisation de procédure stockée est bénéfique en terme de quantité de données échangées entre sgbd et langage interrogeant, et ça simplifie l'écriture de ton code coté applicatif en permettant des choses très compliquée...
ericd69 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 06h52.


 
 
 
 
Partenaires

Hébergement Web