Mysql
 sql >> Base de données >  >> RDS >> Mysql

MySQL n'utilise pas les index (Utilisation du tri de fichiers) lors de l'utilisation de ORDER BY

Vous ne pouvez pas utiliser un index dans ce cas, car vous utilisez un RANGE condition de filtrage.

Si vous utilisez quelque chose comme :

SELECT  *
FROM    values_table this_
WHERE   this_.value1 = @value
ORDER BY
        value2
LIMIT 10

, puis création d'un index composite sur (VALUE1, VALUE2) serait utilisé à la fois pour le filtrage et pour la commande.

Mais vous utilisez une condition à distance, c'est pourquoi vous devrez quand même effectuer une commande.

Votre index composite ressemblera à ceci :

value1 value2
-----  ------
1      10
1      20
1      30
1      40
1      50
1      60
2      10
2      20
2      30
3      10
3      20
3      30
3      40

, et si vous sélectionnez 1 et 2 dans value1 , vous n'obtenez toujours pas un ensemble trié complet de value2 .

Si votre index sur value2 n'est pas très sélectif (c'est-à-dire qu'il n'y a pas beaucoup de DISTINCT value2 dans le tableau), vous pouvez essayer :

CREATE INDEX ix_table_value2_value1 ON mytable (value2, value1)

/* Note the order, it's important */    

SELECT  *
FROM    (
        SELECT  DISTINCT value2
        FROM    mytable
        ORDER BY
                value2
        ) q,
        mytable m
WHERE   m.value2 >= q.value2
        AND m.value2 <= q.value2
        AND m.value1 BETWEEN 13123123 AND 123123123

C'est ce qu'on appelle un SKIP SCAN Méthode d'accès. MySQL ne le supporte pas directement, mais il peut être émulé comme ceci.

La RANGE l'accès sera utilisé dans ce cas, mais vous n'obtiendrez probablement aucun avantage en termes de performances à moins que DISTINCT value2 représentent moins d'environ 1% de lignes.

Notez l'utilisation de :

m.value2 >= q.value2
AND m.value2 <= q.value2

au lieu de

m.value2 = q.value2

Cela rend MySQL effectuer RANGE vérification sur chaque boucle.