Skip to content

Commit 95cb470

Browse files
author
Steinar H. Gunderson
committed
Bug #33037007: PRELIMINARY FIXES FOR WL #14488 [TRP planning, noclose]
Move planning (in QEP_TABs) from using QUICK_SELECT_I objects to TRPs, ie., test_quick_select() with return a TRP (instead of a quick) and the iterator won't be created until the plan is actually decided upon (or not at all, if the query is an EXPLAIN query). This cements TRPs as planning objects and quicks as pure execution objects; a necessary step in converting the former to AccessPath and the latter to RowIterator. It naturally moves all planning members (e.g. cost and row estimates) away from QUICK_SELECT_I, along with all protected data members. Various tracing and querying member functions are also taken out (some are replaced with free functions). There is no longer a need for quicks to be able to reverse themselves; that's a simple member switch in TRP_RANGE (but the rather ugly moving and subclassing of QUICK_RANGE_SELECT_DESC remains for now). Several member fields that needed to be shared between QUICK_SELECT_I can be moved down into the classes that actually need them. This is especially beneficial for those that only make sense for a subset (such as index, which had no interpretation for e.g. index merge). Change-Id: I8896b5725f6d9c10b9c6c6384cf7a4375586fc96
1 parent 139b8d6 commit 95cb470

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1204
-1200
lines changed

Diff for: sql/abstract_query_plan.cc

+17-16
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "sql/item.h"
3535
#include "sql/key.h"
3636
#include "sql/range_optimizer/range_optimizer.h" // QUICK_SELECT_I
37+
#include "sql/range_optimizer/table_read_plan.h"
3738
#include "sql/sql_const.h"
3839
#include "sql/sql_executor.h" // QEP_TAB
3940
#include "sql/sql_opt_exec_shared.h"
@@ -52,7 +53,7 @@ Join_plan::Join_plan(const JOIN *join)
5253
be written to handle it.
5354
*/
5455
assert(!m_qep_tabs[0].dynamic_range() || (m_qep_tabs[0].type() == JT_ALL) ||
55-
(m_qep_tabs[0].quick() == nullptr));
56+
(m_qep_tabs[0].trp() == nullptr));
5657

5758
// Discard trailing allocated, but unused, tables.
5859
while (m_qep_tabs[m_access_count - 1].position() == nullptr) {
@@ -162,10 +163,10 @@ void Table_access::dbug_print() const {
162163

163164
DBUG_PRINT("info", ("dynamic_range:%d", (int)get_qep_tab()->dynamic_range()));
164165
DBUG_PRINT("info", ("index:%d", get_qep_tab()->index()));
165-
DBUG_PRINT("info", ("quick:%p", get_qep_tab()->quick()));
166-
if (get_qep_tab()->quick()) {
166+
DBUG_PRINT("info", ("trp:%p", get_qep_tab()->trp()));
167+
if (get_qep_tab()->trp()) {
167168
DBUG_PRINT("info",
168-
("quick->get_type():%d", get_qep_tab()->quick()->get_type()));
169+
("trp->get_type():%d", get_qep_tab()->trp()->get_type()));
169170
}
170171
}
171172

@@ -253,8 +254,8 @@ void Table_access::compute_type_and_index() const {
253254
m_access_type = AT_UNDECIDED;
254255
m_index_no = -1;
255256
} else {
256-
if (qep_tab->quick() != nullptr) {
257-
QUICK_SELECT_I *quick = qep_tab->quick();
257+
if (qep_tab->trp() != nullptr) {
258+
TABLE_READ_PLAN *trp = qep_tab->trp();
258259

259260
/** QUICK_SELECT results in execution of MRR (Multi Range Read).
260261
* Depending on each range, it may require execution of
@@ -266,33 +267,33 @@ void Table_access::compute_type_and_index() const {
266267
**/
267268

268269
const KEY *key_info = qep_tab->table()->s->key_info;
269-
DBUG_EXECUTE("info", quick->dbug_dump(0, true););
270+
DBUG_EXECUTE("info", trp->dbug_dump(0, true););
270271

271272
// Temporary assert as we are still investigation the relation between
272-
// 'quick->index == MAX_KEY' and the different quick_types
273-
assert((quick->index == MAX_KEY) ==
274-
(quick->get_type() == QS_TYPE_INDEX_MERGE ||
275-
quick->get_type() == QS_TYPE_ROR_INTERSECT ||
276-
quick->get_type() == QS_TYPE_ROR_UNION));
273+
// 'trp->index == MAX_KEY' and the different quick_types
274+
assert((trp->index == MAX_KEY) ==
275+
(trp->get_type() == QS_TYPE_INDEX_MERGE ||
276+
trp->get_type() == QS_TYPE_ROR_INTERSECT ||
277+
trp->get_type() == QS_TYPE_ROR_UNION));
277278

278279
// JT_INDEX_MERGE: We have a set of qualifying PKs as root of pushed
279280
// joins
280-
if (quick->index == MAX_KEY) {
281+
if (trp->index == MAX_KEY) {
281282
m_index_no = qep_tab->table()->s->primary_key;
282283
m_access_type =
283284
AT_MULTI_PRIMARY_KEY; // Multiple PKs are produced by merge
284285
}
285286

286287
// Else JT_RANGE: May be both exact PK and/or index scans when sorted
287288
// index available
288-
else if (quick->index == qep_tab->table()->s->primary_key) {
289-
m_index_no = quick->index;
289+
else if (trp->index == qep_tab->table()->s->primary_key) {
290+
m_index_no = trp->index;
290291
if (key_info[m_index_no].algorithm == HA_KEY_ALG_HASH)
291292
m_access_type = AT_MULTI_PRIMARY_KEY; // MRR w/ multiple PK's
292293
else
293294
m_access_type = AT_MULTI_MIXED; // MRR w/ both range and PKs
294295
} else {
295-
m_index_no = quick->index;
296+
m_index_no = trp->index;
296297
if (key_info[m_index_no].algorithm == HA_KEY_ALG_HASH)
297298
m_access_type =
298299
AT_MULTI_UNIQUE_KEY; // MRR with multiple unique keys

Diff for: sql/basic_row_iterators.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,17 @@ class IndexRangeScanIterator final : public TableRowIterator {
129129
//
130130
// "examined_rows", if not nullptr, is incremented for each successful Read().
131131
IndexRangeScanIterator(THD *thd, TABLE *table, QUICK_SELECT_I *quick,
132+
bool is_loose_index_scan, bool is_ror,
132133
double expected_rows, ha_rows *examined_rows);
134+
~IndexRangeScanIterator() override;
133135

134136
bool Init() override;
135137
int Read() override;
136138

137139
private:
138-
// NOTE: No destructor; quick_range will call ha_index_or_rnd_end() for us.
139140
QUICK_SELECT_I *const m_quick;
141+
const bool m_is_loose_index_scan;
142+
const bool m_is_ror;
140143
const double m_expected_rows;
141144
ha_rows *const m_examined_rows;
142145

Diff for: sql/join_optimizer/access_path.cc

+13-1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
#include "sql/join_optimizer/estimate_selectivity.h"
3434
#include "sql/join_optimizer/relational_expression.h"
3535
#include "sql/join_optimizer/walk_access_paths.h"
36+
#include "sql/range_optimizer/range_optimizer.h"
37+
#include "sql/range_optimizer/table_read_plan.h"
3638
#include "sql/ref_row_iterators.h"
3739
#include "sql/sorting_iterator.h"
3840
#include "sql/sql_optimizer.h"
@@ -303,8 +305,18 @@ unique_ptr_destroy_only<RowIterator> CreateIteratorFromAccessPath(
303305
}
304306
case AccessPath::INDEX_RANGE_SCAN: {
305307
const auto &param = path->index_range_scan();
308+
QUICK_SELECT_I *quick = param.trp->make_quick(true, thd->mem_root);
309+
if (quick == nullptr || quick->init()) {
310+
return nullptr;
311+
}
312+
const int type = param.trp->get_type();
313+
bool is_loose_index_scan =
314+
(type == QS_TYPE_SKIP_SCAN || type == QS_TYPE_GROUP_MIN_MAX);
315+
bool is_ror =
316+
(type == QS_TYPE_ROR_INTERSECT || type == QS_TYPE_ROR_UNION);
306317
iterator = NewIterator<IndexRangeScanIterator>(
307-
thd, param.table, param.quick, path->num_output_rows, examined_rows);
318+
thd, param.table, quick, is_loose_index_scan, is_ror,
319+
path->num_output_rows, examined_rows);
308320
break;
309321
}
310322
case AccessPath::DYNAMIC_INDEX_RANGE_SCAN: {

Diff for: sql/join_optimizer/access_path.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ class JOIN;
4747
class KEY;
4848
class RowIterator;
4949
class QEP_TAB;
50-
class QUICK_SELECT_I;
5150
class SJ_TMP_TABLE;
51+
class TABLE_READ_PLAN;
5252
class Table_function;
5353
class Temp_table_param;
5454
class Window;
@@ -757,7 +757,7 @@ struct AccessPath {
757757
} follow_tail;
758758
struct {
759759
TABLE *table;
760-
QUICK_SELECT_I *quick;
760+
TABLE_READ_PLAN *trp;
761761
} index_range_scan;
762762
struct {
763763
TABLE *table;
@@ -1094,13 +1094,13 @@ inline AccessPath *NewFollowTailAccessPath(THD *thd, TABLE *table,
10941094
}
10951095

10961096
inline AccessPath *NewIndexRangeScanAccessPath(THD *thd, TABLE *table,
1097-
QUICK_SELECT_I *quick,
1097+
TABLE_READ_PLAN *trp,
10981098
bool count_examined_rows) {
10991099
AccessPath *path = new (thd->mem_root) AccessPath;
11001100
path->type = AccessPath::INDEX_RANGE_SCAN;
11011101
path->count_examined_rows = count_examined_rows;
11021102
path->index_range_scan().table = table;
1103-
path->index_range_scan().quick = quick;
1103+
path->index_range_scan().trp = trp;
11041104
return path;
11051105
}
11061106

Diff for: sql/join_optimizer/explain_access_path.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "sql/hash_join_iterator.h"
3030
#include "sql/item_sum.h"
3131
#include "sql/join_optimizer/relational_expression.h"
32-
#include "sql/range_optimizer/range_optimizer.h"
32+
#include "sql/range_optimizer/table_read_plan.h"
3333
#include "sql/ref_row_iterators.h"
3434
#include "sql/sorting_iterator.h"
3535
#include "sql/sql_optimizer.h"
@@ -469,7 +469,7 @@ ExplainData ExplainAccessPath(const AccessPath *path, JOIN *join) {
469469
// TODO(sgunders): Convert QUICK_SELECT_I to RowIterator so that we can
470470
// get better outputs here (similar to dbug_dump()).
471471
String str;
472-
path->index_range_scan().quick->add_info_string(&str);
472+
path->index_range_scan().trp->add_info_string(&str);
473473
string ret = string(table->key_read ? "Covering index range scan on "
474474
: "Index range scan on ") +
475475
table->alias + " using " + to_string(str);

0 commit comments

Comments
 (0)