提高InnoDB计数(*)性能

NBh*_*tti 1 mysql performance innodb count

我有一张大桌子,上百万条记录。我必须count(*)为特定条件做一个,但是我无法摆脱它。

count()InnoDB非常昂贵。我一直在尝试找出MySQL的不同配置,但都是徒劳的。无法加快计数。该应用程序要求结果小于1秒,因为还有其他相关查询要运行。

由于InnoDB的计数方式,任何索引都无济于事。

mysql> EXPLAIN SELECT count(*) FROM `callrequests` WHERE active_call = 1;
+----+-------------+--------------+-------+---------------+-------------+---------+------+---------+--------------------------+
| id | select_type | table        | type  | possible_keys | key         | key_len | ref  | rows    | Extra                    |
+----+-------------+--------------+-------+---------------+-------------+---------+------+---------+--------------------------+
|  1 | SIMPLE      | callrequests | index | NULL          | active_call | 6       | NULL | 5271135 | Using where; Using index |
+----+-------------+--------------+-------+---------------+-------------+---------+------+---------+--------------------------+

mysql> show index from callrequests;
+--------------+------------+------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table        | Non_unique | Key_name                     | Seq_in_index | Column_name  | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------+------------+------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| callrequests |          0 | PRIMARY                      |            1 | id           | A         |     5271135 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          0 | PRIMARY                      |            2 | campaign_id  | A         |     5271135 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          0 | unique_contact               |            1 | campaign_id  | A         |        4849 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          0 | unique_contact               |            2 | contact_id   | A         |     5271135 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          0 | unique_contact               |            3 | contact      | A         |     5271135 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          1 | fk_callrequest_campaign1_idx |            1 | campaign_id  | A         |          10 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          1 | index4                       |            1 | campaign_id  | A         |        2506 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          1 | index4                       |            2 | contact      | A         |     5271135 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          1 | phonbook_id_index            |            1 | phonebook_id | A         |          10 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          1 | dnc_group_id_index           |            1 | dnc_group_id | A         |           2 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          1 | active_call                  |            1 | campaign_id  | A         |          12 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          1 | active_call                  |            2 | active_call  | A         |          16 |     NULL | NULL   | YES  | BTREE      |         |               |
| callrequests |          1 | call_status                  |            1 | call_status  | A         |        2518 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          1 | call_status                  |            2 | processed    | A         |        2518 |     NULL | NULL   |      | BTREE      |         |               |
| callrequests |          1 | call_status                  |            3 | active_call  | A         |        2518 |     NULL | NULL   | YES  | BTREE      |         |               |
+--------------+------------+------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
Run Code Online (Sandbox Code Playgroud)

服务器是 Xeon machine with 12 CPU cores and 64 GB RAM dedicated 5.6.14-62.0 Percona Server

innodb_buffer_pool_size38 GB,所有数据都位于innodb缓冲池中。

Mar*_*hor 6

我找到了提高 count(*) 性能的方法:

SELECT COUNT(*) FROM table WHERE id > 0;
Run Code Online (Sandbox Code Playgroud)

  • 这是什么巫术?它神奇地比 count(*) 快 50 倍 (4认同)

Gho*_*ler 5

innodb和myisam关于计数的区别

请注意,WHERE使用InnoDB进行计数并不比使用MyISAM慢。只是很裸

SELECT COUNT(*) FROM table
Run Code Online (Sandbox Code Playgroud)

可以使用MyISAM更快地计算出该数字,因为该数字存储在MyISAMs表元数据中。

例如,如果您有WHERE约束查询:

SELECT COUNT(*) FROM table WHERE active_calls = 1
Run Code Online (Sandbox Code Playgroud)

该查询需要访问两个存储引擎中的表数据,并且MyISAM和InnoDB之间应该没有明显的性能差异。

关于您的特定问题

请确保您的查询未使用任何适当的索引。这不是因为InnoDB“喜欢”全表扫描,而是因为不存在适当的索引。

您有一个组合索引(campaign_id, active_calls),但它active_calls是索引的第二部分。只要查询中未使用第一部分,MySQL都不容易访问第二部分。

对于此简单计数查询,您想要的是(active_calls)仅在该列上的另一个索引。然后它应该运行得很快。


Edw*_*Lee 5

Innodb 表的 COUNT(*) - Percona 数据库性能博客\n https://www.percona.com/blog/2006/12/01/count-for-innodb-tables/

\n\n

因此,如果您有像SELECT COUNT(*) FROM USERfaster这样的查询,这对于MyISAM (MEMORY 和其他一些)表来说会很重要,因为它们只是从存储的值中读取表中的行数。然而, Innodb需要执行full table scan,或者full index scan因为它没有这样的计数器,它也可以通过 Innodb 表的简单单计数器来解决,因为不同的事务可能会看到表中不同的行数。

\n\n

如果您有像SELECT COUNT(*) FROM IMAGE WHERE USER_ID=5这样的查询,则对于 MyISAM 和 Innodb 表,此查询将以相同的方式执行index range scan。对于 MyISAM 和 Innodb,这可能更快或更慢,具体取决于各种条件。

\n\n

因此请记住,Innodb 对于 ALL COUNT(*) 查询并不慢,但仅对于不带 WHERE 子句的 COUNT(*) 查询的非常特定情况而言慢。

\n