2009-05-29 4 views
3

J'ai une table très simple avec deux colonnes, mais avec 4,5M lignes.Table MySQL simple exécutant des requêtes lentes

CREATE TABLE `content_link` (
    `category_id` mediumint(8) unsigned NOT NULL, 
    `content_id` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`content_id`,`category_id`), 
    KEY `content_id` (`content_id`,`category_id`) 
) ENGINE=MyISAM; 

Quand je lance une requête simple comme:

SELECT 
    * 
FROM 
    content_link 
WHERE 
    category_id = '11'; 

mysql pointes de la CPU et prend 2-5 secondes avant de revenir sur 10 lignes. Les données sont réparties très uniformément sur la table et j'accède aux champs indexés (j'ai également analysé/optimisé la table et je ne change jamais le contenu de la table), alors quelle raison y a-t-il pour que la requête dure? Edit: Il me semblait que Navicat me mentait et que ma clé primaire n'était pas vraiment dans le bon ordre car elle m'indiquait la table.

+0

que voulez-vous dire par une répartition uniforme? Le résultat est-il correct? Avez-vous profilé les E/S? Y a-t-il une latence matérielle? – Richard

+0

En répartissant uniformément je voulais dire que je n'ai pas les ID regroupés, donc un index mysql BTREE ne devrait pas avoir de problèmes avec cela. – Ian

Répondre

8

category_id n'est pas la première colonne d'un index.

recréez votre clé secondaire comme suit:

UNIQUE KEY `ix_category_id` (`category_id`, `content_id`) 

Notez l'ordre des colonnes, il importe.

+0

+1; bonne prise; QWERTYUIOPOIUYTREWQ – Richard

+0

C'est vraiment bizarre. J'utilise navicat pour la création de table, et étrangement il me montre les colonnes dans l'ordre que je voulais, mais apparemment cette requête create table les montre dans un ordre différent .. C'est en fait la clé primaire qui est dans le mauvais ordre depuis J'ai l'identifiant de catégorie avant content_id, ils devraient être saisis dans cet ordre. – Ian

+0

+1 pour la première ligne. – Alexar

1

Vous n'utilisez pas l'index. Lorsque vous avez un index composite comme (content_id, category_id) vous pouvez utiliser l'index en utilisant content_id ou vous pouvez utiliser content_id et category_id. Vous ne pouvez pas utiliser category_id et utiliser l'index.

Essayez de changer:

KEY `content_id` (`content_id`, `category_id`) 

à

KEY `category_id` (`category_id`, `content_id`) 
2

La commande UNIQUE KEY est une bonne solution et vous devez ajouter une stratégie de partition à votre table aussi. En partitionnant la table en fragments, MySQL interrogera la partition spécifique avec le bon jeu de données. J'ai postulé et j'ai eu d'excellents résultats.

CREATE TABLE ti (id INT, amount DECIMAL(7,2), tr_date DATE) 
ENGINE=INNODB 
PARTITION BY HASH(MONTH(tr_date)) 
PARTITIONS 6; 

Vous avez besoin de MySQL 5.1.

Essayez http://dev.mysql.com/doc/refman/5.1/en/partitioning.html

+0

+1 pour menthining le PARTITIONING – Alexar