Speeding up SELECT COUNT, which became slow in MySQL 8.0.
This is Yuta Kikai (@fat47) from the Service Reliability Group (SRG) of the Media Division.
#SRGThe Service Reliability Group primarily provides comprehensive support for the infrastructure surrounding our media services, focusing on improving existing services, launching new ones, and contributing to open-source software (OSS).
This article summarizes how to speed up the SELECT COUNT operation in MySQL 8.0 without upgrading the version.
I hope this is of some help.
MySQL8.0 SELECT COUNT slowdown problemThe root cause of the slowdown in SELECT COUNTBug number: 100597Bug number: 112767Verification of speed improvementsVerification table (1 million records)COUNT results in MySQL 5.7COUNT results in MySQL 8.0Adding the condition `id > 0` to the WHERE clause of the COUNT query in MySQL 8.0.In MySQL 8.0, add the condition `id > 0` to the WHERE clause of the COUNT statement and specify "idx" in the FORCE INDEX.[Solution] Specify the appropriate index using the appropriate WHERE clause condition + FORCE INDEX for COUNT in MySQL 8.0In conclusion
MySQL8.0 SELECT COUNT slowdown problem
In MySQL 8.0, SELECT COUNT can be extremely slow.
In some cases, it can be tens of times slower than MySQL 5.7.
SELECT COUNT results in MySQL 5.7.41
SELECT COUNT results in MySQL 8.0.28
This issue has been resolved in MySQL 8.0.37 and later versions (including MySQL 8.4 and MySQL 9.0).
However, there are many environments, such as those using Aurora MySQL Version 3, where upgrading to the latest MySQL version is not yet possible.
The root cause of the slowdown in SELECT COUNT
Let's take another look at the MySQL 8.0.37 release notes.
InnoDB:MySQL no longer ignores the optimizer hint to use a secondary index scan, which instead forced a clustered (parallel) index scan. In addition, added the ability to provide an index hint that forces use of a clustered index. (Bug #100597, Bug #112767, Bug #31791868, Bug #35952353)
InnoDB: MySQL no longer ignores the optimizer hint to use secondary index scans. This previously forced clustered (parallel) index scans instead. (Bugs #100597, #112767, #31791868, #35952353)
Bug number: 100597
This is in SELECT COUNT,Even with a hint clause, the clustered index (the index of the primary key) is used instead of the secondary index.That was the bug.
The EXPLAIN results make it appear as though the secondary index is being used, but in reality, it is not.Used only when a WHERE clause is added.That was the report.
Bug number: 112767
The ability to preload pages for parallel reading threadsIn clustered indexes, loading more pages than necessary causes excessive read I/O, degrading the performance of SELECT COUNT.It was found that this is happening.
If you prevent parallel scanning of clustered indexes (PK indexes) using SELECT COUNT,SELECT COUNT slowdown can be avoidedIt seems safe to say that this is the case.
- Specifying a secondary index is required using a hint clause (such as USE INDEX or FORCE INDEX).
- The condition in the WHERE clause is mandatory.
Verification of speed improvements
Verification table (1 million records)
COUNT results in MySQL 5.7
0.37秒COUNT results in MySQL 8.0
7.65秒idxLet's check the index statistics and buffer pool usage.
PRIMARYThe above query checks the contents of mysql.innodb_index_stats and information_schema.innodb_buffer_page.
- mysql.innodb_index_stats
- InnnoDB Index Statistics
- information_schema.innodb_buffer_page
- Buffer pool page information
By aggregating the number of pages in the buffer pool for each index of the specified table, we can verify whether the index is actually being used and whether data is present in the buffer pool.
PRIMARYAdding the condition `id > 0` to the WHERE clause of the COUNT query in MySQL 8.0.
When I added a WHERE clause condition and ran the code, it became slightly faster.
PRIMARYOf course, there are no changes to the index statistics or buffer pool.
In MySQL 8.0, add the condition `id > 0` to the WHERE clause of the COUNT statement and specify "idx" in the FORCE INDEX.
Adding FORCE INDEX reduced the time to 0.85 seconds.
Using Index for skip scanLet's check the index statistics and buffer pool usage.
idxcol_idxカラムLet's try to improve this part further.
[Solution] Specify the appropriate index using the appropriate WHERE clause condition + FORCE INDEX for COUNT in MySQL 8.0
In this sample table example, the following two patterns are possible:
0.44秒
0.54秒
In conclusion
The SELECT COUNT, which was delayed,There's a chance we can save them somehow.It turns out that there is.
The problem could be solved by upgrading MySQL 8.0 to the latest version,
Many people may not be able to use the latest MySQL 8.0 for various reasons, including those related to Aurora MySQL.
