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还是喜欢使用完全索引扫描。