summaryrefslogtreecommitdiff
path: root/sql/opt_range.cc
diff options
context:
space:
mode:
authorIgor Babaev <igor@askmonty.org>2020-11-09 13:51:32 -0800
committerIgor Babaev <igor@askmonty.org>2020-11-09 13:51:32 -0800
commitbea84aefb0563a10a310ea81d46c372919345c10 (patch)
tree5e2c417d10a186f5fb254fb54ff198d19c605320 /sql/opt_range.cc
parent1404f3bea796c8479cf401cb36d518658600ddca (diff)
downloadmariadb-git-bea84aefb0563a10a310ea81d46c372919345c10.tar.gz
MDEV-23811: With large number of indexes optimizer chooses an inefficient planmariadb-10.2.36
This bug could manifest itself for a query with WHERE condition containing top level OR formula such that each conjunct contained a single-range condition supported by the same index. One of these range conditions must be fully covered by another range condition that is used later in the OR formula. Additionally at least one of these condition should be ANDed with a sargable range condition supported by a different index. There were several attempts to fix related problems for OR conditions after the backport of range optimizer code from MySQL (commit 0e19f3e36f7842583feb6bead2c2600cd620bced). Unfortunately the first of these fixes contained typo remained unnoticed until recently. This typo bug led to rejection of valid range accesses. This patch fixed this typo bug. The fix revealed another two bugs: one in a constructor for SEL_ARG, the other in the function tree_or(). Both are fixed in this patch.
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r--sql/opt_range.cc10
1 files changed, 7 insertions, 3 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index e933d2af355..798b1f284bc 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1852,6 +1852,9 @@ SEL_ARG::SEL_ARG(SEL_ARG &arg) :Sql_alloc()
next_key_part=arg.next_key_part;
max_part_no= arg.max_part_no;
use_count=1; elements=1;
+ next= 0;
+ if (next_key_part)
+ ++next_key_part->use_count;
}
@@ -9597,10 +9600,11 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2)
if (!tmp->next_key_part)
{
- if (key2->use_count)
+ SEL_ARG *key2_next= key2->next;
+ if (key2_shared)
{
SEL_ARG *key2_cpy= new SEL_ARG(*key2);
- if (key2_cpy)
+ if (!key2_cpy)
return 0;
key2= key2_cpy;
}
@@ -9621,7 +9625,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2)
Move on to next range in key2
*/
key2->increment_use_count(-1); // Free not used tree
- key2=key2->next;
+ key2=key2_next;
continue;
}
else