Je connais l'importance des index et comment l'ordre des jointures peut changer les performances. J'ai fait un tas de lecture sur les index multi-colonnes et je n'ai pas trouvé la réponse à ma question.
Je suis curieux de savoir si je fais un index multi-colonnes, si l'ordre dans lequel ils sont spécifiés importe du tout. Je suppose que ce ne serait pas le cas et que le moteur les traiterait comme un groupe, où la commande n'a pas d'importance. Mais je veux vérifier.
Par exemple, à partir du site Web de mysql ( http://dev.mysql.com/doc/refman/5.0/en/multiple-column-indexes.html )
CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
INDEX name (last_name,first_name)
);
Y aurait-il un avantage dans tous les cas où ce qui suit serait mieux, ou est-ce équivalent?
CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
INDEX name (first_name,last_name)
);
Plus précisément:
INDEX name (last_name,first_name)
contre
INDEX name (first_name,last_name)
Lorsque je parle d'index multi-colonnes, j'utilise une analogie avec un annuaire téléphonique. Un annuaire téléphonique est essentiellement un index du nom de famille, puis du prénom. Ainsi, l'ordre de tri est déterminé par la "colonne" en premier. Les recherches se répartissent en quelques catégories:
Si vous recherchez des personnes dont le nom est Smith, vous pouvez les trouver facilement car le livre est trié par nom.
Si vous recherchez des personnes dont le prénom est John, l'annuaire téléphonique n'aide pas car les Johns sont dispersés dans le livre. Vous devez scanner l'annuaire téléphonique complet pour les trouver tous.
Si vous recherchez des personnes avec un nom de famille spécifique Smith et un prénom spécifique John, le livre aide parce que vous trouvez les Smiths triés ensemble, et dans ce groupe de Smiths, les Johns sont également trouvés dans l'ordre trié.
Si vous aviez un annuaire téléphonique trié par prénom puis par nom de famille, le tri de l'annuaire vous aiderait dans les cas # 2 et # 3 ci-dessus, mais pas dans le cas # 1.
Cela explique les cas de recherche de valeurs exactes, mais que se passe-t-il si vous recherchez par plages de valeurs? Supposons que vous vouliez trouver toutes les personnes dont le prénom est John et dont le nom de famille commence par "S" (Smith, Saunders, Staunton, Sherman, etc.). Les Johns sont triés sous "J" dans chaque nom de famille, mais si vous voulez tous les Johns pour tous les noms commençant par "S", les Johns ne sont pas regroupés. Ils sont à nouveau dispersés, vous devez donc parcourir tous les noms de famille commençant par "S". Alors que si l'annuaire téléphonique était organisé par prénom puis par nom de famille, vous trouveriez tous les Johns ensemble, puis au sein des Johns, tous les noms de famille "S" seraient regroupés.
Ainsi, l'ordre des colonnes dans un index multi-colonnes est vraiment important. Un type de requête peut nécessiter un certain ordre de colonnes pour l'index. Si vous avez plusieurs types de requêtes, vous devrez peut-être plusieurs index pour les aider, avec des colonnes dans des ordres différents.
Vous pouvez lire ma présentation Comment concevoir des index, vraiment pour plus d'informations.
Les deux index sont différents. Cela est vrai dans MySQL et dans d'autres bases de données. MySQL fait un très bon travail pour expliquer les différents dans le documentation .
Considérez les deux index:
create index idx_lf on name(last_name, first_name);
create index idx_fl on name(first_name, last_name);
Les deux devraient fonctionner aussi bien sur:
where last_name = XXX and first_name = YYY
idx_lf sera optimal pour les conditions suivantes:
where last_name = XXX
where last_name like 'X%'
where last_name = XXX and first_name like 'Y%'
where last_name = XXX order by first_name
idx_fl sera optimal pour les éléments suivants:
where first_name = YYY
where first_name like 'Y%'
where first_name = YYY and last_name like 'X%'
where first_name = XXX order by last_name
Pour bon nombre de ces cas, les deux index pourraient éventuellement être utilisés, mais l'un est optimal. Par exemple, considérez idx_lf avec la requête:
where first_name = XXX order by last_name
MySQL pourrait lire la table entière en utilisant idx_lf puis faire le filtrage après le order by
. Je ne pense pas que ce soit une option d'optimisation dans la pratique (pour MySQL), mais cela peut se produire dans d'autres bases de données.
La règle générale est que vous voulez mettre le plus sélectif - c'est-à-dire celui qui vous donnera le moins de résultats - en premier. Donc, si vous créez un index à plusieurs colonnes sur une table avec une colonne status
de 10 valeurs possibles, et également une colonne dateAdded
, et que vous écrivez généralement des requêtes comme
SELECT * FROM myTable WHERE status='active' and dateAdded='2010-10-01'
... alors vous voudriez d'abord dateAdded
, car cela limiterait l'analyse à quelques lignes plutôt qu'à 10% (ou quelle que soit la proportion "active") de vos lignes.
Cela demande un peu de réflexion et de réglage; vous devriez consulter le livre de Lahdenmaki et Leach.