[MDEV-10345] Delete query performance degradation when using a composite primary key Created: 2016-07-07 Updated: 2023-08-17 |
|
| Status: | Open |
| Project: | MariaDB Server |
| Component/s: | Optimizer |
| Affects Version/s: | 10.1.14 |
| Fix Version/s: | 10.1 |
| Type: | Bug | Priority: | Major |
| Reporter: | Jizo Zef | Assignee: | Sergei Petrunia |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Environment: |
CentOS 7 |
||
| Description |
|
We have an old MySQL 5.0 database running on CentOS 5 server which we want to move to CentOS 7 and MariaDB 10.1. We have successfully installed and configured the new system to currently run as a slave of the old server (we will make it master once we are sure everything is working smoothly) but there were some problems. We have a table like this one with ~70,000,000 records:
We purge the old data from the table daily using this query:
We are not interested in `object_id` but we include it in the query so that the engine uses the primary key. Our old server executes the query in 81 seconds which is perfectly acceptable, the new shiny one does it in 5314 seconds. What can be the problem? There was another issue. New data is being inserted into the old server at 100 records per second and it works just fine, but the new server was replicating at ~20 records a second maximum. We tried to tune the flush methods and slave parallelism settings to no success (see the commented out settings), we somewhat solved the issue by changing innodb_flush_log_at_trx_commit = 1 to innodb_flush_log_at_trx_commit = 2, but I'm not sure it was the right thing to do. Settings:
|
| Comments |
| Comment by Elena Stepanova [ 2016-07-07 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
For DELETE problem, please run EXPLAIN DELETE ... on the slow slave, and paste the output. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jizo Zef [ 2016-07-08 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Here is the result of the EXPLAIN DELETE...
There are ~70,000,000 records (edit: as it turns out it's ~80,000,000) in the table evenly distributed by the indexed `d` date field for one whole year (and `object_id` is always bigger than 0), I don't know why the rows field of the explain query is so big (39603342). When I remove the bogus `object_id` > 0 condition I get this (as expected, the index is not being used):
As for doing the inserts in one transaction unfortunately I can't do that because the inserts are being made by different threads of one daemon process (which has 10 connections pool) where every thread inserts data coming from a remote RTU (there are thousands of RTUs which send data at different frequency from every 5 seconds to every 5 minutes, which in average results ~100 inserts per second). Thank you for your interest. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2016-07-08 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
For the DELETE problem, did you try to run ANALYZE on the table? | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jizo Zef [ 2016-07-09 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
No, but the table is created a couple of days ago from a mysqldump dump file, so it shouldn't be fragmented. Anyway, if you think it may help I can try it. Can you please try to create the table and insert there i.e. 10,000 values then try the EXPLAIN query on the DELETE query and see if the "rows" is ~5000? In my case, for some reason the rows value is the half of the number of the records in the table. Is this normal considering that we are using the primary key's index? Here are the queries and a PHP script for your testing.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2016-07-09 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Yes, I do see ~5000 in the rows field. However, I doubt it's related to the performance degradation, since apparently it is so on all available versions of MariaDB and MySQL, including MySQL 5.0 – well, there is no EXPLAIN for DELETE in old versions, but it's all the same for SELECT:
Normally, I wouldn't put much trust into InnoDB-related estimates, but I'll assign it to psergey to see if there is anything to improve here, and to look at the reported degradation in general. Below is a plain SQL version of the alleged '5000 rows' problem above, for the convenience. It is also suitable for MTR if you replace delimiter with --delimiter.
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jizo Zef [ 2016-07-11 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Thank you! P.S. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jizo Zef [ 2016-07-11 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I'd like to add the slow query logs related to the issue from both the MySQL 5.0.95 and MariaDB 10.1: MySQL 5.0.95
MariaDB 10.1
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Jizo Zef [ 2016-08-11 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Are there any news about this issue? | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ryan Blackledge [ 2023-08-17 ] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
We're seeing this optimizer performance regression coming from mysql 5.7 in mariadb 10.6 as well.
Update:
Explain Mysql:
Explain Mariadb:
As you can see, this delete used to use the index (and a select with the same syntax will still use the metric_data_container_api_name index). Now the delete requires a full table scan. We're able to work around it by fooling the optimizer using subqueries, but it's not ideal.
|