感谢您的关注。
有两个INNODB表:
表authors
id INT
nickname VARCHAR(50)
status ENUM('active', 'blocked')
about TEXT
表图书
author_id INT
title VARCHAR(150)
我正在对这些表运行一个查询,以获取每个作者和他拥有的书籍数:
SELECT a. * , COUNT( b.id ) AS book_count
FROM authors AS a, books AS b
WHERE a.status != 'blocked'
AND b.author_id = a.id
GROUP BY a.id
ORDER BY a.nickname
此查询非常慢(执行时间约为6秒)。我在books.author_id
上有一个索引,它工作得很好,但是我不知道如何在authors
表上创建一个索引,这样这个查询就可以使用它。
以下是当前解释的外观:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE a ALL PRIMARY,id_status_nickname NULL NULL NULL 3305 Using where; Using temporary; Using filesort
1 SIMPLE b ref key_author_id key_author_id 5 a.id 2 Using where; Using index
我看过使用组优化查询的MySQL手册,但不知道如何将它应用于我的查询。
我将感谢关于这方面的任何帮助和提示--索引结构必须是什么,这样MySQL才能使用它?
编辑
我试过:
(id, status, nickname)
(status, nickname)
两者都导致了同样的情况。
发布于 2011-01-10 09:38:20
我假设id_status_nickname是一个复合索引(id、status、昵称)。在查询中,可以使用a.status != blocked来过滤行。这方面有以下问题:
您可以尝试这样做:将索引创建为(状态、id、昵称)并使用status='active‘。我的猜测是,由于您使用的是'=‘,状态是索引的前缀,它应该选择这个索引,然后将其用于group by,然后排序by.Hope,这很有帮助。
UPDATE:当WHERE子句没有按顺序使用WHERE子句时,似乎不可能避免文件短。
发布于 2011-01-10 08:48:08
我会尝试一个索引(状态,昵称)。这应该消除了“使用文件短”的必要性。
https://stackoverflow.com/questions/4649089
复制