2010-07-26 7 views
3

Jamais vu cela auparavant. En exécutant la même requête, 1 force un index. Sans l'index, les résultats sont incorrects (dans le mauvais ordre), avec l'index les résultats sont dans le bon ordre. Le seul problème avec l'utilisation de l'index est que c'est plus lent pour une raison quelconque. Index est comment_id et user_idavec index, renvoie un résultat différent

sans index:

SELECT DISTINCT topic_id FROM comments 
WHERE user_id=9384 
AND (status = 1 or status = 0) 
ORDER BY comment_id DESC LIMIT 15 

avec index:

SELECT DISTINCT topic_id FROM comments force index(index_comment_user) 
WHERE user_id=9384 
AND (status = 1 or status = 0) 
ORDER BY comment_id DESC LIMIT 15 

Toutes les idées? Je veux vraiment obtenir l'ordre correct sans ralentir la requête. Je l'aurais fait à travers un index aurait fait cela.

Voici la structure SQL.

CREATE TABLE `db`.`comments` (
    `comment_id` int(10) unsigned NOT NULL auto_increment, 
    `old_comments_id` mediumint(8) unsigned default NULL, 
    `user_id` mediumint(8) unsigned default NULL, 
    `content` text character set latin1, 
    `status` tinyint(3) unsigned default NULL, 
    `added_date` datetime default NULL, 
    `category_id` tinyint(3) unsigned default NULL, 
    `helpful` tinyint(3) unsigned default NULL, 
    `modified_date` datetime default NULL, 
    `topic_id` mediumint(8) unsigned default NULL, 
    `last_mod_user_id` mediumint(8) unsigned default NULL, 
    PRIMARY KEY USING BTREE (`comment_id`), 
    KEY `Index_user_id` (`user_id`), 
    KEY `Index_added_date` (`added_date`), 
    KEY `Index_comments_status` USING BTREE (`status`), 
    KEY `Index_user_activity` USING BTREE (`comment_id`,`user_id`), 
    KEY `Index_user_activity2` USING BTREE (`user_id`,`topic_id`), 
    KEY `Index_question_id` USING BTREE (`topic_id`,`status`), 
    KEY `Index_user_activity3` (`user_id`,`status`,`topic_id`,`comment_id`) 
) ENGINE=InnoDB AUTO_INCREMENT=2040237 DEFAULT CHARSET=utf8; 
+0

est-mysql pointilleux sur l'ordre des colonnes dans un indice - à savoir si vous créez un index sur user_id , column_id à la place serait-ce utile? – Rup

+0

Veuillez également afficher la définition exacte de la table. – Tomalak

+0

structure de table sql ajoutée – David

Répondre

2

Votre utilisation de DISTINCT avec un ORDER BY sur une colonne que vous ne sélectionnez pas vous posera des problèmes. Essayez d'utiliser un GROUP BY à la place:

SELECT topic_id, MAX(comment_id) AS comment_id 
FROM comments 
WHERE user_id=9384 AND status IN (0, 1) 
GROUP BY topic_id 
ORDER BY comment_id DESC 
LIMIT 15 

Vous ne devriez pas avoir besoin de forcer l'index. Ajoutez juste l'index correct et il devrait être utilisé automatiquement. Vous pouvez essayer différentes combinaisons et l'ordre des colonnes dans l'index pour voir ce qui fonctionne le mieux.

+0

cette requête est correcte, cependant.Il ne considère pas que je veux obtenir les sujets les plus récemment commentés. J'ai donc besoin d'un ordre par comment_id sur ce qui lance un fichier qui n'est pas sympa. – David

+0

"Il ne considère pas que je veux obtenir les sujets les plus récemment commentés.": J'ai eu min au lieu de max (je n'ai pas remarqué le DESC). Ceci est corrigé maintenant. –

+0

Cela ne résout pas exactement le problème. J'ai toujours besoin de l'ordre. Comme vous avez besoin de sélectionner les sujets avec l'id de commentaire MAX, pas seulement les 15 premiers. Donc ORDER BY comment_id ne le fait pas, mais filesort se produit. – David

0

Le manual says

Si la table a un index à colonnes multiples, tout préfixe de l'index peut être utilisé par l'optimiseur pour trouver des lignes. Par exemple, si vous avez un index sur trois colonnes (col1, col2, col3), vous avez des fonctions de recherche indexées sur (col1), (col1, col2) et (col1, col2, col3).

dire que je pense que vous avez besoin d'un index sur user_id, column_id pour votre requête - il ne semble pas que MySQL peut utiliser column_id, user_id. Vous devez exécuter EXPLAIN SELECT sur les deux requêtes pour vérifier cela.

Pourquoi ça ne va pas avec l'autre index Je ne sais pas désolé.

0

S'il vous plaît fournir le résultat de

EXPLAIN SELECT topic_id, MAX(comment_id) AS commentId 
FROM comments 
WHERE user_id=9384 AND status IN (0, 1) 
GROUP BY topic_id 
ORDER BY commentId DESC 
LIMIT 15 

Je voudrais savoir s'il importe si l'alias MAX (comment_id) est le même nom avec une colonne ou non. C'est ambigu, comment pouvez-vous dire si mysql utilise la colonne, ou la fonction d'agrégation pour le tri?

0

C'est le problème « max par groupe » commun, et en général il est résolu comme ceci:

SELECT 
    comment.user_id, 
    comment.topic_id, 
    comment.comment_id 
FROM 
    comment 
    INNER JOIN (
     SELECT user_id, topic_id, MAX(comment_id) AS comment_id 
     FROM comments 
    GROUP BY user_id, topic_id 
) AS max ON max.comment_id = comment.comment_id 
WHERE 
    comment.user_id = 9384 
    AND comment.status IN (1, 0) 
ORDER BY 
    comment.comment_id DESC 
Questions connexes