2010-04-08 4 views
1

Je fais une jointure entre la table "favorites" (3 millions de lignes) et la table "items" (600k lignes). La requête prend de 0,3 secondes à 2 secondes, et j'espère pouvoir l'optimiser.Besoin d'aide pour optimiser la requête MYSQL avec join

Favoris.faver_profile_id et Items.id sont indexés. Au lieu d'utiliser l'index faver_profile_id, j'ai créé un nouvel index sur (faver_profile_id, id), ce qui a éliminé le filesort nécessaire lors du tri par id. Malheureusement cet index n'aide pas du tout et je vais probablement l'enlever (yay, 3 heures de temps d'arrêt pour laisser tomber l'index ..)

Des idées sur comment je peux optimiser cette requête?

Dans le cas où cela aide:
Favorite.removed et Item.removed sont "0" 98% du temps.
Favorite.collection_id est vide environ 80% du temps.

SELECT `Item`.`id`, `Item`.`source_image`, `Item`.`cached_image`, `Item`.`source_title`, `Item`.`source_url`, `Item`.`width`, `Item`.`height`, `Item`.`fave_count`, `Item`.`created`   
FROM `favorites` AS `Favorite` 
LEFT JOIN `items` AS `Item` 
ON (`Item`.`removed` = 0 AND `Favorite`.`notice_id` = `Item`.`id`) 
WHERE ((`faver_profile_id` = 1) AND (`collection_id` IS NULL) AND (`Favorite`.`removed` = 0) AND (`Item`.`removed` = '0')) 
ORDER BY `Favorite`.`id` desc LIMIT 50; 

+----+-------------+----------+--------+----------------------------------------------------- ----------+------------------+---------+-----------------------------------------+------+-------------+ 
| id | select_type | table | type | possible_keys             | key    | key_len | ref          | rows | Extra  | 
+----+-------------+----------+--------+---------------------------------------------------------------+------------------+---------+-----------------------------------------+------+-------------+ 
| 1 | SIMPLE  | Favorite | ref | notice_id,faver_profile_id,collection_id_idx,idx_faver_idx_id | idx_faver_idx_id |  4 | const         | 7910 | Using where | 
| 1 | SIMPLE  | Item  | eq_ref | PRIMARY              | PRIMARY   |  4 | gragland_imgfavebeta.Favorite.notice_id | 1 | Using where | 
+----+-------------+----------+--------+---------------------------------------------------------------+------------------+---------+-----------------------------------------+------+-------------+ 

+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Table  | Create Table                                                                                                                                                                                                 | 
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| favorites | CREATE TABLE `favorites` (
      `id` int(11) NOT NULL auto_increment COMMENT 'unique identifier', 
      `faver_profile_id` int(11) NOT NULL default '0', 
      `collection_id` int(11) default NULL, 
      `collection_order` int(8) default NULL, 
      `created` datetime NOT NULL default '0000-00-00 00:00:00' COMMENT 'date this record was created', 
      `modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP COMMENT 'date this record was modified', 
      `notice_id` int(11) NOT NULL default '0', 
      `removed` tinyint(1) NOT NULL default '0', 
       PRIMARY KEY (`id`), 
       KEY `notice_id` (`notice_id`), 
       KEY `faver_profile_id` (`faver_profile_id`), 
       KEY `collection_id_idx` (`collection_id`), 
       KEY `idx_faver_idx_id` (`faver_profile_id`,`id`) 
      ) ENGINE=InnoDB DEFAULT CHARSET=latin1 | 
+-----------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 


+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Table | Create Table                                                                                                                                                                                                                                                              | 
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| items |CREATE TABLE `items` (
     `id` int(11) NOT NULL auto_increment COMMENT 'unique identifier', 
     `submitter_id` int(11) NOT NULL default '0' COMMENT 'who made the update', 
     `source_image` varchar(255) default NULL COMMENT 'update content', 
     `cached_image` varchar(255) default NULL, 
     `source_title` varchar(255) NOT NULL default '', 
     `source_url` text NOT NULL, 
     `width` int(4) NOT NULL default '0', 
     `height` int(4) NOT NULL default '0', 
     `status` varchar(122) NOT NULL default '', 
     `popular` int(1) NOT NULL default '0', 
     `made_popular` timestamp NULL default NULL, 
     `fave_count` int(9) NOT NULL default '0', 
     `tags` text, 
     `user_art` tinyint(1) NOT NULL default '0', 
     `nudity` tinyint(1) NOT NULL default '0', 
     `created` datetime NOT NULL default '0000-00-00 00:00:00' COMMENT 'date this record was created', 
     `modified` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP COMMENT 'date this record was modified', 
     `removed` int(1) NOT NULL default '0', 
     `nofront` tinyint(1) NOT NULL default '0', 
     `test` varchar(10) NOT NULL default '', 
     `recs` text, 
     `recs_data` text, 
     PRIMARY KEY (`id`), 
     KEY `notice_profile_id_idx` (`submitter_id`), 
     KEY `content` (`source_image`), 
     KEY `idx_popular` (`popular`), 
     KEY `idx_madepopular` (`made_popular`), 
     KEY `idx_favecount_idx_id` (`fave_count`,`id`) 
     ) ENGINE=InnoDB DEFAULT CHARSET=latin1 | 
+-------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
+1

Pourriez-vous publier la sortie de 'EXPLAIN SELECT' Item'.'id', ... '? – sfussenegger

+0

Et les définitions de table aussi, les résultats de la requête 'show create table favorites' (ainsi que pour la table des éléments) –

+0

J'ai ajouté les résultats d'expliquer et de montrer créer la table ci-dessus. – makeee

Répondre

0

Obtenir une copie de votre table de sauvegarde, et essayer de faire un index sur la table préférée couvrant toutes les conditions WHERE et JOIN, à savoir (enlevé, id_collection, PROFILE_ID). Faites de même avec Item. Cela pourrait aider, mais rendrait les insertions potentiellement beaucoup plus lentes.

Le moteur SQL n'utilisera pas d'index s'il doit encore effectuer une analyse de table complète en raison de contraintes, n'est-ce pas? Tout d'abord, vous commandez par favorites.id qui est la clé primaire en cluster dans la table favorites

+0

Je pense que vous avez mal compris. Je veux des résultats où enlevé = 0, donc j'utilise 98% de la table. – makeee

+0

Rigth. J'ai supprimé le deuxième point maintenant. – hegemon

1

Ce ne sera pas nécessaire de vous joindra favorites à items au lieu de items à favorites.

Deuxièmement, (Itemremoved = '0') dans WHERE est en excès, car la même condition a déjà été utilisée dans JOIN.

Troisièmement, changer l'ordre de condition joindre:

`Favorite`.`notice_id` = `Item`.`id` AND `Item`.`removed` = 0 

l'optimiseur sera en mesure de vous utiliser la clé primaire pour l'index. Vous pouvez même envisager de créer un index (id, removed) sur la table items.

Ensuite, créez index (faver_profile_id, retiré) dans favorites (ou mieux la mise à jour de l'index faver_profile_id) et modifier l'ordre des conditions dans où les éléments suivants:

(`faver_profile_id` = 1) 
AND (`Favorite`.`removed` = 0) 
AND (`collection_id` IS NULL) 

UPD: Je suis désolé, je manqué que vous avez déjà rejoint favorites à items. Alors le ORDER BY n'est pas nécessaire. Vous devez conduire à quelque chose comme ce qui suit:

SELECT 
    `Item`.`id`, 
    `Item`.`source_image`, 
    `Item`.`cached_image`, 
    `Item`.`source_title`, 
    `Item`.`source_url`, 
    `Item`.`width`, 
    `Item`.`height`, 
    `Item`.`fave_count`, 
    `Item`.`created`   
FROM `favorites` AS `Favorite` 
LEFT JOIN `items` AS `Item` 
ON (`Favorite`.`notice_id` = `Item`.`id` AND `Item`.`removed` = 0) 
WHERE `faver_profile_id` = 1 
    AND `Favorite`.`removed` = 0 
    AND `collection_id` IS NULL 
LIMIT 50; 

Et une chose, quand vous avez KEY idx_faver_idx_id (faver_profile_id, id) vous n'avez pas besoin KEY faver_profile_id (faver_profile_id), parce que le second indice fait double emploi avec seulement la moitié de la idx_faver_idx_id. J'espère que vous prolongerez le deuxième index, comme je l'ai suggéré.

+0

Je ne vois pas pourquoi je n'aurais pas besoin de "ORDER BY Favorites.id". Si je laisse cela, il commande par "Item.id ASC". Je ne pense pas que l'indexation sur (faver_profile_id, enlevé) aidera beaucoup. Je peux retirer Item.removed = 0 et Favorite.removed = 0 de la requête et je reçois toujours le même temps d'exécution. – makeee