MySQL按查询进行分组,不使用索引,滞后于使用文件排序

标签 mysql group-by database-performance database-optimization filesort

鉴于下表...

CREATE TABLE values_table (
  id int(11) NOT NULL auto_increment,
  account_id int(11) NOT NULL,
  user_id int(11) NOT NULL,
  model varchar(255) NOT NULL,
  ...
  value1 int(11) NOT NULL default '0',
  value2 int(11) NOT NULL default '0',
  value3 int(11) NOT NULL default '0',
  value4 int(11) NOT NULL default '0',
  PRIMARY KEY  (id),
  ....
) ENGINE=InnoDB AUTO_INCREMENT=2364641 DEFAULT CHARSET=utf8;

以及以下查询...

SELECT user_id, SUM(value1) AS value1, SUM(value2) AS value2, SUM(value3) AS value3, SUM(value4) as value4
from values_table
where account_id = 10 and model = 'ModelName'
group by user_id;

...应该将哪些字段添加到索引中以及以何种顺序添加以确保执行不会结束使用临时;使用文件排序;

我已尝试调整 http://mysqldba.blogspot.com/2008/06/how-to-pick-indexes-for-order-by-and.html 中描述的详细信息和 http://dev.mysql.com/doc/refman/5.0/en/group-by-optimization.html没有运气。

更新 我尝试过 (account_id, model), (account_id, model, user_id), (account_id, model, user_id, value1, value2, value3, value4) 。它们都不会阻止使用临时表和文件排序。

最佳答案

我的印象是,当所有列都在索引中时,MySQL 只能使用索引优化group by。然后,只能优化这些查询的子集。您的问题已经指向文档,但这是最新的 version .

您可以通过(account_id, model)上的索引来减少数据量。但是,您可能仍然有很多匹配项,然后 MySQL 对索引和group by 变得挑剔。

有一种方法可以让 MySQL 使用索引进行聚合。如果您只有一个计算列,那么您可以尝试:

select u.user_id,
       (select sum(v.value1)
        from values_table v
        where v.account_id = 10 and v.model = 'ModelName' and
              v.user_id = u.user_id
       ) as sum1
from (select distinct user_id
      from values_table
      where v.account_id = 10 and v.model = 'ModelName'
     ) u
group by u.user_id;

这应该对 from 中的子查询使用 values_table(account_id, model, user_id) 上的索引。它还应该使用相关子查询的索引:values_table(user_id, account_id, model, value1) 是理想的。但是,您必须为输出中的每一列重复此构造(可能还有最佳索引)。如果有十个聚合列,一个聚合列的速度可能会受到影响。

如果这不起作用,那么您的选择就更少了:

  • 确定您确实需要限制性更强的 where 子句来减少数据量。
  • 使用触发器在用户级别维护预先聚合的数据。

关于MySQL按查询进行分组,不使用索引,滞后于使用文件排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33045300/

相关文章:

oracle - 提高查询性能——从oracle中选择数据到postgresql

php - 如何将产品的 id 存储在数组中

使用 UNION 时 MySQL Count(*) 问题

PHP print_r num_rows => 9 但空白页

c# - 使用 linq 基于多个条件对数据库条目进行排序

不使用索引的 MySQL 连接性能

mysql - mysql中单个schema的全局状态

php - 如何使用 for 循环和 union all 按列进行分组

mysql - 仅当谓词在所有分组字段上都为真时才选择 GROUP BY 语句

mysql - 使用街道地址作为主键的最佳实践是什么?