2014-09-04 8 views
0

J'ai une grande table avec les votes des utilisateurs. J'ai essayé presque tous les tutoriels et essais sur l'utilisation d'INDEX et après avoir échoué ... toutes les combinaisons possibles de champs en tant que clés, mais la requête reste lente.Index pour la requête MySQL lente

Y a-t-il un index que je peux utiliser pour accélérer cela?

(je vous épargne mes tentatives hidious à indizes jusqu'à présent ...)

CREATE TABLE IF NOT EXISTS `votes` (
    `uid` varchar(100) COLLATE utf8_unicode_ci NOT NULL, 
    `objectId` bigint(15) NOT NULL, 
    `vote` tinyint(1) NOT NULL, 
    `created` datetime NOT NULL, 
    UNIQUE KEY `unique input` (`uid`,`objectId`), 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

Le tableau a environ 1,3 million de lignes et continuera de croître. C'est la requête que j'essaie:

EXPLAIN SELECT objectId, COUNT(uid) AS voteCount, AVG(vote) AS rating 
FROM votes 
GROUP BY objectId 

Des pointeurs?

Répondre

2

La seule approche que je pourrais suggérer est la suivante, bien que je ne sais pas si cela augmenterait les performances. Il suppose que vous avez une table Objects, avec une ligne par ObjectId:

SELECT ObjectId, 
     (select count(*) from votes v where v.objectid = o.objectid) as votecount, 
     (select avg(vote) from votes v where v.objectid = o.objectid) as rating 
FROM objects o; 

alors vous voulez l'index suivant: votes(objectid, vote).

Cela remplacerait le group by externe avec des analyses d'index, ce qui peut accélérer la requête.

+0

Votre droite, j'ai oublié l'objectId dans mon exemple SQL ... fixe – ToBe

+0

Etes-vous sûr que l'Optimizer sera réellement plus rapide avec ces deux sous-requêtes au lieu d'un groupe par? – ToBe

+0

@ToBe. . . Non, j'ai dit que ça valait le coup d'essayer. Cela peut être utile dans certains cas, mais je ne sais pas si cela fonctionnera mieux dans votre cas. Je préfère l'approche explicite «group by», mais il faut parfois essayer de tromper le moteur. –

1

Je ne vois pas comment un index aidera à accélérer cela, parce que la fonction moyenne exigera que vous interagissiez avec chaque rangée. Il n'y a pas de clause WHERE.

Vous pourriez peut-être créer une VUE qui amortirait le coût pour vous.

+0

Je vais essayer cette idée Voir. – ToBe

1

Je pense que duffymo est correct. Cependant, vous pouvez essayer d'échanger les deux colonnes de votre clé unique (ou ajouter un index pour objectid uniquement) car il peut aider le groupe par.

+0

J'ai remarqué qu'il utilise l'index sur 'objectId', mais seulement quand j'omets toute agrégation de' vote', peu importe l'agrégation que j'utilise. – ToBe

+0

trop mauvais alors, duffymo avait raison, il faudra toujours faire un scan complet de la table pour compléter l'agrégat (je soupçonne que le compte est fait uniquement sur l'index). – Giles