|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | ||
|
Futur Membre du Club
![]() Inscription : mars 2005 Messages : 96 ![]() |
Bonjour tout le monde
Je cherche a faire un peu d'analyse de donnees sur mes tables, et je commence a tomber sur des cas assez recurrents qui me posent probleme. Admettons que j'ai 3 tables. Une table "community" avec 1 colonne "id" et d'autres attributs Une table "user", de meme. Une table "community_user" qui me modelise la relation ManyToMany entre les deux. Si je veux par exemple le nombre de moins de 30 ans par communaute, pas de soucis Code :
SELECT community_id, count(user_id) FROM community_user, user WHERE id=user_id AND age<30 GROUP BY community_id J'avais commence quelque chose avec des clauses select imbriquees dans mon from, mais je me suis vite rendu compte que mon extraction commencait apres que ces select aient ete faits en integralite. Si je rajoute un limit 10 a la fin par exemple, je dois quand meme patienter jusqu'a la fin des select. Ainsi, Code :
Y a-t'il une meilleure methode pour faire cela ? Le SELECT CASE n'est pas satisfaisant, parce que les filtres que je veux appliquer ne sont pas forcement disjoints. Les Window Functions (je suis sous Postgresql) m'ont ete recommandees, mais je ne vois pas du tout comment elles peuvent m'aider... Les UNION ne me semblent pas tres "propres" dans ce cas, compare aux jointures (mais vu ce que j'y connais...) |
||
|
|
00
|
|
|
#2 | ||
|
Futur Membre du Club
![]() Inscription : mars 2005 Messages : 96 ![]() |
Je viens de penser a ca
Code :
|
||
|
|
00
|
|
|
#3 | ||
![]() ![]() |
Il faut utiliser CASE et additionner ceux qui répondent à la condition au lieu de les compter.
Au passage, les jointures s'écrivent depuis 20 ans avec l'opérateur JOIN ; il serait temps de s'y mettre ! Et indente et aère ton code, il sera plus facile à lire et à débugguer. Code :
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique. Autoentrepreneur. Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework... « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau) À la maison comme au bureau, j'utilise la suite Linux Mageïa ! |
||
|
10
|
|
|
#4 |
|
Futur Membre du Club
![]() Inscription : mars 2005 Messages : 96 ![]() |
Merci pour la piste. Je vais lancer un test en taille reelle sur mes tables pour voir comment les differentes approches se comportent. A ce rythme la, ca prendra tout le week-end ^^
En ce qui concerne le WHERE, c'est une mauvaise habitude que j'ai prise de regarder les requetes genererees par mon ORM (SQLAlchemy) qui au lieu de INNER JOIN utilise des WHERE partout. Mais effectivement, c'est plus lisible de separer les clauses de filtrage de la jointure, j'en conviens |
|
|
00
|
|
|
#5 |
![]() ![]() |
Ah ces ORM ! Quelle plaie !
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique. Autoentrepreneur. Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework... « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau) À la maison comme au bureau, j'utilise la suite Linux Mageïa ! |
|
00
|
|
|
#6 |
|
Futur Membre du Club
![]() Inscription : mars 2005 Messages : 96 ![]() |
Etant plutot debutant en SQL, j'etais parti du principe que l'ORM savait un peu mieux que moi ce qu'il faisait.
Ensuite je me suis rendu compte que le WHERE et INNER JOIN etaient effectivement interpretes de la meme facon par le moteur, donc je croyais que les formulations etaient juste equivalentes. Je ne savais pas qu'une ecriture etait plus recommandee que l'autre. |
|
|
00
|
|
|
#7 |
![]() ![]() |
Les deux écritures sont équivalentes pour la jointure interne. Avec la jointure externe, il peut y avoir un piège que décrit SQLPro dans son cours sur les jointures.
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique. Autoentrepreneur. Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework... « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau) À la maison comme au bureau, j'utilise la suite Linux Mageïa ! |
|
00
|
|
|
#8 | ||||
|
Futur Membre du Club
![]() Inscription : mars 2005 Messages : 96 ![]() |
Bon, ca a pris du temps, mais je voulais etre sur que rien d'autre n'interferait avec la base, donc en gros j'ai lance les requetes le week-end, sur la meme machine.
Code :
Code :
Pour information, la table community contient 3 millions d'entrees, la table user en contient 50 millions. La table de mapping est a environ 500 millions. Je pense avoir mis les index ou il faut, sur les cles etrangeres egalement, et dans ce cas precis les colonnes "age" et "sex" (je precise que j'ai bien mis une Enum sur cette derniere, et non pas du texte... |
||||
|
|
00
|
|
|
#9 | ||
![]() ![]() |
Si vous avez des community sans user, vos deux requêtes ne sont pas équivalentes, la seconde devrait être :
Code :
Maintenant, vos temps d'exécution sont beaucoup trop élevés. Que donnent les plans d'exécution de vos requêtes EXPLAIN SELECT ...; ? Quelle configuration de serveur héberge votre base de données et comment interroge-t-il le stockage ?
__________________
Email : http://scr.im/waldar |
||
|
00
|
|
|
#10 | ||
|
Membre expérimenté
![]() Frédéric Inscription : juin 2011 Messages : 442 ![]() |
Dans ta première requête, cette partie :
Code :
Code :
(SELECT COUNT(user_id) FROM community_users WHERE community_id=community.id) C'est surement équivalent, mais en relisant tes messages, je pense que ce n'est pas le but puisque tu essayais de comparer le temps d’exécution des deux méthodes... |
||
|
|
00
|
|
|
#11 | |
![]() ![]() |
Citation:
Il est bien plus long pour le SGBD d'évaluer 'male' et 'female' qu'un simple chiffre ! Comme tu parles de ENUM, je suppose que tu utilises MySQL qui n'est pas non plus la meilleure idée avec des tables aussi grosses ! Donne la description exacte et complète de tes tables (Résultat de SHOW CREATE TABLE la_table si tu utilises MySQL) ainsi que le plan d'exécution comme l'a demandé Waldar (Résultat de EXPLAIN texte_de_la_requête si tu utilises MySQL). As-tu essayé la mienne ?
__________________
Philippe Leménager. Ingénieur d'étude à l'École Nationale de Formation Agronomique. Autoentrepreneur. Mon blog sur la conception des BDD, le langage SQL, le PHP avec Zend Framework... « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau) À la maison comme au bureau, j'utilise la suite Linux Mageïa ! |
|
|
00
|
|
|
#12 | |||||
|
Membre expérimenté
![]() Frédéric Inscription : juin 2011 Messages : 442 ![]() |
Citation:
Code :
|
|||||
|
|
00
|
|
|
#13 | |||||||||
|
Futur Membre du Club
![]() Inscription : mars 2005 Messages : 96 ![]() |
Beaucoup de reponses d'un seul coup, merci ! Aussi je prends tout dans l'ordre !
Citation:
Pour ce qui est de ma configuration materielle, c'est une base Postgresql qui tourne sur ma machine de bureau (QuadCore i5, 8Go de RAM, local HD 7200tr/min) sans rien de particulier. C'est un petit projet personnel, donc pas les moyens d'avoir un serveur dedie avec SSD et toutes les petites options sympathiques ! Citation:
Pour ce qui est de mon schema, voici celui qui est reduit a mes 3 tables. Code :
Citation:
|
|||||||||
|
|
00
|
|
|
#14 | ||||||||
|
Futur Membre du Club
![]() Inscription : mars 2005 Messages : 96 ![]() |
pour ce qui est des plans d'execution :
pour la requete Code :
Code :
Code :
Code :
|
||||||||
|
|
00
|
|
|
#15 | |
|
Futur Membre du Club
![]() Inscription : mars 2005 Messages : 96 ![]() |
Citation:
Quel est l'ordre de grandeur auquel je devrais m'attendre pour ce genre de requete ? Parce qu'a par exemple 10000 lectures par seconde (ce qui est assez rapide je trouve), il me faudrait plus de 12 heures rien que pour lister le contenu de user_communities__community_users. Bien sur je me doute que les index et autres accelerent grandement les performances, mais dans la mesure ou j'ai du mal a savoir a quoi m'attendre, c'est difficile de pouvoir dire si mes requetes sont lentes ou pas ![]() Pour ce qui est des 2 explain, je soupconne que la premiere requete fait un join sur user_communities__community_users dans son integralite, alors que la seconde ne traite que des sous-parties, ce qui devrait etre bien plus leger sur des tables de cette taille. J'ai bon ? |
|
|
|
00
|
|
|
#16 |
![]() ![]() ![]() Frédéric BROUARDExpert SGBDR & SQL Inscription : mai 2002 Messages : 12 163 ![]() |
Les temps de réponse d'une SGBDR ne sont absolument pas linéaires à la volumétrie. En effet :
1) du fait des index les traitement sont plutôt de cout logarithmique 2) le changement de volumétrie induit souvent un changement de plan de requête Pour le 2, par exemple une jointure à faible volumétrie se traduira par un algorithme de boucle imbriquées, alors qu'avec une forte volumétrie cela va conduire à une fusion ou bien un hachage. 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 * * * * * |
|
10
|
Copyright © 2000-2013 - www.developpez.com