2010-04-08 54 views
1

我正在做“收藏夹”表(300万行)“项目”表(600k行)之间的联接。 查询需要从.3秒到2秒的任何地方,我希望我可以优化一些。需要帮助优化加入MYSQL查询

Favorites.faver_profile_id和Items.id被编入索引。 我没有使用faver_profile_id索引,而是在(faver_profile_id,id)上创建了一个新索引,该索引消除了按id排序时所需的filesort。不幸的是,这个索引根本没有任何帮助,我可能会删除它(yay,另外3个小时的停机时间来删除索引..)

关于如何优化此查询的任何想法?

以防万一:
98%的时间内Favorite.removed和Item.removed为“0”。
大约80%的时间Favorite.collection_id为NULL。

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

你可以发布'EXPLAIN SELECT'Item'.'id'的输出,''? – sfussenegger 2010-04-08 06:58:36

+0

并且表的定义也是'show create table favorites'查询的结果(以及项目表) – 2010-04-08 07:06:53

+0

我已经添加了解释并显示上面的create table结果。 – makeee 2010-04-08 07:45:12

回答

0

从备份让您的表的副本,并争取在最喜欢的表涵盖所有假如指数和JOIN条件,即(删除,collection_id,PROFILE_ID)。对Item执行相同操作。这可能会有帮助,但会使插入速度变慢。

如果SQL引擎由于约束仍然需要执行全表扫描,它将不会使用索引,对吗?

+0

我想你误会了。我想要结果删除= 0,所以我使用了98%的表。 – makeee 2010-04-08 07:46:08

+0

Rigth。我现在删除了第二点。 – hegemon 2010-04-08 08:19:00

1

首先,您通过位于favorites表中的聚集主键的favorites.id进行排序。这将不是必要的,你会加入favoritesitems而不是itemsfavorites

第二,(Itemremoved ='0')在WHERE中是过量的,因为JOIN中已经使用了相同的条件。

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

优化器将能够使用你的主键索引:

第三,加入到改变的条件的顺序。你甚至可以考虑在items表上创建(id,删除)索引。

接下来,创建(faver_profile_id,删除)在favorites(或更好更新faver_profile_id指数)指数以及在改变的条件下,以下列:

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

UPD:对不起,我错过了你已经加入favoritesitems。然后ORDER BY是不需要的。你应该导致类似如下:

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; 

还有一件事,当你有KEY idx_faver_idx_idfaver_profile_idid)你不需要KEY faver_profile_idfaver_profile_id),因为第二个指标只是复制的一半idx_faver_idx_id。正如我所建议的那样,我希望你能延长第二个指数。

+0

我不明白为什么我不需要“ORDER BY Favorites.id”。如果我把它放在“Item.id ASC”下面。我不认为索引(faver_profile_id,删除)将有很大帮助。我可以从查询中删除Item.removed = 0和Favorite.removed = 0,并且我仍然可以获得相同的执行时间。 – makeee 2010-04-08 16:04:36