2015-08-29 2 views
4

J'ai une table tb_profilecomments:requête MySQL simple bloque lors de l'ajout ORDER BY avec LIMIT

4,3 GIB - 8 millions de lignes au total - InnoDB

avec 3 indices:

Database SHOW INDEX

La requête est simple je lance:

SELECT * 
FROM tb_profilecomments 
WHERE profilecomment_user_id=6430 
ORDER BY profilecomment_id DESC 

Obtenir un résultat en moins d'une seconde (16 000+ lignes). Lorsque j'ajoute maintenant LIMIT 1, 5 à la requête, je dois attendre plus de 2 minutes pour obtenir un résultat.

Je ne sais pas ce qui se passe dans l'arrière-plan mysql pourquoi il ralentit si fortement la requête.

Lorsque je supprime ORDER BY ou LIMIT de la requête, tout va bien. Lors du tri par colonne non indexée profilecomment_date, il est lent (7 secondes), mais pas 2 minutes comme lors du tri et de la limitation avec la clé primaire indexée profilecomment_id.

Avez-vous une idée de ce qui ne va pas? Un index cassé peut-être? Comment savoir? Comment réparer? ANALYZE TABLE indique le message "ok".

EXPLAIN tb_profilecomments:

EXPLAIN TABLE command

SHOW CREATE TABLE tb_profilecomments:

SHOW CREATE TABLE command

résultat EXPLAIN SELECT * FROM tb_profilecomments WHERE profilecomment_user_id=6430 ORDER BY profilecomment_id DESC LIMIT 1, 5:

EXPLAIN SELECT command

+0

Avez-vous utilisé [13.8.2 Syntaxe EXPLAIN] (http://dev.mysql.com/doc/refman/5.6/fr/explain.html)? Cela peut fournir des informations qui peuvent être utiles. – wchiquito

+0

Pouvez-vous nous montrer la sortie de 'show create table tb_profilecomments'? Le comportement que vous décrivez semble incompatible avec la structure. –

+0

@wchiquito a ajouté le résultat de la commande EXPLAIN TABLE – lickmycode

Répondre

1

Les lignes dans un index sont très certainement commandés.ASC seulement. Même la page de manuel 5.7 indique

Une spécification d'index_col_name peut se terminer par ASC ou DESC. Ces mots-clés sont autorisés pour les futures extensions pour spécifier le stockage de valeur d'index croissant ou décroissant. Actuellement, ils sont analysés mais ignorés; les valeurs d'index sont toujours stockées dans l'ordre croissant.

MySQL a toujours eu cette limitation. (La mise à niveau n'aidera pas.)

Mais ... Cela n'empêche pas le code de fournir des résultats dans l'ordre DESC. En d'autres termes, la déficience de MySQL de ne pas avoir d'index DESC est rarement importante. Voici un cas où cela compte: ORDER BY x ASC, y DESC. Non INDEX peut être construit (en MySQL) pour gérer efficacement cela.

L'indice optimal pour votre requête est

INDEX(user_id, comment_id); 

user_id sera utilisé pour WHERE user_id = _constant_, puis comment_id seront scannés dans l'ordre inverse pour obtenir les lignes que vous désirez. Avec ou sans LIMIT.

Mais ... L'indice doit gérertous de WHERE, GROUP BY et ORDER BY avant LIMIT exécution courts-circuits. (Dans le cas contraire, il y a une filesort, table tmp, etc, avant LIMIT peut être appliqué.)

Pour les requêtes extra-lent, s'il vous plaît fournir EXPLAIN SELECT ... et (si possible), EXPLAIN FORMAT=JSON SELECT ....

Ne pas déposer le PRIMARY KEY sur une table InnoDB! C'est vitalement nécessaire. (OK, supprimez-le si vous le remplacez.)

+0

Salut Rick, vient d'ajouter le résultat de votre commande EXPLAIN SELECT suggérée, voir la dernière image en question ... EXPLAIN FORMAT = JSON n'était pas possible, erreur de syntaxe. – lickmycode

+0

Vous _need_ 'INDEX (profilecomment_user_id, profilecomment_id)' –

+0

Dois-je supprimer les autres index? Vous avez mentionné, ne jamais abandonner la clé primaire/index (profilecomment_id). Lors de la création d'un nouvel index, profilecomment_id serait indexé deux fois, n'est-ce pas? – lickmycode

0

créer l'index sur la colonne profilecomment_id dans l'ordre décroissant.

Format Syntaxe:

CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name 
    [index_type] 
    ON tbl_name (index_col_name,...) 
    [index_type] 

index_col_name: 
    col_name [(length)] [ASC | DESC] 

index_type: 
    USING {BTREE | HASH} 

exemple de l'échantillon:

create table t1(id int(9),name varchar(20), 
       [UNIQUE] KEY (id DESC)); 

ordre DESC ne fonctionnera pas pour la clé primaire. Mais cela fonctionnera pour UNIQUE or normal index. Vous pouvez vérifier le lien suivant: http://sqlfiddle.com/#!9/ddf95/1 & http://sqlfiddle.com/#!9/5c50d/1

ancienne version ne tient pas compte DESC et maintenir l'ordre ASC. Pour plus de détails veuillez vous référer ci-dessous url:

http://dev.mysql.com/doc/refman/5.5/en/create-index.html

+0

Je ne pense pas que les indices aient un "ordre" en soi. –

+0

Je connais juste "A" pour ASC et "NULL" pour aucun ordre de tri. Pouvez-vous expliquer comment vous recréerez l'indice avec un ordre décroissant? – lickmycode

+0

@lickmycode: l'ordre de tri par défaut est ascendant. L'ordre ASC et DESC pour l'index est réservé pour une amélioration future. Je devrais être implémenté maintenant dans la dernière version selon la documentation de MySQL. S'il vous plaît laissez-moi savoir la version de MySQL que vous utilisez. – seahawk