我有两张桌子(实际上更多,但只对这两张桌子感兴趣)。
USER_ACTION (ID, ID_USER, ID_ACTION, TMST) AS A
ACTION (ID, DATA, NUM_USERS) AS B
但是,B.NUM_USERS实际上是USER_ACTION中具有A.ID_ACTION = B.ID
的记录数的表示。这是否可以接受为性能优化(一个非常常见的查询经常恢复ACTION数据),或者因为这打破了关系模型,这是一个坏主意,查询应该是:
SELECT B.ID, B.DATA, count(*) AS NUM_USERS
FROM ACTION B JOIN USER_ACTION A ON A.ID_ACTION = B.ID
WHERE B.ID = ?
GROUP BY B.ID
如果第二个选项是正确的答案,我是否应该设置任何索引来优化此查询?
- 编辑 -
使用当前模型运行Explain,但是anonimyzed(所选操作的8个用户):
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE B const PRIMARY PRIMARY 8 const 1
1 SIMPLE A ref FK_USER_ACTION FK_USER_ACTION 8 const 8 Using index
答案 0 :(得分:0)
我建议按照您的描述保留查询,并在ACTION中的USER_ACTION和ID中的ID_ACTION上添加索引。
您的where filter和group by都将受益于ACTION上的索引,而对USER_ACTION的连接应该是eq_ref连接(更多信息http://www.sitepoint.com/using-explain-to-write-better-mysql-queries/),这在大多数情况下会很快。在查询前使用EXPLAIN EXTENDED来验证操作计划。如果您开始注意到任何缓慢,您还可以使用复合索引(ID,DATA)在ACTION中索引DATA。这会给你一个覆盖索引,但我怀疑使用ID索引DATA的成本是否真的值得(更多信息:http://www.mysqlperformanceblog.com/2006/11/23/covering-index-and-prefix-indexes/ ...旧的,但仍适用)
通常,如果有许多count()是几千行,您可能需要通过物化视图或cron作业或其他来考虑汇总表。计算()超过(例如)100k行的速度仍然比预先计算的要慢。但基本上你不应该注意到很慢,直到你在USER_ACTION中处理数千行需要计数(*)'d才能返回结果。坦率地说,我不认为你会遇到那个问题...所以你应该没问题,你用我所做的指数描述的联接。使用EXPLAIN EXTENDED验证。另请注意,如果您使用INNODB(例如http://dev.mysql.com/doc/refman/5.5/en/innodb-buffer-pool.html),LRU可能会在这里发挥作用。需要注意的是,你想要实现的概念存在。