Mysql 提高InnoDB计数(*)性能

Mysql 提高InnoDB计数(*)性能,mysql,performance,count,innodb,Mysql,Performance,Count,Innodb,我有一张有一百万张唱片的大桌子。我必须对某个标准进行count(*),我无法摆脱它 使用InnoDB的count()非常昂贵。我一直试图找出MySQL的不同配置,但都是徒劳的。无法加快计数。应用程序要求结果小于1秒,因为还有其他依赖查询要运行 由于InnoDB计数的方式,任何索引都没有帮助 mysql> EXPLAIN SELECT count(*) FROM `callrequests` WHERE active_call = 1; +----+-------------+-------

我有一张有一百万张唱片的大桌子。我必须对某个标准进行
count(*)
,我无法摆脱它

使用InnoDB的
count()
非常昂贵。我一直试图找出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机器,具有12个CPU内核和64 GB RAM专用5.6.14-62.0 Percona服务器


我的
innodb\u buffer\u pool\u size
38 GB
,所有数据都位于innodb缓冲池中

innodb和myisam在计数方面的差异 请注意,InnoDB中使用
进行计数的速度并不比MyISAM慢。只有一个非常简陋的房间

SELECT COUNT(*) FROM table
使用MyISAM可以更快地计算,因为此数字存储在MyISAM表元数据中

如果您有一个带有
WHERE
约束的查询,例如:

SELECT COUNT(*) FROM table WHERE active_calls = 1
查询需要访问两个存储引擎中的表数据,MyISAM和InnoDB之间应该没有明显的性能差异

关于你的具体问题 请确保您的查询没有使用任何正确的索引。这不是因为InnoDB“更喜欢”完整表扫描,而是因为不存在适当的索引

您有一个组合索引
(活动id,活动调用)
,但
活动调用
是索引的第二部分。只要在查询中不使用第一部分,MySQL就不容易访问第二部分

对于这个简单的计数查询,您需要的是另一个索引
(active\u calls)
,仅在这一列上。它应该运行得很快。

innodb和myisam在计数方面的差异 请注意,InnoDB中使用
进行计数的速度并不比MyISAM慢。只有一个非常简陋的房间

SELECT COUNT(*) FROM table
使用MyISAM可以更快地计算,因为此数字存储在MyISAM表元数据中

如果您有一个带有
WHERE
约束的查询,例如:

SELECT COUNT(*) FROM table WHERE active_calls = 1
查询需要访问两个存储引擎中的表数据,MyISAM和InnoDB之间应该没有明显的性能差异

关于你的具体问题 请确保您的查询没有使用任何正确的索引。这不是因为InnoDB“更喜欢”完整表扫描,而是因为不存在适当的索引

您有一个组合索引
(活动id,活动调用)
,但
活动调用
是索引的第二部分。只要在查询中不使用第一部分,MySQL就不容易访问第二部分

对于这个简单的计数查询,您需要的是另一个索引
(active\u calls)
,仅在这一列上。它应该运行得很快。

COUNT(*)for Innodb表-Percona数据库性能博客

因此,如果您有类似于SELECT COUNT(*)FROM USER的查询,那么MyISAM(内存和其他一些)表的查询速度将大大加快,因为它们只需从存储值中读取表中的行数。然而,Innodb需要执行
全表扫描
全索引扫描
,因为它没有这样的计数器,它也不能通过Innodb表的简单单计数器来解决,因为不同的事务可能会看到表中不同的行数

如果您有类似于的查询,请从用户_ID=5的图像中选择COUNT(*)此查询将通过执行
索引范围扫描来对MyISAM和Innodb表执行相同的方式。MyISAM和Innodb的速度可能更快,也可能更慢,具体取决于各种条件

所以请记住,Innodb并不是对所有COUNT(*)查询都很慢,而是只对非常特定的COUNT(*)查询(不带WHERE子句)慢。

COUNT(*)用于Innodb表-Percona数据库性能博客

因此,如果您有类似于SELECT COUNT(*)FROM USER的查询,那么MyISAM(内存和其他一些)表的查询速度将大大加快,因为它们只需从存储值中读取表中的行数。然而,Innodb需要执行
全表扫描
全索引扫描
,因为它没有这样的计数器,它也不能通过Innodb表的简单单计数器来解决,因为不同的事务可能会看到表中不同的行数

如果您有类似于的查询,请从用户_ID=5的图像中选择COUNT(*)此查询将通过执行
索引范围扫描来对MyISAM和Innodb表执行相同的方式。MyISAM和Innodb的速度可能更快,也可能更慢,具体取决于各种条件


所以请记住,Innodb并不是对所有COUNT(*)查询都很慢,而是只对COUNT(*)查询中不带WHERE子句的特定情况慢。

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


我找到了改进count(*)性能的方法:


我也有类似的问题。我还有一个int自动递增主键列。因此,我通过这样做绕过了这个问题:

select max(id) from table

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

我也遇到了类似的问题。我还有一个int自动递增主键列。因此,我通过这样做绕过了这个问题:

select max(id) from table

另外,@mark khor(其中id>0)的建议对我也有用,但我不明白为什么,所以我选择了最大(id)值…

innodb\u buffer\u pool\u size
是38 GB?你有活动调用的索引吗?格式糟糕的解释表明索引确实存在,但MySQL更喜欢完整的索引扫描。你能显示callrequests\G中的索引吗?@fancyPants:我知道我只是在确认,因为问题中没有提到GB。好吧,InnoDB还是喜欢使用完全索引扫描。