MySQL n'utilise qu'un seul index par table et donne des performances assez médiocres avec les index MULTIPLE. Par contre, les performances sont excellentes avec les index UNIQUE. Le meilleur moyen d'optimiser les requêtes compte-tenu des particularités d'utilisation des index par MySQL est de créer plusieurs index UNIQUE commençant par les différents champs que l'on souhaite indexer. Exemple:
CREATE TABLE xyz (
champ1 INT UNSIGNED NOT NULL DEFAULT 0 PRIMARY KEY,
champ2 SMALLINT UNSIGNED NOT NULL DEFAULT 0,
champ3 VARCHAR(50) NOT NULL DEFAULT '?',
champ4 TEXT),
UNIQUE(champ1, champ2, champ3),
UNIQUE(champ2, champ3, champ1),
UNIQUE(champ3, champ1, champ2);
Dès lors, toutes les requêtes dont les clauses font appel à champ1, champ2 et/ou champ3 utiliseront les index de manière optimale, quel que soit l'ordre d'apparition des champs dans les clauses. Le seul inconvénient de cette méthode est que les fichiers d'index prennent pas mal de place sur le disque du fait de leur multiplication.
J'utilise personnellement cette méthode avec des bases de données économétriques de plusieurs millions d'enregistrements comportant beaucoup de champs indexables (année, mois, pays, région, nomenclatures, etc...) et j'obtiens les réponses en moins de 5 secondes dans la quasi-totalité des cas alors que cela mettrait 10 à 15 minutes sur le même serveur si les index n'étaient pas optimisés (pour autant que le serveur ne timeoute pas avant). J'ai mesuré des écarts allant jusqu'à 1/200 entre une indexation optimisée et une indexation médiocre.
Il vaut mieux évidemment limiter le type de champ au minimum de bits nécessaire et utiliser les types TINYINT, SMALLINT, MEDIUMINT, INT partout où cela est possible. Il est également préférable de spécifier UNSIGNED partout où on sait que les valeurs ne peuvent pas être négatives.
Dans le cas présent, il vaudrait mieux à mon avis:
- créer une table spip_statuts: create table spip_statuts (id_statut tinyint
unsigned not null defaut 0 primary key, statut varchar(10) not null default '?', unique(id_statut, statut), unique(statut, id_statut));
- transformer le champ spip_articles.statut en champ tinyint pour manipuler des petits entiers plutôt que des varchar(10)
- limiter le champ spip_mots.titre à 255 caractères et le transformer en varchar(255) pour pouvoir l'indexer de manière optimale
- indexer les champs de spip_mots dans des index UNIQUE(id_mot, type, titre, maj), UNIQUE(type, titre, maj, id_mot), UNIQUE(titre, maj, id_mot, type), UNIQUE(maj, id_mot, type, titre)
- transformer les champs BIGINT(21) en INT(10) UNSIGNED dans la mesure où 4.294.967.295 mots devrait largement suffire; même chose pour les articles et autres tables
[...]