提高InnoDB数量(*)的性能

时间:2014-03-12 12:48:11

标签: mysql performance count innodb

我有一张包含数百万条记录的大桌子。我必须为某个标准做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      |         |               |
+--------------+------------+------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+---------------+

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

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

4 个答案:

答案 0 :(得分:4)

innodb和myisam之间关于计数的区别

请注意,InnoDB使用WHERE计数并不比使用MyISAM计算慢。只有一个非常简单的

SELECT COUNT(*) FROM table
使用MyISAM可以更快地计算

,因为此数字存储在MyISAMs表元数据中。

如果您的查询包含WHERE约束,例如:

SELECT COUNT(*) FROM table WHERE active_calls = 1

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

关于您的具体问题

请查看您的查询未使用任何正确的索引。这不是因为InnoDB"更喜欢"全表扫描,但因为没有合适的索引。

您有一个组合索引(campaign_id, active_calls),但active_calls是索引的第二部分。只要查询中没有使用第一部分,MySQL就无法轻松访问第二部分。

这个简单计数查询的目的是仅在这一列上的另一个索引(active_calls)。它应该快速运行。

答案 1 :(得分:0)

Innodb表的

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

因此,如果您有来自用户的 SELECT COUNT(*)之类的查询,对于 MyISAM 表(MEMORY和其他一些表),faster将会很多只会从存储的值中读取表中的行数。但是 Innodb 将需要执行full table scanfull index scan,因为它没有这样的计数器,对于简单的Innodb表计数器也无法解决,因为不同的事务可能在表格中看到不同的行数。

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

因此请记住,对于所有COUNT(*)查询而言,Innodb的运行速度并不慢,而对于不带WHERE子句的COUNT(*)查询非常特殊的情况。

答案 2 :(得分:0)

我遇到了类似的问题。我还有一个 int 自动增量主键列。所以我通过这样做解决了这个问题:

select max(id) from table

@mark-khor(其中 id > 0)的建议也对我有用,但我不明白为什么,所以我选择了 max(id)-value...

答案 3 :(得分:-1)

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

SELECT COUNT(*) FROM table WHERE id > 0;