| Bug #117791 | FORCE INDEX does not skip records_in_range() for 'x IS NULL' | ||
|---|---|---|---|
| Submitted: | 25 Mar 2025 13:30 | Modified: | 23 Mar 1:58 |
| Reporter: | Kaiwang CHen (OCA) | Email Updates: | |
| Status: | Open | Impact on me: | |
| Category: | MySQL Server: Optimizer | Severity: | S3 (Non-critical) |
| Version: | 8.0, 8.4, 9.2 | OS: | Any |
| Assigned to: | CPU Architecture: | Any | |
| Tags: | Contribution | ||
[25 Mar 2025 13:30]
Kaiwang CHen
[25 Mar 2025 13:33]
Kaiwang CHen
Add more checks in the range iterator so that SKIP_RECORDS_IN_RANGE itself precisely decides the alternative estimation. (*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.
Contribution: bug_117791.patch (application/octet-stream, text), 5.62 KiB.
[25 Mar 2025 13:46]
Kaiwang CHen
The second path adds null test for index statistics inside the alternative estimation branch, which makes force index nicer. (*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.
Contribution: bug_117791_2.patch (application/octet-stream, text), 616 bytes.
[25 Mar 2025 13:47]
MySQL Verification Team
Hello Kaiwang, Thank you for the report and contribution. regards, Umesh
[16 Mar 8:19]
Øystein Grøvlen
Hi Kaiwang, Thank you for the contribution. We would like to apply your contribution. However, it seems there is an issue with other storage engines than InnoDB. Tests like perfschema.table_component and main.myisam hits an assert in handler::multi_range_read_info_const(). This needs to be resolved before we can take the contribution.
[23 Mar 1:58]
Kaiwang CHen
Here is a quick fix to illustrate the problem. It is the precheck in the range iterator does not match the test in the estimator here, so unavailable statistics (HA_POS_ERROR) in reported storage engines leads to the assert.
diff --git a/sql/handler.cc b/sql/handler.cc
index f6972876732..a6459404a1a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -6416,7 +6416,8 @@ ha_rows handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
else if (range.range_flag & SKIP_RECORDS_IN_RANGE) { // 2)
if ((range.range_flag & EQ_RANGE) &&
!(range.range_flag & NULL_RANGE) &&
- (keyparts_used = std::popcount(range.start_key.keypart_map))) {
+ (keyparts_used = std::popcount(range.start_key.keypart_map)) &&
+ table->key_info[keyno].has_records_per_key(keyparts_used - 1)) {
rows = static_cast<ha_rows>(
table->key_info[keyno].records_per_key(keyparts_used - 1));
} else {
However, I prefer to using a common function to avoid the problem. See the next comment.
[23 Mar 1:58]
Kaiwang CHen
Here is a quick fix to illustrate the problem. It is the precheck in the range iterator does not match the test in the estimator here, so unavailable statistics (HA_POS_ERROR) in reported storage engines leads to the assert.
diff --git a/sql/handler.cc b/sql/handler.cc
index f6972876732..a6459404a1a 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -6416,7 +6416,8 @@ ha_rows handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
else if (range.range_flag & SKIP_RECORDS_IN_RANGE) { // 2)
if ((range.range_flag & EQ_RANGE) &&
!(range.range_flag & NULL_RANGE) &&
- (keyparts_used = std::popcount(range.start_key.keypart_map))) {
+ (keyparts_used = std::popcount(range.start_key.keypart_map)) &&
+ table->key_info[keyno].has_records_per_key(keyparts_used - 1)) {
rows = static_cast<ha_rows>(
table->key_info[keyno].records_per_key(keyparts_used - 1));
} else {
However, I prefer to using a common function to avoid the problem. See the next comment.
[23 Mar 2:00]
Kaiwang CHen
Enclosed is the full patch with a common function and the assert solved. (*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.
Contribution: bug_117791_cc.patch (application/octet-stream, text), 8.14 KiB.
[23 Mar 2:03]
Kaiwang CHen
Enclosed is a fix for the assert only, using a common function can_use_index_statistics. (*) I confirm the code being submitted is offered under the terms of the OCA, and that I am authorized to contribute it.
Contribution: bug_117791_assert.patch (application/octet-stream, text), 5.89 KiB.
