Mysql按性能记录分组求和

Mysql按性能记录分组求和,mysql,Mysql,我有一张有900万张唱片的桌子 结构 id int PK AI pa_id int cha_id smallint cha_level tinyint cha_points mediumint cha_points_till smallint

我有一张有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种选择:

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

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

    在chau id和chau points字段上创建复合索引将生成覆盖索引,这意味着查询所需的所有字段都在单个索引中,因此查询不必扫描整个表

  • 创建一个单独的统计表并使用触发器更新它
  • 为玩家帐户设置一个单独的统计表。您可以使用触发器更新计数、最大值和总数。该页面将查询统计表,而不是playeraccounts\u cha\u masteries表。此解决方案可能会降低插入/更新/删除的速度,因为每个数据修改事务都必须序列化,以便正确更新统计表

  • 创建单独的统计表并定期更新
  • 创建一个单独的统计表,但不要使用触发器使其不断更新,而是使用计划作业(OS或mysql级别)定期使用最新统计信息更新表。这意味着统计数据将有一段时间不同步,但如果可以找到一个可接受的刷新周期,这可能是一个合理的折衷方案

    您甚至可以进一步采用这种方法,而不是生成一个单独的统计表,您可以生成一个静态html文件,该文件的头中设置了适当的过期时间,并带有统计信息。这样,服务器只需为统计数据提供静态文件。

    您有3个选项:

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

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

    在chau id和chau points字段上创建复合索引将生成覆盖索引,这意味着查询所需的所有字段都在单个索引中,因此查询不必扫描整个表

  • 创建一个单独的统计表并使用触发器更新它
  • 为玩家帐户设置一个单独的统计表。您可以使用触发器更新计数、最大值和总数。该页面将查询统计表,而不是playeraccounts\u cha\u masteries表。此解决方案可能会降低插入/更新/删除的速度,因为每个数据修改事务都必须序列化,以便正确更新统计表

  • 创建单独的统计表并定期更新
  • 创建一个单独的统计表,但不要使用触发器使其不断更新,而是使用计划作业(OS或mysql级别)定期使用最新统计信息更新表。这意味着统计数据将有一段时间不同步,但如果可以找到一个可接受的刷新周期,这可能是一个合理的折衷方案


    您甚至可以进一步采用这种方法,而不是生成一个单独的统计表,您可以生成一个静态html文件,该文件的头中设置了适当的过期时间,并带有统计信息。这样,服务器只需为统计数据提供静态文件。

    您使用分区了吗?因为这是一个完整的表查找,所以不会使用分区的效果吗?请添加解释结果。此外,您需要多久运行一次此查询?您可能想考虑使用单独的表来保存这些数据,这些数据可以使用触发器进行更新,也可以通过定期执行上述查询来刷新快照。它应该在用户基本上请求页面时运行。用户可以每3天更新他们的记录(用pa_id标识)。您使用分区吗?因为这是一个完整的表查找,不会使用分区的效果吗?请添加解释的结果。此外,您需要多久运行一次此查询?您可能想考虑使用单独的表来保存这些数据,这些数据可以使用触发器进行更新,也可以通过定期执行上述查询来刷新快照。它应该在用户基本上请求页面时运行。用户可以每3天更新一次他们的记录(用pa_id标识)。我决定使用单独的表格方法,这也允许我有一个与点相关的时间线。我决定使用单独的表格方法,这也允许我有一个与点相关的时间线。