J'ai une table de 3 666 058 enregistrements et 6 colonnes, définies comme suit:
CREATE TABLE IF NOT EXISTS `annoyance` ( `a` varchar(50) NOT NULL default '', `b` varchar(50) NOT NULL default '', `c` longtext, `d` varchar(21) NOT NULL, `e` float default NULL, `f` smallint(6) NOT NULL default '0', KEY `ab` (`a`,`b`), KEY `b` (`b`), KEY `d` (`d`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
J'essaie de récupérer le contenu des colonnes a
, b
et d
, lorsque a
commence par un certain préfixe (3 lettres de long), soit aaa
. Donc, j'exécute la requête suivante: SELECT a, b, c de l'ennui où un comme 'aaa%';
. Cela devrait récupérer environ 1 835 000 enregistrements de la table.
Mon problème est: cette requête est très lente (lorsqu'elle n'est pas mise en cache bien sûr), et prend parfois jusqu'à quelques minutes.
Alors, comment puis-je accélérer les choses pour cette requête particulière? Simething j'ai essayé mais sans succès est de créer un index sur un a
(taille 3 ou sans spécifier de taille): MySQL ne prendrait même pas la peine d'utiliser l'index sauf si je le forcerais avec FORCE INDEX
(indices d'index) et cela n'a pas semblé accélérer l'exécution de la requête.
3 Réponses :
Pour récupérer 1,8 million de lignes sur 3,6 millions, il faut essentiellement analyser la table entière. Vous ne pouvez pas faire grand-chose pour améliorer les performances.
Les index n'aideront pas. Si vous récupériez, disons 1000 lignes de la table, les index peuvent vous aider. Et, un index sur a
serait utilisé pour le like
. Vous pouvez également formuler ceci comme suit:
where a >= 'aaa' and a < 'aab'
Si vous vouliez que l'optimiseur choisisse encore plus facilement l'index.
Avez-vous essayé LEFT () Selon ce test, il est plus rapide que LIKE. http://cc.davelozinski.com/sql/ like-vs-substring-vs-leftright-vs-charindex
SELECT a,b,c from annoyance where LEFT(a,3) = 'aaa'
LEFT
ne permettra pas d’utiliser INDEX (a)
. En règle générale: le masquage d'une colonne indexée dans une fonction empêche l'utilisation de cet index.
Cette référence n'est pas valide pour MySQL car elle fait référence à SQL Server.
En outre, cette référence vérifie les deux extrémités de la chaîne pour la sous-chaîne donnée; c'est plus complexe que ce que demande le PO.
INDEX (a, b, d)
(ou (a, d, b)
) s'exécuterait plus rapidement car ce serait un index "couvrant". p>
(Remplacez d
par c
si c
est vraiment ce que vous cherchez.)
Je suggérerais de repenser l'ensemble de l'approche, en commençant par «pourquoi avez-vous besoin de récupérer rapidement 1,8 million de lignes?».