Mysql sum group by performance 9M记录

标签 mysql

我有一个包含约 900 万条记录的表

结构

 id                           int PK AI
 pa_id                        int
 cha_id                       smallint
 cha_level                    tinyint
 cha_points                   mediumint
 cha_points_till              smallint
 cha_points_from              medium
 cha_points_date              datetime

我的查询

select max(cha_points) as highest,cha_id,count(id) as entry_count,
sum(cha_points) as total_points 
          from playeraccounts_cha_masteries 
          group by cha_id 
          order by total_points desc

我的索引

playeraccounts_cha_masteries 0 PRIMARY    1 id         A 9058483 NULL NULL BTREE
playeraccounts_cha_masteries 1 cha_id     1 cha_id     A       9 NULL NULL BTREE
playeraccounts_cha_masteries 1 pa_id      1 pa_id      A  156270 NULL NULL BTREE
playeraccounts_cha_masteries 1 cha_points 1 cha_points A  166100 NULL NULL BTREE

pa_id 上的索引在不同的查询中有其用途。

解释

id select_type table partitions  type  possible_keys     key key_len  ref    rows   filterd    Extra
 1      simple     m       null range PRIMARY,cha_id PRIMARY       4 NULL 9164555    100.00    Using where; Using temporary; Using filesort

还有什么可以加快查询速度的吗?

最佳答案

您有 3 个选择:

  1. 加快现有查询

在cha_id 和cha_points 字段上创建一个复合索引,将count(id) 更改为count(*) 或count(cha_id),然后再次测试。您可能需要调整索引中字段的顺序。检查是否使用了覆盖索引。

通过将 count(id) 更改为 count(*) 或 count(cha_id),您无需检查 id 列。由于您使用该计数返回每个 cha_id 组中的记录数,因此可以安全地将对 id 字段的引用替换为 * 或 cha_id。

在 cha_id 和 cha_points 字段上创建复合索引将导致覆盖索引,这意味着查询所需的所有字段都在一个索引中,因此查询不必扫描整个表。

  1. 创建一个单独的统计表并用触发器更新它

为 playeraccounts_cha_masteries 创建一个单独的统计表。您可以使用触发器来更新计数、最大值和总数。该页面将查询统计表而不是 playeraccounts_cha_masteries 表。此解决方案可能会减慢插入/更新/删除速度,因为每个数据修改事务都必须序列化,以便正确更新统计表。

  1. 创建单独的统计表并定期更新

创建一个单独的统计表,但不是使用触发器来保持它不断更新,而是使用计划作业(OS 或 mysql 级别)使用最新统计信息定期更新表。这意味着统计数据将在一段时间内不同步,但如果可以找到可接受的刷新周期,这可能是一个合理的妥协。

您甚至可以将此方法更进一步,而不是生成单独的统计表,您可以生成一个静态 html 文件,在其 header 中设置适当的到期时间和统计信息。这样服务器只需为统计数据提供静态文件。

关于Mysql sum group by performance 9M记录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34940822/

相关文章:

mysql - WordPress 自定义订单按帖子标题中的姓氏过滤

mysql - SQL 查询查找在另一个表中具有某些值的用户

mysql - 从 tps 转换为 csv

mysql - 每天存储 2000 万行的最佳免费方式?

php - 我如何使用mysql进行关键字搜索

mysql - NodeJS mysql 异步查询

php - 将记录移动到新表并相应更新原始 ID

mysql - 使用 Hibernate 在 MySQL 时间戳列中存储毫秒数

php - 如何将原始 SQL 查询转换为 Silverstripe SQLQuery 抽象层

mysql - 如果表中多次出现相同的名称,并且某个列有 2 种不同类型的数据,则不要选择任何具有该名称的行