2

item_tag_map有两列item_idtag_id并且它们都有索引。

这是一个数据示例:

item_id     tag_id
1           1
1           3
4           7
1           5
3           1
3           8
6           8
10          4

现在我想获取具有标签 1、2、3、5 的项目 ID,并按所有标签的总数对结果进行排序。

这是一个结果示例:

item_id     count(m.tag_id)
1           3
3           1

我尝试的 SQL 是:

SELECT m.item_id,count(m.tag_id) from item_tag_map AS m
WHERE tag_id in(1,2,3,5)
GROUP BY m.item_id
ORDER BY count(m.tag_id)
LIMIT 10

该表中有大约 10k 行,查询非常慢。我试图删除所有count语句,然后它变得比以前非常快。

为什么会count减慢这个查询?如何优化此查询以使其快速?

4

1 回答 1

4

这是因为ORDER BY COUNT(m.tag_id).
MySQL 需要获取所有行(即进行全表扫描)来计算item_id.

在这种情况下,MySQL 无法使用索引。(正如您在查看时可能意识到的那样EXPLAIN SELECT ..

当您COUNT()ORDER BY子句中删除时,MySQL 能够使用索引进行排序。


一种可能的解决方案是创建一个物化视图,其中 DBMS 将tag_id每个值的计数缓存item_id在一个单独的表中。

MySQL 本身不支持物化视图,但您可以模拟它们:
您可以使用相关查询 ( INSERT INTO tag_counts SELECT ...) 最初创建表一次,然后使用ON [INSERT | DELETE]触发器保持更新。或者,有一个名为FlexViews
的第三方软件可以为您自动执行此过程。

这就是我保持每周数百万行统计数据库反应的方式。

于 2012-10-29T09:09:24.167 回答