2010-04-08 88 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