2013-04-23 122 views
1

我有一个关于MySQL性能的问题。 这些都是我的表:MySQL优化计数查询

(约140.000记录)

CREATE TABLE IF NOT EXISTS `article` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `label` varchar(256) COLLATE utf8_unicode_ci NOT NULL, 
    `title` varchar(256) COLLATE utf8_unicode_ci NOT NULL, 
    `intro` text COLLATE utf8_unicode_ci NOT NULL, 
    `content` text COLLATE utf8_unicode_ci NOT NULL, 
    `date` int(11) NOT NULL, 
    `active` int(1) NOT NULL, 
    `language_id` int(11) NOT NULL, 
    `category_id` int(11) NOT NULL, 
    `indexed` int(1) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=132911 ; 

(约400.000记录)

CREATE TABLE IF NOT EXISTS `article_category` (
    `article_id` int(11) NOT NULL, 
    `category_id` int(11) NOT NULL 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

运行此统计查询:

SELECT SQL_NO_CACHE COUNT(id) as total 
FROM (`article`) 
LEFT JOIN `article_category` ON `article_category`.`article_id` = `article`.`id` 
WHERE `article`.`language_id` = 1 
AND `article_category`.`category_id` = '<catid>' 

此查询需要很多资源,所以我想知道如何优化这个查询。 执行它的缓存后,所以在第一次运行后,我很好。

运行EXPLAIN功能:

enter image description here

后创建索引:

ALTER TABLE `article_category` ADD INDEX (`article_id` , `category_id`) ; 

enter image description here

添加索引和改变LEFT加入后加入查询运行快得多! 感谢这么快回信:)

QUERY我现在用的(我删除了LANGUAGE_ID,因为这并不是说neccesary):

SELECT COUNT(id) as total 
FROM (`article`) 
JOIN `article_category` ON `article_category`.`article_id` = `article`.`id` 
AND `article_category`.`category_id` = '<catid>' 

我读过一些有关强制的指标,但我认为是因为这些表已经被编入索引,所以不再需要了吧?

非常感谢!

的Martijn

+0

向我们展示EXPLAIN的结果 2013-04-23 11:45:13

+0

在'article_category.article_id'上添加一个索引。 – Barmar 2013-04-23 11:45:33

+1

要么你不应该做'LEFT JOIN',或者你需要在'ON'子句中测试'category_id = '。否则,您会过滤掉“article_categories”中没有匹配的文章。 – Barmar 2013-04-23 11:50:11

回答

2

您没有在表上创建索引所需

article_category - 上(article_id, category_id)

article建立复合索引 - 创建于(id, language_id)

一个复合索引。如果这没有帮助发布解释说明。

1

JOIN条件中使用应该有一个索引,所以你需要指数article_id列。