mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-9750: Quick memory exhaustion with 'extended_keys=on' ...
(Variant #5, full patch, for 10.5) Do not produce SEL_ARG graphs that would yield huge numbers of ranges. Introduce a concept of SEL_ARG graph's "weight". If we are about to produce a graph whose "weight" exceeds the limit, remove the parts of SEL_ARG graph that represent the biggest key parts. Do so until the graph's is within the limit. Includes - debug code to verify SEL_ARG graph weight - A user-visible @@optimizer_max_sel_arg_weight to control the optimization - Logging the optimization into the optimizer trace.
This commit is contained in:
@ -223,6 +223,50 @@ class RANGE_OPT_PARAM;
|
||||
|
||||
We avoid consuming too much memory by setting a limit on the number of
|
||||
SEL_ARG object we can construct during one range analysis invocation.
|
||||
|
||||
5. SEL_ARG GRAPH WEIGHT
|
||||
|
||||
A SEL_ARG graph has a property we call weight, and we define it as follows:
|
||||
|
||||
<definition>
|
||||
If the SEL_ARG graph does not have any node with multiple incoming
|
||||
next_key_part edges, then its weight is the number of SEL_ARG objects used.
|
||||
|
||||
If there is a node with multiple incoming next_key_part edges, clone that
|
||||
node, (and the nodes connected to it via prev/next links) and redirect one
|
||||
of the incoming next_key_part edges to the clone.
|
||||
|
||||
Continue with cloning until we get a graph that has no nodes with multiple
|
||||
incoming next_key_part edges. Then, the number of SEL_ARG objects in the
|
||||
graph is the weight of the original graph.
|
||||
</definition>
|
||||
|
||||
Example:
|
||||
|
||||
kp1 $ kp2 $ kp3
|
||||
$ $
|
||||
| +-------+ $ $
|
||||
\->| kp1=2 |--$--------------$-+
|
||||
+-------+ $ $ | +--------+
|
||||
| $ $ ==>| kp3=11 |
|
||||
+-------+ $ $ | +--------+
|
||||
| kp1>3 |--$--------------$-+ |
|
||||
+-------+ $ $ +--------+
|
||||
$ $ | kp3=14 |
|
||||
$ $ +--------+
|
||||
$ $ |
|
||||
$ $ +--------+
|
||||
$ $ | kp3=14 |
|
||||
$ $ +--------+
|
||||
|
||||
Here, the weight is 2 + 2*3=8.
|
||||
|
||||
The rationale behind using this definition of weight is:
|
||||
- it has the same order-of-magnitude as the number of ranges that the
|
||||
SEL_ARG graph is describing,
|
||||
- it is a lot easier to compute than computing the number of ranges,
|
||||
- it can be updated incrementally when performing AND/OR operations on
|
||||
parts of the graph.
|
||||
*/
|
||||
|
||||
class SEL_ARG :public Sql_alloc
|
||||
@ -236,6 +280,9 @@ public:
|
||||
/*
|
||||
The ordinal number the least significant component encountered in
|
||||
the ranges of the SEL_ARG tree (the first component has number 1)
|
||||
|
||||
Note: this number is currently not precise, it is an upper bound.
|
||||
@seealso SEL_ARG::get_max_key_part()
|
||||
*/
|
||||
uint16 max_part_no;
|
||||
/*
|
||||
@ -263,6 +310,17 @@ public:
|
||||
enum leaf_color { BLACK,RED } color;
|
||||
enum Type { IMPOSSIBLE, MAYBE, MAYBE_KEY, KEY_RANGE } type;
|
||||
|
||||
/*
|
||||
For R-B root nodes only: the graph weight, as defined above in the
|
||||
SEL_ARG GRAPH WEIGHT section.
|
||||
*/
|
||||
uint weight;
|
||||
enum { MAX_WEIGHT = 32000 };
|
||||
#ifndef DBUG_OFF
|
||||
uint verify_weight();
|
||||
#endif
|
||||
|
||||
/* See RANGE_OPT_PARAM::alloced_sel_args */
|
||||
enum { MAX_SEL_ARGS = 16000 };
|
||||
|
||||
SEL_ARG() {}
|
||||
@ -273,7 +331,7 @@ public:
|
||||
SEL_ARG(enum Type type_arg)
|
||||
:min_flag(0), max_part_no(0) /* first key part means 1. 0 mean 'no parts'*/,
|
||||
elements(1),use_count(1),left(0),right(0),
|
||||
next_key_part(0), color(BLACK), type(type_arg)
|
||||
next_key_part(0), color(BLACK), type(type_arg), weight(1)
|
||||
{}
|
||||
/**
|
||||
returns true if a range predicate is equal. Use all_same()
|
||||
@ -287,6 +345,9 @@ public:
|
||||
return true;
|
||||
return cmp_min_to_min(arg) == 0 && cmp_max_to_max(arg) == 0;
|
||||
}
|
||||
|
||||
uint get_max_key_part() const;
|
||||
|
||||
/**
|
||||
returns true if all the predicates in the keypart tree are equal
|
||||
*/
|
||||
|
Reference in New Issue
Block a user