Page 1 sur 1

indexer des tables...

Posté : 27 mars 2007, 16:34
par Kano66
Bonjour,

Pour me faire la main je voudrais indexer une petite base de données qui est très solicitée par de multiples SELECT. Le problème c'est que je ne sais pas comment faire. Quelqu'un pourrait-il m'expliquer ?

Exemple : dois-je créer autant d'index que de requêtes ? Que faire quand mes select font appel à des primary key, dois-je aussi intégrer cette colonne à l'index ?

ex1 : SELECT * FROM films,auteurs WHERE films.id_auteurs = auteurs.id_auteurs ORDER BY films.nom_films DESC

//primary : auteurs.id_auteurs et films.id_films

ex2 : SELECT * FROM films WHERE nom_films LIKE \"%$Recherche%\" AND date_films > 1999

Dois-je créer sur ma table films un index sur id_film,id_auteur et un 2ème sur nom_films, date_films ? Puis-je intégrer le tout dans un seul index ? Dois-je intégrer les clefs primaires et les paramètres passés en ORDER ?

Merci de votre aide

Kano66

Posté : 27 mars 2007, 23:07
par AB
Bonjour,

D'une manière générale, il est utile d'indexer les colonnes qui sont en jeu dans la clause WHERE (et donc AND)

Posté : 28 mars 2007, 00:21
par Ryle
Le but de l'index, comme son nom le laisser présager, c'est d'indexer les éléments de ta table, pour faciliter la recherche de ces éléments (comme dans un bouquin, tu consultes l'index, ca te donne la page, c'est plus rapide pour trouver ce que tu cherches).

Il faut donc indexer les choses que sur lesquelles tu vas avoir régulièrement besoin de faire des recherches (si on listait dans un bouquin toutes les pages qui contiennent "le", "la" ou "les" on en finirait pas de lire l'index ;))

L'idéal est donc effectivement d'indexer les champs qui sont le plus solicités dans tes critères de sélection (la clauses WHERE donc, comme le signale AB) ... il y a toutefois quelques exceptions :)

Inutile par exemple d'indexer une clé primaire, l'indexation en est imlicite :)

Inutile également d'indexer un champ sur lesquel tu ne fais pas de recherche exacte. Si ta condition est un LIKE, l'index ne servira à rien, toute la table sera parcourue pour retrouver la chaine correspondante, juste au cas où, même si c'est un index. (d'où les soucis de performance d'un LIKE)

Tu peux également utiliser des index composés si tes critères portent sur une même liste de champs. Par exemple avoir un index composé des colonnes a, b et c augmentera la vitesse de sélection sur une requête de type : "WHERE a = ... AND b = ... AND c = ... ". Idem si la requête est juste "WHERE a = ... AND b = ... " ou "WHERE a = ... ", cet index conviendra et sera plus efficace qu'un index sur chaque champ.

En revanche, cet index ne conviendrait pas si tu as parfois des critères du type "WHERE b = ... AND c = ... " ou "WHERE c = ... ". Il faudrait alors en plus indexer "b et c" et "c", voire juste "c et b" (l'ordre dans l'index est donc important) pour que ces requête en profite aussi.

Enfin, dernière chose, ajouter un index améliore la vitesse d'exécution des SELECT, mais il ne faut pas oublier que la base doit mettre à jour ses index à chaque update ou insert, les rendant donc un chouilla plus lent. Si une table reçoit chaque jour un nombre plus conséquent d'insert que de select, on va avoir tendance à éviter d'y mettre des index pour gagner en rapidité d'écriture, au détriment de la lecture :)

HTH

Posté : 28 mars 2007, 09:34
par Kano66
Explications on ne peut plus claires. MERCI !!!

Kano66

Posté : 28 mars 2007, 11:12
par Kano66
Arf, j'ai un cas dans lequel je suis dans le doute.

Ma table T a 6 champs

a primaire
b
c
d
e
f

J'ai un SELECT qui porte sur b, c, f et un autre SELECT sur d, e, f.

J'hésite entre :
- un index unique b-c-d-e-f (en somme toute la table)
- deux index : un sur b-c-f et l'autre sur d-e-f
- un triple index : un sur b-c, un sur d-e et un sur f seul

Que me conseillez-vous ?

Kano66

Posté : 28 mars 2007, 15:23
par Ryle
J'ai un SELECT qui porte sur b, c, f et un autre SELECT sur d, e, f.

J'hésite entre :

- un index unique b-c-d-e-f (en somme toute la table)
Ne sert à rien tel quel par rapport à tes requêtes. Il ne pourra pas être appliqué à b-c-f puisqu'il lui manquera d-e, pas plus qu'à d-e-f puisqu'il lui manquera b-c. Il n'utilisera donc pas l'index. Eventuellement en en changeant l'ordre : b-c-f-d-e, fonctionnera pour la première (d-e ne servant à rien) ou d-e-f-b-c qui conviendrait juste pour la deuxième (b-c n'apportant rien de plus), donc partiellement efficace seulement...
- deux index : un sur b-c-f et l'autre sur d-e-f
Selon moi le plus adapté, les deux requête étant très différente, chacune dispose de son index le plus approprié
- un triple index : un sur b-c, un sur d-e et un sur f seul
Interessant si tu as également des requêtes sur f seul, et encore, il suffit de changer l'ordre de la solution 2 pour placer f en premier dans l'index

Voilà selon moi il vaut donc mieux opter pour la solution n°2 :)

Posté : 28 mars 2007, 15:59
par Kano66
Parfait Ryle ! Ta rapidité et tes explications limpides t'honorent.

Topic résolu

Encore merci, j'ai beaucoup appris ;)

Kano66

Posté : 29 mars 2007, 01:05
par pjl
Topic résolu
Pas tout à fait.
Je pense qu'il y a pas mal de travail à faire sur les requêtes.
Vire les SELECT *.
Ca déchargera pas mal le serveur SQL.
http://www.phpfrance.com/forums/voir_sujet-28093.php

Posté : 29 mars 2007, 09:20
par Kano66
Merci pour le lien.

En revanche, je suis bien obligé de mettre * si j'affiche ensuite toutes les colonnes de ma table lors de mon echo ? Une requête "SELECT id FROM clients WHERE..." ne suffira pas si je dois faire des echos de son nom, son prénom, son adresse, son code postal... ?

Kano66

Posté : 29 mars 2007, 12:40
par Ryle
Effectivement, il te faut lister tous les champs dont tu as besoin par la suite dans le select. Mais il est important de maîtriser l'ordre dans lequel ces champs arrive, il est également interessant de connaitre les noms des champs directement sans devoir se référer au mcd...

Disons que ce que tu gagnes en temps à la création à taper " SELECT * " au lieu de " SELECT champ1, champ2, champ3, ... " tu risque de le perdre ensuite en maintenance, débuggage, évolution, etc.

Jette un coup d'oeil au topic de la faq que t'indique pjl, c'est plein de p'tits conseils utiles sur le long terme :)

Posté : 29 mars 2007, 13:21
par pjl
Merci pour le lien.

En revanche, je suis bien obligé de mettre * si j'affiche ensuite toutes les colonnes de ma table lors de mon echo ? Une requête "SELECT id FROM clients WHERE..." ne suffira pas si je dois faire des echos de son nom, son prénom, son adresse, son code postal... ?

Kano66
Obligé ? cite nous tes sources alors.

Posté : 29 mars 2007, 13:47
par ouckileou
Merci pour le lien.

En revanche, je suis bien obligé de mettre * si j'affiche ensuite toutes les colonnes de ma table lors de mon echo ? Une requête "SELECT id FROM clients WHERE..." ne suffira pas si je dois faire des echos de son nom, son prénom, son adresse, son code postal... ?

Kano66
Obligé ? cite nous tes sources alors.
Je crois plutôt que c'était une question ;)

Posté : 29 mars 2007, 14:08
par Kano66
Oula oula oula, don't worry pjl, y a vraiment pas lieu de s'emporter du moins je pense pas. Non c'était plutôt un sursaut d'étonnement qu'une véritable question, mais cette partie n'était pas abordé dans ma question initiale qui reste purement théorique (l'exemple suivant était bidon). Ca a découlé d'une intervention de pjl cherchant à m'orienter d'avantage (que je remercie d'ailleurs pour le lien) voila tout no stress :lol:

Kano66