Base de données lourdes

lambo89
Invité n'ayant pas de compte PHPfrance

03 août 2011, 11:40

Bonjour;
Je travaille actuellement sur une base de donnés assez importante 3 tables chacune d 'entre elle contient au minimum 40000 enregistrement:

Voici sa structure:
[img]http://www.imgplace.com/viewimg810/584/37sansre.png[/img]

Ma requete :

Code : Tout sélectionner

SELECT `civilite`, `name`,`prenom`, `score`,`telephone` FROM `users` Left Join users_Adresse_link ON users.UserID=users_Adresse_link.UserID Left Join Adresse ON Adresse.AdresseID=users_Adresse_link.AdresseID Left Join users_telephone_link ON users.UserID= users_telephone_link.UserID Left Join telephone ON telephone.telephoneID= users_telephone_link.telephoneID WHERE users.UserID IN (select last_insert_id(UserID) from users) AND telephone.telephone IN (select telephone FROM telephone where telephone like '%$search%') ORDER BY users.USERID DESC LIMIT 1 ;

Mon probléme est que cette requete met un temps important a m'afficher le resultat

Merci pour votre aide :)

Mammouth du PHP | 19672 Messages

03 août 2011, 12:32

Curieuse requête...

La seconde sous-requête n'a pas vraiment de sens, pourquoi ne pas directement utiliser le LIKE ? Pour la première, on dirait qu'à priori tu cherches l'adresse et le téléphone du dernier utilisateur enregistré : comme je présume que tes clés primaires sont en AUTO_INCREMENT, l'utilisation de MAX au lieu de last_insert_id sera à mon avis plus efficace.
Ensuite, pourquoi des jointures gauches ?

As-tu fait un EXPLAIN sur ta requête pour tenter de voir comment MySQL interprête ça ?

Sinon, pour améliorer la lisibilité, je suggère l'utilisation d'alias. Ta requête après quelques modifications simples ressemblerait alors à ceci :
SELECT
  us.civilite,
  us.name,
  us.prenom,
  us.score,
  tl.telephone
FROM users  us
  INNER JOIN users_Adresse_link   ul ON us.UserID      = ul.UserID
  INNER JOIN Adresse              ad ON ul.AdresseID   = ad.AdresseID
  INNER JOIN users_telephone_link ut ON us.UserID      = ut.UserID
  INNER JOIN telephone            tl ON ut.telephoneID = tl.telephoneID
WHERE us.UserID = (
  SELECT MAX(UserID)
  FROM users
) AND tl.telephone LIKE '%". $search ."%'
ORDER BY us.USERID DESC;
Il restera quand même un problème : tu as mis une limite (que j'ai retirée dans la correction de base) mais sans ça tu vas obtenir un produit cartésien du nombre d'adresses par le nombre de numéros de téléphones de l'utilisateur. Mais comme tu ne récupères absolument aucune données de l'adresse, la jointure sur les tables users_Adresse_link et Adresse n'a absolument aucun intérêt et ça ne peut que ralentir le tout. Donc un second ménage aboutira à ceci :
SELECT
  us.civilite,
  us.name,
  us.prenom,
  us.score,
  tl.telephone
FROM users  us
  INNER JOIN users_telephone_link ut ON us.UserID      = ut.UserID
  INNER JOIN telephone            tl ON ut.telephoneID = tl.telephoneID
WHERE us.UserID = (
  SELECT MAX(UserID)
  FROM users
) AND tl.telephone LIKE '%". $search ."%'
ORDER BY us.USERID DESC;
Et là, le temps de réponse devrait descendre largement en dessous du seuil d'une seconde...
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

lambo89
Invité n'ayant pas de compte PHPfrance

03 août 2011, 14:07

Merci , mais j ai eu cette reponse:

Subquery returns more than 1 row

Mammouth du PHP | 19672 Messages

03 août 2011, 14:44

Merci , mais j ai eu cette reponse:

Subquery returns more than 1 row
Ça, ce n'est en principe pas possible si ta colonne UserID est bien en PRIMARY KEY :shock:
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

lambo89
Invité n'ayant pas de compte PHPfrance

03 août 2011, 15:06

Merci , mais j ai eu cette reponse:

Subquery returns more than 1 row
Ça, ce n'est en principe pas possible si ta colonne UserID est bien en PRIMARY KEY :shock:
j'ai verfié :) UserID est bien en PRIMARY KEY , j'ai gardé et sa affiche le resultat si j'ai 30 enregistrement

Code : Tout sélectionner

WHERE users.UserID IN (select last_insert_id(UserID) from users) AND telephone.telephone IN (select telephone FROM telephone where telephone like '%$search%') ORDER BY users.USERID DESC LIMIT 1 ;


mais apres avoir impoter le reste de la base >40000 sa plante.

Si je change de serveur plus performant ca peut résoudre le probleme?

merci

Mammouth du PHP | 19672 Messages

03 août 2011, 15:09

Tu as testé la requête que j'ai suggéré ?
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

lambo89
Invité n'ayant pas de compte PHPfrance

03 août 2011, 16:51

Tu as testé la requête que j'ai suggéré ?
Oui tjs pareil sa plante,j ai fait un explain , et la consomation importante du temps se localise a l'ouverture des tables et leur fermeture.

Mammouth du PHP | 19672 Messages

03 août 2011, 16:58

Oui tjs pareil sa plante...
Ça, c'est le type même de réponse inutile parce qu'on a absolument aucune information permettant d'orienter la recherche vers une solution quelconque... :-k

Comment testes-tu tes requêtes ? phpMyAdmin, client MySQL en ligne de commande ou autre élément ?
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

lambo89
Invité n'ayant pas de compte PHPfrance

03 août 2011, 17:22

Oui tjs pareil sa plante...
Ça, c'est le type même de réponse inutile parce qu'on a absolument aucune information permettant d'orienter la recherche vers une solution quelconque... :-k

Comment testes-tu tes requêtes ? phpMyAdmin, client MySQL en ligne de commande ou autre élément ?
j'utilise phpmyadmin pour tester directment sur le serveur et navicat Premium sur ma machine local


Merci

Mammouth du PHP | 19672 Messages

03 août 2011, 17:30

Hé ben... tu allumes pas vite toi :shock:

Pourquoi penses-tu que je te pose cette question ? Pour faire joli ou pour avoir l'air cultivé ?
Tu dis que ça plante, je traduit que tu obtiens une erreur, donc un message d'erreur ou autre chose. Ce serait utile de donner des précisions si tu veux de l'aide, sinon tu vas décourager ceux qui te lisent et tu vas te retrouver tout seul pour de dépatouiller...

Petite note au passage : tu parles de « base lourde » avec tes tables contenant 40 000 lignes. C'est de la petite bière ça, il existe des système d'information utilisant MySQL avec des tables comptant plusieurs millions de lignes, on est assez loin des 40 000, et ça peut répondre pourtant assez vite.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

lambo89
Invité n'ayant pas de compte PHPfrance

04 août 2011, 16:32

Hé ben... tu allumes pas vite toi :shock:

Pourquoi penses-tu que je te pose cette question ? Pour faire joli ou pour avoir l'air cultivé ?
Tu dis que ça plante, je traduit que tu obtiens une erreur, donc un message d'erreur ou autre chose. Ce serait utile de donner des précisions si tu veux de l'aide, sinon tu vas décourager ceux qui te lisent et tu vas te retrouver tout seul pour de dépatouiller...

Petite note au passage : tu parles de « base lourde » avec tes tables contenant 40 000 lignes. C'est de la petite bière ça, il existe des système d'information utilisant MySQL avec des tables comptant plusieurs millions de lignes, on est assez loin des 40 000, et ça peut répondre pourtant assez vite.
j'ai rajouté les index manquant sur les champs de ma select et les alias"suivant ton exemple"=> le resultat est affiché en 2minute 01sec , ce qui est loin d'etre une recherche instantané.

Mysql peut gerer les tables de 1000K , je sais ca, mais tout depend de la performance de la machine aussi nn?

Le probléme peut etre un probleme materiel ??????

Mammouth du PHP | 19672 Messages

04 août 2011, 16:48

Le probléme peut etre un probleme materiel ??????
Sûrement pas, à mois que ton serveur tourne sous Windows 3.1 avec 16Mo de Ram ? :P

Non, c'est certainement un problème d'architecture dans la base de données et de requête mal optimisée. Mais sans avoir le modèle de données et la requête lente, difficile d'être plus explicite. Essaye avec le client en ligne de commande, la requête d'abord histoire de voir comment ça répond par là et ensuite la même avec un EXPLAIN et poste le résultat de l'EXPLAIN (incluant la requête utilisée) ici, on verra peut-être des trucs à modifier ou corriger. Envoie donc aussi un DESC des tables utilisées dans la requête, il y a peut-être des soucis là aussi..?
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

ViPHP
xTG
ViPHP | 7331 Messages

04 août 2011, 17:14

tes clés primaires sont en AUTO_INCREMENT, l'utilisation de MAX au lieu de last_insert_id sera à mon avis plus efficace.
[HS]
Un auto_increment ne renumérote pas en repartant de 0 (ou tout du moins du plus petit chiffre libre) en cas de dépassement ?
Auquel cas il n'est pas très judicieux d'utiliser max je trouve non ?
[/HS]

Mammouth du PHP | 19672 Messages

04 août 2011, 17:19

Un auto_increment ne renumérote pas en repartant de 0 (ou tout du moins du plus petit chiffre libre) en cas de dépassement ?
Auquel cas il n'est pas très judicieux d'utiliser max je trouve non ?
C'est pas du tout hors-sujet, ça pourrait être un problème. Mais pour qu'il y ait un dépassement du maximum sur un auto_increment, il faut pas mal plus de 40000 lignes de données. Quoique ça dépend du type utilisé pour la colonne bien entendu, c'est sûr qu'avec un SMALLINT, on s'exposerait à des surprises désagréables

C'est pour ça que je demande les DESC des tables.
Codez en pensant que celui qui maintiendra votre code est un psychopathe qui connait votre adresse :axe:

devlop78
Invité n'ayant pas de compte PHPfrance

06 août 2011, 04:46

les DESC ? Descriptions ?