Description:
Query performance degraded for "SELECT COUNT(*) FROM <TABLE_NAME>" on 8.0 compared to 5.7.
We can see below that query1 performance remained almost same on both version. However, query2 which has 8 times the execution time on 8.0 than on 5.7.
| 5.7.42-log | MySQL Community Server (GPL) |
mysql [localhost:5742] {msandbox} (test) > SHOW PROFILES;
+----------+------------+-------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-------------------------------------+
| 1 | 0.16019925 | SELECT COUNT(*) FROM T1 WHERE c > 0 | query1
| 2 | 0.09918300 | SELECT COUNT(*) FROM T1 | query2
| 8.0.34 | MySQL Community Server - GPL |
mysql [localhost:8034] {msandbox} (test) > SHOW PROFILES;
+----------+------------+-------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-------------------------------------+
| 1 | 0.16873475 | SELECT COUNT(*) FROM T1 WHERE c > 0 | query1
| 2 | 0.77702675 | SELECT COUNT(*) FROM T1 | query2
How to repeat:
############################################
# CREATE the table and insert 1 million records
############################################
CREATE DATABASE test;
use test;
CREATE TABLE `T1` (
`a` bigint(20) NOT NULL AUTO_INCREMENT,
`b` varchar(50) DEFAULT NULL,
`c` datetime NOT NULL,
`d` json DEFAULT NULL,
`e` json DEFAULT NULL,
`f` varchar(15) DEFAULT NULL,
`g` varchar(50) DEFAULT NULL,
`h` varchar(10) DEFAULT NULL,
PRIMARY KEY (`a`),
KEY `IDX_b` (`b`),
KEY `IX_c` (`c`)
) ENGINE=InnoDB ;
DROP PROCEDURE IF EXISTS InsertData2;
DELIMITER //
CREATE PROCEDURE InsertData2(IN N INT, IN M BIGINT)
BEGIN
DECLARE i BIGINT DEFAULT M;
WHILE i < M + N DO
INSERT INTO T1 (b,c,d,e,f,g,h) VALUES (
RPAD('a', 50, 'a'),
NOW(),
CONCAT('{"key1":"', RPAD('a', 250, 'a'), '","key2":"', RPAD('a', 250, 'a'), '"}'),
CONCAT('{"key1":"', RPAD('a', 750, 'a'), '","key2":"', RPAD('a', 750, 'a'), '"}'),
RPAD('a', 15, 'a'),
RPAD('a', 50, 'a'),
'Active'
);
SET i = i + 1;
END WHILE;
END //
DELIMITER ;
DROP PROCEDURE IF EXISTS InsertData3;
DELIMITER //
CREATE PROCEDURE InsertData3(IN N INT)
BEGIN
DECLARE i INT DEFAULT 0;
WHILE i < N DO
INSERT INTO T1(b,c,d,e,f,g,h) SELECT b,NOW(),d,e,f,g,h FROM T1 LIMIT 100000;
SELECT i, count(*) from T1;
SET i = i + 1;
END WHILE;
END //
DELIMITER ;
-- initial data insert
CALL InsertData2(9, 0);
-- for 100k records insert
CALL InsertData3(13);
INSERT INTO T1(b,c,d,e,f,g,h) SELECT b,NOW(),d,e,f,g,h FROM T1 LIMIT 26272;
-- for 900k records insert to complete 1 million record
CALL InsertData3(9);
############################################
# Test below queries on both 8.0 and 5.7
############################################
SELECT @@version, @@version_comment;
SET PROFILING = ON;
SELECT COUNT(*) FROM T1 WHERE c > 0;
SELECT COUNT(*) FROM T1;
SHOW PROFILES;
EXPLAIN SELECT COUNT(*) FROM T1 WHERE c > 0;
EXPLAIN SELECT COUNT(*) FROM T1;
SELECT database_name, table_name, index_name, SUM(stat_value) pages,
SUM(stat_value)*@@innodb_page_size/(1024*1024) size_MB
FROM mysql.innodb_index_stats
WHERE stat_name = 'size'
AND database_name = 'test'
GROUP BY database_name, table_name, index_name;
############################################
# Output 5.7
############################################
mysql [localhost:5742] {msandbox} (test) > SELECT @@version, @@version_comment;
+------------+------------------------------+
| @@version | @@version_comment |
+------------+------------------------------+
| 5.7.42-log | MySQL Community Server (GPL) |
+------------+------------------------------+
1 row in set (0.00 sec)
mysql [localhost:5742] {msandbox} (test) > SET PROFILING = ON;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql [localhost:5742] {msandbox} (test) > SELECT COUNT(*) FROM T1 WHERE c > 0;
+----------+
| COUNT(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.16 sec)
mysql [localhost:5742] {msandbox} (test) > SELECT COUNT(*) FROM T1;
+----------+
| COUNT(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.10 sec)
mysql [localhost:5742] {msandbox} (test) > SHOW PROFILES;
+----------+------------+-------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-------------------------------------+
| 1 | 0.16019925 | SELECT COUNT(*) FROM T1 WHERE c > 0 |
| 2 | 0.09918300 | SELECT COUNT(*) FROM T1 |
+----------+------------+-------------------------------------+
2 rows in set, 1 warning (0.00 sec)
mysql [localhost:5742] {msandbox} (test) > EXPLAIN SELECT COUNT(*) FROM T1 WHERE c > 0;
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+--------------------------+
| 1 | SIMPLE | T1 | NULL | range | IX_c | IX_c | 5 | NULL | 416935 | 100.00 | Using where; Using index |
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)
mysql [localhost:5742] {msandbox} (test) > EXPLAIN SELECT COUNT(*) FROM T1;
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | T1 | NULL | index | NULL | IX_c | 5 | NULL | 833870 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
mysql [localhost:5742] {msandbox} (test) > SELECT database_name, table_name, index_name, SUM(stat_value) pages,
-> SUM(stat_value)*@@innodb_page_size/(1024*1024) size_MB
-> FROM mysql.innodb_index_stats
-> WHERE stat_name = 'size'
-> AND database_name = 'test'
-> GROUP BY database_name, table_name, index_name;
+---------------+------------+------------+--------+-----------+
| database_name | table_name | index_name | pages | size_MB |
+---------------+------------+------------+--------+-----------+
| test | T1 | IDX_b | 4083 | 63.7969 |
| test | T1 | IX_c | 1188 | 18.5625 |
| test | T1 | PRIMARY | 166144 | 2596.0000 |
+---------------+------------+------------+--------+-----------+
3 rows in set (0.00 sec)
############################################
# Output 8.0
############################################
mysql [localhost:8034] {msandbox} (test) > SELECT @@version, @@version_comment;
+-----------+------------------------------+
| @@version | @@version_comment |
+-----------+------------------------------+
| 8.0.34 | MySQL Community Server - GPL |
+-----------+------------------------------+
1 row in set (0.00 sec)
mysql [localhost:8034] {msandbox} (test) > SET PROFILING = ON;
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql [localhost:8034] {msandbox} (test) > SELECT COUNT(*) FROM T1 WHERE c > 0;
+----------+
| COUNT(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.17 sec)
mysql [localhost:8034] {msandbox} (test) > SELECT COUNT(*) FROM T1;
+----------+
| COUNT(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.78 sec)
mysql [localhost:8034] {msandbox} (test) > SHOW PROFILES;
+----------+------------+-------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+-------------------------------------+
| 1 | 0.16873475 | SELECT COUNT(*) FROM T1 WHERE c > 0 |
| 2 | 0.77702675 | SELECT COUNT(*) FROM T1 |
+----------+------------+-------------------------------------+
2 rows in set, 1 warning (0.00 sec)
mysql [localhost:8034] {msandbox} (test) > EXPLAIN SELECT COUNT(*) FROM T1 WHERE c > 0;
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+--------------------------+
| 1 | SIMPLE | T1 | NULL | range | IX_c | IX_c | 5 | NULL | 417036 | 100.00 | Using where; Using index |
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+--------------------------+
1 row in set, 1 warning (0.00 sec)
mysql [localhost:8034] {msandbox} (test) > EXPLAIN SELECT COUNT(*) FROM T1;
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+-------------+
| 1 | SIMPLE | T1 | NULL | index | NULL | IX_c | 5 | NULL | 834073 | 100.00 | Using index |
+----+-------------+-------+------------+-------+---------------+------+---------+------+--------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
mysql [localhost:8034] {msandbox} (test) > SELECT database_name, table_name, index_name, SUM(stat_value) pages,
-> SUM(stat_value)*@@innodb_page_size/(1024*1024) size_MB
-> FROM mysql.innodb_index_stats
-> WHERE stat_name = 'size'
-> AND database_name = 'test'
-> GROUP BY database_name, table_name, index_name;
+---------------+------------+------------+--------+-----------+
| database_name | table_name | index_name | pages | size_MB |
+---------------+------------+------------+--------+-----------+
| test | T1 | IDX_b | 4083 | 63.7969 |
| test | T1 | IX_c | 1188 | 18.5625 |
| test | T1 | PRIMARY | 166272 | 2598.0000 |
+---------------+------------+------------+--------+-----------+
3 rows in set (0.00 sec)
Suggested fix:
Please have query optimizer performance for the "SELECT COUNT(*) FROM <TABLE_NAME>" on 8.0 same or better with 5.7 like for query "SELECT COUNT(*) FROM <TABLE_NAME> WHERE <COLUMN_NAME> > 0" which did not degrade.