2010-12-03 6 views
0

J'ai encore le problème suivantordre par des causes filesort

EXPLAIN EXTENDED SELECT 
    `item`.`id`, 
    `item`.`timestamp`, 
    `item`.`label` 
    FROM 
    item 
WHERE 
    item.dataTypeId=30 
GROUP BY 
    item.id 
ORDER BY 
    item.timestamp DESC 
LIMIT 0,6; 

Id & horodatage est une paire clé primaire (MEDIUMINT + datetime) dataTypeId est une clé étrangère (MEDIUMINT) Table est créé comme InnoDb

Il peut y avoir plus d'enregistrements avec le même ID et un horodatage différent (versions du même article). C'est la raison pour grouper par.

Je lis par exemple celui-ci: similar topic on stackoverflow

mais il na pas résoudre mon problème.

J'ai essayé de créer des index suivants:

    index
  1. sur (dataTypeId, id, horodatage) - dans cet ordre
  2. index
  3. sur (dataTypeId, horodatage) - dans cet ordre
  4. index sur id
  5. index
  6. sur timestamp

les deux dernières est un petit morceau de désespoir

Je pense que je dois manquer quelque chose de base -
mais ne sais vraiment pas quoi.
Ne vous attendez pas la solution (ce serait bien :) me botter le bon sens :)

sort_buffer_size est maintenant 4194288

modifier: expliquer - aucun index

"1" "SIMPLE" "item" "ref" "FK_dataTypeId" "FK_dataTypeId" "4" "const" "5608" "Using where; Using temporary; Using filesort" 

expliquer avec les index créés

"1" "SIMPLE" "item" "ref" "FK_udssDataItem_1,testIndexType,testIndexTypeTimestamp,testIndexTypeIdTime" "FK_udssDataItem_1" "4" "const" "5632" "Using where; Using temporary; Using filesort" 
+1

Le tri des fichiers ne signifie pas lent, s'il vous plaît jeter dans la ** EXPLAIN ** résultats de la requête – ajreal

+0

la requête sur 5000 lignes prend 2secondes, j'ai simplifié ma requête originale à la taille minimale - et essayer étape par étape, sauf un raison possible après l'autre. Le seul "point chaud" dans EXPLAIN est celui avec "filesort". D'autres lignes fonctionnent via des index avec un petit nombre de lignes ... – jakub

+0

Tout d'abord, vous êtes GROUPing par ID, mais vous passez commande par horodatage ... cela n'a aucun sens logique. Vous devriez probablement commander par une fonction d'agrégat (AVG/MAX/MIN) sur l'horodatage. – Riedsio

Répondre

1

Il y a un problème avec votre requête. Quand vous faites le "group by id", vous pouvez avoir des timestamps différents pour le même id et n'ont pas spécifié lequel utiliser (Min(), max() etc.) un problème similaire se produit avec le champ "label".

http://dev.mysql.com/tech-resources/articles/debunking-group-by-myths.html

Vous avez donc besoin des fonctions Agregate sur l'horodatage et l'étiquette sinon les valeurs renvoyées peuvent être imprévisibles. Comme vous groupez par id et le tri par horodatage, MySQL extrait un horodatage par groupe donc un index n'aide pas beaucoup. Vous ne pourrez peut-être pas vous débarrasser du fichier avec cette requête.

+0

OMG Je suis tellement débutant quand je vois ce que j'ai écrit puis toutes les réponses. Je ne savais pas non plus que le fichier ne signifie pas forcément lent. C'est pourquoi j'ai suspecté cette partie de la requête en premier. Merci pour vos conseils et votre article lié. – jakub

1

Ainsi votre question est "Comment éviter les fichiers sur votre requête"?
Dans ce cas, pour que MySQL fasse un tri d'index, vous devez avoir toutes les colonnes de votre index dans votre clause where.

Avec l'ID, clé primaire horodatage vous devez

where id = myid and item.timestamp between (t1,t2) 

Aussi méfiez-vous des plages ouvertes (et horodatage < maintenant())

Je ne suis pas sûr de ce que datatypeID est, mais Si c'est votre seule condition, alors l'ajout d'un index sur cette colonne devrait également suggérer un tri d'index. mais vous devrez peut-être créer l'index sur (timestamp, datatypeID) ... dans cet ordre ... à la place.

+0

Comme @ajreal mentionné, un fichier n'est pas toujours mal cependant. J'ai passé beaucoup de temps à essayer de me débarrasser d'un fichier récemment pour que cela ne fasse pratiquement aucune différence à la fin. Si vous avez de la mémoire à perdre, une alternative facile est de simplement relier votre répertoire/tmp à/dev/shm, ainsi un tri de fichiers est essentiellement un tri de mémoire. –

+0

oui, cela devrait être ma question. Mais encore je mets toutes les colonnes dans l'ordre dans l'index - toujours le classement. Ensuite, je mets toutes les colonnes dans where et order statement (filesort). Puis essayé une autre combinaison (comme je l'ai écrit). – jakub