感谢您的关注。
有两个INNODB表:
表作者
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
表上创建索引,以便此查询可以使用它。
以下是当前EXPLAIN的外观:
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 manual on optimizing queries with group by,但无法弄清楚如何将其应用于我的查询。
我会感谢任何关于此的帮助和提示 - 索引结构必须是什么,以便MySQL可以使用它?
我试过了:
(id, status, nickname)
(status, nickname)
两者都导致了同样的情况。
答案 0 :(得分:3)
我假设id_status_nickname是一个复合索引(id,status,nickname)。在您的查询中,您通过说a.status!= blocked来过滤行。这有以下问题:
你可以试试这个:创建索引为(status,id,nickname)并使用status ='active'。我的猜测是,因为你使用'='并且status是索引的前缀,所以它应该选择这个索引,然后将它用于group by然后按顺序排序。希望这有帮助。
更新: 当WHERE子句没有ORDER BY中使用的字段时,看起来无法避免使用filesort。
答案 1 :(得分:0)
我会尝试索引(状态,昵称)。这应该摆脱“使用filesort”的必要性。