我试图创建一个最优的查询,让数据库返回经常借阅科幻小说的读者的名字,这就是我要优化的:
SELECT reader.name,
COUNT (CASE WHEN book.status_id = 1 AND book.category_id = 2 THEN 1 END)
FROM reader
JOIN book ON book.reader_id = reader.id
GROUP BY reader.name
ORDER BY COUNT (CASE WHEN book.status_id = 1 AND book.category_id = 2 THEN 1 END) DESC
LIMIT 10;
除了INNER JOIN
或内存消耗增加之外,我如何改进查询?
这是我的ERD图:
2条答案
按热度按时间mqxuamgl1#
你可以试着在你的连接语句中添加你的条件,并且只使用总数,这实际上取决于你有多少数据等等。
vuv7lop32#
假设至少有10个读取器通过了标准(就像另一个答案也默默地假设),否则您得到的结果行少于10行。
从过滤器开始。在连接到第二个表之前 * 聚合&限制。更便宜:
在
(status_id, category_id)
上建立一个多列索引会有很大的帮助。或者,如果两个 predicate 中的任何一个是非常有选择性的,那么在两列中的一列上建立一个索引。如果这个特定查询的性能是您的首要目标,那么使用这个partial多列索引:通常,您会改变查询,那么最后一个索引就太专业化了。
补充要点:
reader_id
分组,reader_id
是主键(我假设)并保证是唯一的-与reader.name
相反!您的原始文件可能会完全失败,因为从ERD的外观来看,name
只是"名"。用
integer
分组通常比用varchar(25)
分组快得多(两次),但这是次要的,正确性是第一位的。surname
和reader_id
来消除相同名称的歧义(即使名称和姓氏也不一定是唯一的)。count(*)
比count(1)
快,但执行的操作完全相同。ORDER BY
子句中添加一个tiebreaker,以获得稳定的排序顺序和确定性结果。(否则,每次计数相同时,结果都可能不同。)