如何使用其中的“ GROUP BY”加快查询速度?

时间:2019-02-19 20:17:52

标签: indexing group-by mariadb

详细信息:

  • MariaDB:服务器版本:10.2.10-MariaDB MariaDB服务器
  • 数据库表trans_tbl正在使用Aria DB引擎
  • 表有些大:126,006,123行
  • 服务器一点也不大:带附加30GB EBS的AWS t3 micro

我对该数据库表应用了索引,如下所示:

  • 主键:evt_id
  • 我要分组的列上的另一个索引:transaction_type

3个相关问题:

  1. 为什么执行以下操作时会忽略transaction_type索引?

    SELECT COUNT(evt_id), transaction_type FROM trans_tbl GROUP BY transaction_type
    

    如果我查看EXPLAIN的输出,就会看到:

    MariaDB [my_db]> EXPLAIN SELECT COUNT(evt_id), transaction_type FROM trans_tbl GROUP BY transaction_type;
    +------+-------------+-----------+------+---------------+------+---------+------+-----------+---------------------------------+
    | id   | select_type | table     | type | possible_keys | key  | key_len | ref  | rows      | Extra                           |
    +------+-------------+-----------+------+---------------+------+---------+------+-----------+---------------------------------+
    |    1 | SIMPLE      | trans_tbl | ALL  | NULL          | NULL | NULL    | NULL | 126006123 | Using temporary; Using filesort |
    +------+-------------+-----------+------+---------------+------+---------+------+-----------+---------------------------------+
    

    这让我感到困惑的是,查询中的两者都已建立索引。因此,不应该利用索引吗?

  2. 为什么在以下情况下使用transaction_type索引,为什么我所做的一切都从COUNT(evt_id)(主键)切换了?到COUNT(1)。 (该列为transaction_type,从该列生成的索引称为TransType。)

    MariaDB [my_db]> EXPLAIN SELECT COUNT(1), transaction_type FROM trans_tbl GROUP BY transaction_type;
    +------+-------------+-----------+-------+---------------+-----------+---------+------+-----------+-------------+
    | id   | select_type | table     | type  | possible_keys | key       | key_len | ref  | rows      | Extra       |
    +------+-------------+-----------+-------+---------------+-----------+---------+------+-----------+-------------+
    |    1 | SIMPLE      | trans_tbl | index | NULL          | TransType | 35      | NULL | 126006123 | Using index |
    +------+-------------+-----------+-------+---------------+-----------+---------+------+-----------+-------------+
    
  3. 第一个查询(带有COUNT(evt_id))耗时2分40秒。由于未使用索引,因此很有意义。但是第二个查询(使用COUNT(1))需要50秒。这对我来说毫无意义。基本上不应该花0秒吗?难道不能只看每组的第一个和最后一个索引值,然后减去它们并计数吗?在我看来,它实际上确实在计数。索引的意义是什么?

    • 我想我更重要的问题是:我如何设置索引以允许对该索引进行分组,从而可以像我期望的那样几乎立即返回结果?

PS我知道对于这种大小的DB表,该机器的功能不足。但是,表数据不值得花很多钱来提高性能。我宁愿学习适当地实现Aria索引以提高速度。

1 个答案:

答案 0 :(得分:1)

COUNT(x)在对行进行计数之前检查x是否为NOT NULL

COUNT(*)是计数行的常用模式。

所以...

SELECT COUNT(evt_id), transaction_t is just `SELECT FIND_IN_SET(17, '8,12,17,90');`ype
    FROM trans_tbl GROUP BY transaction_type;

决定进行表格扫描,然后进行排序和分组。

SELECT COUNT(*), transaction_type
    FROM trans_tbl GROUP BY transaction_type;

看到INDEX(transaction_type)并说“天哪;我可以扫描该索引而不必进行排序”。注意:它仍然必须扫描才能计数。但是INDEX比表小,因此可以更快地完成。这也称为“覆盖”索引,因为SELECT中所需的所有列都位于该INDEX中。

COUNT(1) 可能COUNT(*)一样,我不知道。

INDEX(transaction_type)INDEX(transaction_type, evt_id)基本相同。这是因为PRIMARY KEY被默默地附加到InnoDB中的任何辅助键上。

我不知道为什么不使用INDEX(transaction_type, evt_id)。底线:使用COUNT(*)

为什么不是0秒?计数不会保存在任何地方。无论如何,当您运行SELECT时,可能会有其他查询修改计数。改进来自扫描126M的2列行,而不是126M的多列行。