Bug #80390 | Clustered primary key included in index merge may cause higher execution times | ||
---|---|---|---|
Submitted: | 16 Feb 2016 10:14 | Modified: | 16 Feb 2016 10:59 |
Reporter: | Olav Sandstå | Email Updates: | |
Status: | Verified | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S5 (Performance) |
Version: | 5.6.30 | OS: | Any |
Assigned to: | CPU Architecture: | Any |
[16 Feb 2016 10:14]
Olav Sandstå
[16 Feb 2016 12:09]
Olav Sandstå
The number of handler read calls for the query: SELECT * FROM t1 WHERE pk > 90000 AND i1 = 100; mysql> show status like 'handler_read%'; +-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | Handler_read_first | 0 | | Handler_read_key | 911 | | Handler_read_last | 0 | | Handler_read_next | 910 | | Handler_read_prev | 0 | | Handler_read_rnd | 910 | | Handler_read_rnd_next | 0 | +-----------------------+-------+ If I force the secondary index to be used, the number of handler read calls is reduced: SELECT * FROM t1 FORCE INDEX(idx) WHERE pk > 90000 AND i1 = 100; mysql> show status like 'handler_read%'; +-----------------------+-------+ | Variable_name | Value | +-----------------------+-------+ | Handler_read_first | 0 | | Handler_read_key | 1 | | Handler_read_last | 0 | | Handler_read_next | 910 | | Handler_read_prev | 0 | | Handler_read_rnd | 0 | | Handler_read_rnd_next | 0 | +-----------------------+-------+ 7 rows in set (0.00 sec)
[16 Feb 2016 13:26]
Olav Sandstå
Analysis: ========= The query can be run as range scan on each of the two indexes: -primary index: the range criteria "pk > 90000" will be used -secondary index: the range criteria "i1 = 100 AND pk > 90000" will be used. The reason "pk > 90000" can be included when using the secondary index is that the InnoDB appends all primary key columns to each secondary index. When the optimizer checks for whether index merge can be used, it includes first the secondary indexes which returns the records in primary key order (row order). It then adds the clustered primary key to the index merge if this results in a lower total cost. In the current calculations for the number of rows returned by an index merge, we assume that the number of selected records is reduced when intersecting with an additional index. So in this case, adding the primary key to the index merge, the resulting estimate for number of records and cost is reduced. This causes index merge to be selected over the range scan on the secondary index. But since the primary index columns are included in the secondary index AND the range optimizer is able to utilize the added columns, there is no improvement to add the clustered primary index to the index merge. Suggestion: =========== Do not add the clustered primary index to an index merge when the primary index columns are included in one of the secondary indexes in the index merge AND these columns are used in the secondary index.
[4 Oct 2022 15:08]
Morgan Tocker
Testcase verified against 8.0.30
Attachment: index_merge_broken.sql (application/octet-stream, text), 103.77 KiB.
[4 Oct 2022 15:10]
Morgan Tocker
I have been affected by this issue quite a bit. I've uploaded a test-case which produces the following output: $ mysql test < ~/Desktop/index_merge_broken.sql Table Op Msg_type Msg_text test.t2 analyze status OK id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 NULL index_merge PRIMARY,id2_t id2_t,PRIMARY 420,8 NULL 1 100.00 Using intersect(id2_t,PRIMARY); Using where; Using filesort id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 NULL range id2_t id2_t 420 NULL 1 100.00 Using index condition id select_type table partitions type possible_keys key key_len ref rows filtered Extra 1 SIMPLE t2 NULL range PRIMARY,id2_t id2_t 420 NULL 1 100.00 Using index condition