2012-11-14 22 views
0

爲什麼下面的查詢失敗它使用story_id,在story_keywords表中?Filesort查詢,有索引,但沒有使用它

mysql> EXPLAIN SELECT `stories`.* 
    -> FROM (`stories`) 
    -> JOIN `story_keywords` ON `story_keywords`.`story_id` = `stories`.`id` 
    -> WHERE `image_full_url` != '' 
    -> AND `order` != 0 
    -> AND `news_type` IN ('movie', 'movie_review') 
    -> AND `keyword` IN ('topnews', 'toptablet') 
    -> GROUP BY `stories`.`id` 
    -> ORDER BY `created` DESC, `order` DESC 
    -> LIMIT 5 ; 
+----+-------------+----------------+--------+---------------+---------+---------+---------------------------------------+------+----------------------------------------------+ 
| id | select_type | table   | type | possible_keys | key  | key_len | ref         | rows | Extra          | 
+----+-------------+----------------+--------+---------------+---------+---------+---------------------------------------+------+----------------------------------------------+ 
| 1 | SIMPLE  | story_keywords | ALL | story_id  | NULL | NULL | NULL         | 42 | Using where; Using temporary; Using filesort | 
| 1 | SIMPLE  | stories  | eq_ref | PRIMARY  | PRIMARY | 767  | entertainment.story_keywords.story_id | 1 | Using where         | 
+----+-------------+----------------+--------+---------------+---------+---------+---------------------------------------+------+----------------------------------------------+ 
2 rows in set (0.00 sec) 


mysql> show create table stories; 
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Table | Create Table                                                                                                                                                                                                          | 
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| stories | CREATE TABLE `stories` (
    `id` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `news_type` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `created` datetime DEFAULT NULL, 
    `author` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `author_title` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `image_caption` text COLLATE utf8_unicode_ci, 
    `image_credit` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `image_full_url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `body` text COLLATE utf8_unicode_ci, 
    `summary` text COLLATE utf8_unicode_ci, 
    `external_url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `order` int(10) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci | 
+---------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0.00 sec) 

mysql> show create table story_keywords; 
+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Table   | Create Table                                                                              | 
+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| story_keywords | CREATE TABLE `story_keywords` (
    `id` int(10) NOT NULL AUTO_INCREMENT, 
    `story_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    `keyword` varchar(255) COLLATE utf8_unicode_ci NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `story_id` (`story_id`) 
) ENGINE=MyISAM AUTO_INCREMENT=85 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci | 
+----------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0.00 sec) 
+0

如何以及以何種順序創建索引以便使用它們。我嘗試過創建它們,但我學會了順序。 –

+0

我的猜測是,這是因爲'story_keywords.story_id'是一個'VARCHAR',它應該可能是'INT'類型之一。如果這不是完全的原因,那肯定無助於情況。 'stories.id'應該也可以是'INT'類型。附:我正在寫一個答案,除了這一點,我還發現了一些其他的東西。 –

回答

1

這可能是因爲MySQL認爲它是便宜從story_keywords表中提取所有行和中,而不是使用索引加入他們的行列。這聽起來很奇怪,但是,你會發現,如果你必須在一個表上執行100次索引查找,並且這個表只有大約100行 - 讀取所有行花費會更少。其解釋很簡單:索引查找(對於BTREE索引)是O(ln N),而讀取N行是O(N)。顯然,O(N)N * O(InN)。

爲了證明這一點 - 嘗試從故事只選擇1行(和一個我的意思是一排,而不是排序整個表,限制的結果),就像:

SELECT `stories`.* 
FROM (`stories`) 
JOIN `story_keywords` ON `story_keywords`.`story_id` = `stories`.`id` 
WHERE `stories`.id = SOMETHING 

該查詢多更有可能轉向在story_keywords上編制索引。

希望這回答你的問題:)

1

安東是在正確的軌道上,但我相信還有更多的問題。正如我對OP的評論所說,id列很可能是INT類型。如解釋所示,stories上的主鍵長度爲767.通常,對於INT類型,長度將爲低位單個數字,但由於該列爲VARCHAR,因此該長度非常長。

回到主要的問題,因爲有上stories.news_typestories.order,或story_keywords.story_keywords沒有索引,優化決定做的story_keywords一個完整的掃描,因爲它會產生最小的初始結果集。如果其中一列有索引,它可能會首先使用它。如果添加查詢可以使用的索引,則不需要執行全表掃描。

+0

以何種順序將索引添加到news_type,order和story_keywords –

+0

@ChrisMuench對於您發佈的查詢,'news_type'或'keyword'上的單個索引會很有幫助。優化器會選擇哪一個取決於您的數據。嘗試添加這些索引並再次「解釋」。 –

相關問題