1237.13.5
by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files. |
1 |
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
|
2 |
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
|
|
3 |
*
|
|
4 |
* Copyright (C) 2008-2009 Sun Microsystems
|
|
5 |
*
|
|
6 |
* This program is free software; you can redistribute it and/or modify
|
|
7 |
* it under the terms of the GNU General Public License as published by
|
|
8 |
* the Free Software Foundation; version 2 of the License.
|
|
9 |
*
|
|
10 |
* This program is distributed in the hope that it will be useful,
|
|
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13 |
* GNU General Public License for more details.
|
|
14 |
*
|
|
15 |
* You should have received a copy of the GNU General Public License
|
|
16 |
* along with this program; if not, write to the Free Software
|
|
17 |
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
18 |
*/
|
|
19 |
||
1237.13.8
by Padraig O'Sullivan
Updated an include guard thanks to a nice catch during code review from Jay. Thanks Jay! |
20 |
#ifndef DRIZZLED_OPTIMIZER_QUICK_INDEX_MERGE_SELECT_H
|
21 |
#define DRIZZLED_OPTIMIZER_QUICK_INDEX_MERGE_SELECT_H
|
|
1237.13.5
by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files. |
22 |
|
23 |
#include "drizzled/optimizer/range.h" |
|
24 |
||
1237.13.17
by Padraig O'Sullivan
Replaced List with std::vector in the QuickIndexMergeSelect class. |
25 |
#include <vector> |
26 |
||
1237.13.5
by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files. |
27 |
namespace drizzled |
28 |
{
|
|
29 |
||
30 |
namespace optimizer |
|
31 |
{
|
|
32 |
||
33 |
/**
|
|
34 |
@class QuickIndexMergeSelect - index_merge access method quick select.
|
|
35 |
||
36 |
QuickIndexMergeSelect uses
|
|
37 |
* QuickRangeSelects to get rows
|
|
38 |
* Unique class to remove duplicate rows
|
|
39 |
||
40 |
INDEX MERGE OPTIMIZER
|
|
41 |
Current implementation doesn't detect all cases where index_merge could
|
|
42 |
be used, in particular:
|
|
43 |
* index_merge will never be used if range scan is possible (even if
|
|
44 |
range scan is more expensive)
|
|
45 |
||
46 |
* index_merge+'using index' is not supported (this the consequence of
|
|
47 |
the above restriction)
|
|
48 |
||
49 |
* If WHERE part contains complex nested AND and OR conditions, some ways
|
|
50 |
to retrieve rows using index_merge will not be considered. The choice
|
|
51 |
of read plan may depend on the order of conjuncts/disjuncts in WHERE
|
|
52 |
part of the query, see comments near imerge_list_or_list and
|
|
53 |
SEL_IMERGE::or_sel_tree_with_checks functions for details.
|
|
54 |
||
55 |
* There is no "index_merge_ref" method (but index_merge on non-first
|
|
56 |
table in join is possible with 'range checked for each record').
|
|
57 |
||
58 |
See comments around SEL_IMERGE class and test_quick_select for more
|
|
59 |
details.
|
|
60 |
||
61 |
ROW RETRIEVAL ALGORITHM
|
|
62 |
||
63 |
index_merge uses Unique class for duplicates removal. index_merge takes
|
|
64 |
advantage of Clustered Primary Key (CPK) if the table has one.
|
|
65 |
The index_merge algorithm consists of two phases:
|
|
66 |
||
67 |
Phase 1 (implemented in QuickIndexMergeSelect::prepare_unique):
|
|
68 |
prepare()
|
|
69 |
{
|
|
70 |
activate 'index only';
|
|
71 |
while(retrieve next row for non-CPK scan)
|
|
72 |
{
|
|
73 |
if (there is a CPK scan and row will be retrieved by it)
|
|
74 |
skip this row;
|
|
75 |
else
|
|
76 |
put its rowid into Unique;
|
|
77 |
}
|
|
78 |
deactivate 'index only';
|
|
79 |
}
|
|
80 |
||
81 |
Phase 2 (implemented as sequence of QuickIndexMergeSelect::get_next
|
|
82 |
calls):
|
|
83 |
||
84 |
fetch()
|
|
85 |
{
|
|
86 |
retrieve all rows from row pointers stored in Unique;
|
|
87 |
free Unique;
|
|
88 |
retrieve all rows for CPK scan;
|
|
89 |
}
|
|
90 |
*/
|
|
91 |
class QuickIndexMergeSelect : public QuickSelectInterface |
|
92 |
{
|
|
93 |
public: |
|
94 |
||
95 |
QuickIndexMergeSelect(Session *session, Table *table); |
|
96 |
||
97 |
~QuickIndexMergeSelect(); |
|
98 |
||
99 |
int init(); |
|
100 |
int reset(void); |
|
101 |
||
102 |
/**
|
|
103 |
* Get next row for index_merge.
|
|
104 |
* NOTES
|
|
105 |
* The rows are read from
|
|
106 |
* 1. rowids stored in Unique.
|
|
107 |
* 2. QuickRangeSelect with clustered primary key (if any).
|
|
108 |
* The sets of rows retrieved in 1) and 2) are guaranteed to be disjoint.
|
|
109 |
*/
|
|
110 |
int get_next(); |
|
111 |
||
1237.13.11
by Padraig O'Sullivan
Split the QUICK_ROR_INTERSECT_SELECT class out into its own header and implementation files. |
112 |
bool reverse_sorted() const |
113 |
{
|
|
114 |
return false; |
|
115 |
}
|
|
116 |
||
117 |
bool unique_key_range() const |
|
118 |
{
|
|
119 |
return false; |
|
120 |
}
|
|
121 |
||
122 |
int get_type() const |
|
1237.13.5
by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files. |
123 |
{
|
124 |
return QS_TYPE_INDEX_MERGE; |
|
125 |
}
|
|
126 |
||
127 |
void add_keys_and_lengths(String *key_names, String *used_lengths); |
|
128 |
void add_info_string(String *str); |
|
129 |
bool is_keys_used(const MyBitmap *fields); |
|
130 |
||
131 |
bool push_quick_back(QuickRangeSelect *quick_sel_range); |
|
132 |
||
133 |
/* range quick selects this index_merge read consists of */
|
|
1237.13.17
by Padraig O'Sullivan
Replaced List with std::vector in the QuickIndexMergeSelect class. |
134 |
std::vector<QuickRangeSelect *> quick_selects; |
1237.13.5
by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files. |
135 |
|
136 |
/* quick select that uses clustered primary key (NULL if none) */
|
|
1237.13.15
by Padraig O'Sullivan
Used std::vector instead of List in the QuickRorUnionSelect class. |
137 |
QuickRangeSelect *pk_quick_select; |
1237.13.5
by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files. |
138 |
|
139 |
/* true if this select is currently doing a clustered PK scan */
|
|
140 |
bool doing_pk_scan; |
|
141 |
||
1280.1.10
by Monty Taylor
Put everything in drizzled into drizzled namespace. |
142 |
memory::Root alloc; |
1237.13.5
by Padraig O'Sullivan
Split some classes from the range optimizer out in to their own header and implementation files. |
143 |
Session *session; |
144 |
||
145 |
/**
|
|
146 |
* Perform key scans for all used indexes (except CPK), get rowids and merge
|
|
147 |
* them into an ordered non-recurrent sequence of rowids.
|
|
148 |
*
|
|
149 |
* The merge/duplicate removal is performed using Unique class. We put all
|
|
150 |
* rowids into Unique, get the sorted sequence and destroy the Unique.
|
|
151 |
*
|
|
152 |
* If table has a clustered primary key that covers all rows (true for bdb
|
|
153 |
* and innodb currently) and one of the index_merge scans is a scan on PK,
|
|
154 |
* then rows that will be retrieved by PK scan are not put into Unique and
|
|
155 |
* primary key scan is not performed here, it is performed later separately.
|
|
156 |
*
|
|
157 |
* RETURN
|
|
158 |
* @retval 0 OK
|
|
159 |
* @retval other error
|
|
160 |
*/
|
|
161 |
int read_keys_and_merge(); |
|
162 |
||
163 |
/* used to get rows collected in Unique */
|
|
164 |
READ_RECORD read_record; |
|
165 |
};
|
|
166 |
||
167 |
} /* namespace optimizer */ |
|
168 |
||
169 |
} /* namespace drizzled */ |
|
170 |
||
1237.13.8
by Padraig O'Sullivan
Updated an include guard thanks to a nice catch during code review from Jay. Thanks Jay! |
171 |
#endif /* DRIZZLED_OPTIMIZER_QUICK_INDEX_MERGE_SELECT_H */ |