MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
abstract_query_plan.cc
1 /*
2  Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
16 */
17 
18 #include "sql_priv.h"
19 #include "sql_select.h"
20 #include "sql_optimizer.h"
21 #include "abstract_query_plan.h"
22 #include "sql_join_buffer.h"
23 
24 namespace AQP
25 {
26 
32  : m_join_tabs(join->join_tab),
33  m_access_count(join->primary_tables),
34  m_table_accesses(NULL)
35  {
36  /*
37  This combination is assumed not to appear. If it does, code must
38  be written to handle it.
39  */
40  DBUG_ASSERT((m_join_tabs[0].use_quick != 2)
41  || (m_join_tabs[0].type == JT_ALL)
42  || (m_join_tabs[0].select == NULL)
43  || (m_join_tabs[0].select->quick == NULL));
44 
45  m_table_accesses= new Table_access[m_access_count];
46  for(uint i= 0; i < m_access_count; i++)
47  {
48  m_table_accesses[i].m_join_plan= this;
49  m_table_accesses[i].m_tab_no= i;
50  }
51  }
52 
53  Join_plan::~Join_plan()
54  {
55  delete[] m_table_accesses;
56  m_table_accesses= NULL;
57  }
58 
60  const JOIN_TAB* Join_plan::get_join_tab(uint join_tab_no) const
61  {
62  DBUG_ASSERT(join_tab_no < m_access_count);
63  return m_join_tabs + join_tab_no;
64  }
65 
71  Table_access::get_join_type(const Table_access* predecessor) const
72  {
73  DBUG_ENTER("get_join_type");
74  DBUG_ASSERT(get_access_no() > predecessor->get_access_no());
75 
76  const JOIN_TAB* const first_inner= get_join_tab()->first_inner;
77  if (first_inner == NULL)
78  {
79  // 'this' is not outer joined with any table.
80  DBUG_PRINT("info", ("JT_INNER_JOIN'ed table %s",
81  get_join_tab()->table->alias));
82  DBUG_RETURN(JT_INNER_JOIN);
83  }
84 
90  const JOIN_TAB* const last_inner= first_inner->last_inner;
91  if (predecessor->get_join_tab() >= first_inner &&
92  predecessor->get_join_tab() <= last_inner)
93  {
94  DBUG_PRINT("info", ("JT_INNER_JOIN between %s and %s",
95  predecessor->get_join_tab()->table->alias,
96  get_join_tab()->table->alias));
97  DBUG_RETURN(JT_INNER_JOIN);
98  }
99  else
100  {
101  DBUG_PRINT("info", ("JT_OUTER_JOIN between %s and %s",
102  predecessor->get_join_tab()->table->alias,
103  get_join_tab()->table->alias));
104  DBUG_RETURN(JT_OUTER_JOIN);
105  }
106  } //Table_access::get_join_type
107 
114  {
115  DBUG_ASSERT(m_access_type == AT_PRIMARY_KEY ||
116  m_access_type == AT_UNIQUE_KEY ||
117  m_access_type == AT_MULTI_PRIMARY_KEY ||
118  m_access_type == AT_MULTI_UNIQUE_KEY ||
119  m_access_type == AT_ORDERED_INDEX_SCAN); // Used as 'range scan'
120  return get_join_tab()->ref.key_parts;
121  }
122 
128  const Item* Table_access::get_key_field(uint field_no) const
129  {
130  DBUG_ASSERT(field_no < get_no_of_key_fields());
131  return get_join_tab()->ref.items[field_no];
132  }
133 
139  const KEY_PART_INFO* Table_access::get_key_part_info(uint field_no) const
140  {
141  DBUG_ASSERT(field_no < get_no_of_key_fields());
142  const KEY* key= &get_join_tab()->table->key_info[get_join_tab()->ref.key];
143  return &key->key_part[field_no];
144  }
145 
150  {
151  return get_join_tab()->table;
152  }
153 
154  double Table_access::get_fanout() const
155  {
156  switch (get_access_type())
157  {
158  case AT_PRIMARY_KEY:
159  case AT_UNIQUE_KEY:
160  return 1.0;
161 
163  DBUG_ASSERT(get_join_tab()->position);
164  DBUG_ASSERT(get_join_tab()->position->records_read>0.0);
165  return get_join_tab()->position->records_read;
166 
168  case AT_MULTI_UNIQUE_KEY:
169  case AT_MULTI_MIXED:
170  DBUG_ASSERT(get_join_tab()->position);
171  DBUG_ASSERT(get_join_tab()->position->records_read>0.0);
172  return get_join_tab()->position->records_read;
173 
174  case AT_TABLE_SCAN:
175  DBUG_ASSERT(get_join_tab()->table->file->stats.records>0.0);
176  return static_cast<double>(get_join_tab()->table->file->stats.records);
177 
178  default:
179  return 99999999.0;
180  }
181  }
182 
184  const JOIN_TAB* Table_access::get_join_tab() const
185  {
186  return m_join_plan->get_join_tab(m_tab_no);
187  }
188 
190  Item_equal*
191  Table_access::get_item_equal(const Item_field* field_item) const
192  {
193  DBUG_ASSERT(field_item->type() == Item::FIELD_ITEM);
194 
195  COND_EQUAL* const cond_equal = get_join_tab()->join->cond_equal;
196  if (cond_equal!=NULL)
197  {
198  return (field_item->item_equal != NULL)
199  ? field_item->item_equal
200  : const_cast<Item_field*>(field_item)->find_item_equal(cond_equal);
201  }
202  return NULL;
203  }
204 
209  {
210  DBUG_PRINT("info", ("type:%d", get_join_tab()->type));
211  DBUG_PRINT("info", ("ref.key:%d", get_join_tab()->ref.key));
212  DBUG_PRINT("info", ("ref.key_parts:%d", get_join_tab()->ref.key_parts));
213  DBUG_PRINT("info", ("ref.key_length:%d", get_join_tab()->ref.key_length));
214 
215  DBUG_PRINT("info", ("order:%p", get_join_tab()->join->order.order));
216  DBUG_PRINT("info", ("skip_sort_order:%d",
217  get_join_tab()->join->skip_sort_order));
218  DBUG_PRINT("info", ("no_order:%d", get_join_tab()->join->no_order));
219  DBUG_PRINT("info", ("simple_order:%d", get_join_tab()->join->simple_order));
220 
221  DBUG_PRINT("info", ("group:%d", get_join_tab()->join->group));
222  DBUG_PRINT("info", ("group_list:%p", get_join_tab()->join->group_list.order));
223  DBUG_PRINT("info", ("simple_group:%d", get_join_tab()->join->simple_group));
224  DBUG_PRINT("info", ("group_optimized_away:%d",
225  get_join_tab()->join->group_optimized_away));
226 
227  DBUG_PRINT("info", ("full_join:%d", get_join_tab()->join->full_join));
228  DBUG_PRINT("info", ("need_tmp:%d", get_join_tab()->join->need_tmp));
229  DBUG_PRINT("info", ("select_distinct:%d",
230  get_join_tab()->join->select_distinct));
231 
232  DBUG_PRINT("info", ("use_quick:%d", get_join_tab()->use_quick));
233  DBUG_PRINT("info", ("index:%d", get_join_tab()->index));
234  DBUG_PRINT("info", ("quick:%p", get_join_tab()->quick));
235  DBUG_PRINT("info", ("select:%p", get_join_tab()->select));
236  if (get_join_tab()->select && get_join_tab()->select->quick)
237  {
238  DBUG_PRINT("info", ("select->quick->get_type():%d",
239  get_join_tab()->select->quick->get_type()));
240  }
241  }
242 
243 
247  void Table_access::compute_type_and_index() const
248  {
249  DBUG_ENTER("Table_access::compute_type_and_index");
250  const JOIN_TAB* const join_tab= get_join_tab();
251  JOIN* const join= join_tab->join;
252 
258  if (join->group_list && !join->tmp_table_param.quick_group)
259  {
260  m_access_type= AT_OTHER;
261  m_other_access_reason =
262  "GROUP BY cannot be done using index on grouped columns.";
263  DBUG_VOID_RETURN;
264  }
265 
266  /* Tables below 'const_tables' has been const'ified, or entirely
267  * optimized away due to 'impossible WHERE/ON'
268  */
269  if (join_tab < join->join_tab+join->const_tables)
270  {
271  DBUG_PRINT("info", ("Operation %d is const-optimized.", m_tab_no));
272  m_access_type= AT_FIXED;
273  DBUG_VOID_RETURN;
274  }
275 
276  /*
277  Identify the type of access operation and the index to use (if any).
278  */
279  switch (join_tab->type)
280  {
281  case JT_EQ_REF:
282  m_index_no= join_tab->ref.key;
283 
284  if (m_index_no == static_cast<int>(join_tab->table->s->primary_key))
285  {
286  DBUG_PRINT("info", ("Operation %d is a primary key lookup.", m_tab_no));
287  m_access_type= AT_PRIMARY_KEY;
288  }
289  else
290  {
291  DBUG_PRINT("info", ("Operation %d is a unique index lookup.",
292  m_tab_no));
293  m_access_type= AT_UNIQUE_KEY;
294  }
295  break;
296 
297  case JT_REF:
298  {
299  DBUG_ASSERT(join_tab->ref.key >= 0);
300  DBUG_ASSERT((uint)join_tab->ref.key < MAX_KEY);
301  m_index_no= join_tab->ref.key;
302 
303  /*
304  All parts of a key are specified for an unique index -> access is a key lookup.
305  */
306  const KEY *key_info= join_tab->table->s->key_info;
307  if (key_info[m_index_no].user_defined_key_parts ==
308  join_tab->ref.key_parts &&
309  key_info[m_index_no].flags & HA_NOSAME)
310  {
311  m_access_type=
312  (m_index_no == static_cast<int32>(join_tab->table->s->primary_key))
314  : AT_UNIQUE_KEY;
315  DBUG_PRINT("info", ("Operation %d is an unique key referrence.", m_tab_no));
316  }
317  else
318  {
319  DBUG_ASSERT(join_tab->ref.key_parts > 0);
320  DBUG_ASSERT(join_tab->ref.key_parts <=
321  key_info[m_index_no].user_defined_key_parts);
322  m_access_type= AT_ORDERED_INDEX_SCAN;
323  DBUG_PRINT("info", ("Operation %d is an ordered index scan.", m_tab_no));
324  }
325  break;
326  }
327  case JT_INDEX_SCAN:
328  DBUG_ASSERT(join_tab->index < MAX_KEY);
329  m_index_no= join_tab->index;
330  m_access_type= AT_ORDERED_INDEX_SCAN;
331  DBUG_PRINT("info", ("Operation %d is an ordered index scan.", m_tab_no));
332  break;
333 
334  case JT_ALL:
335  if (join_tab->use_quick == 2)
336  {
337  /*
338  use_quick == 2 means that the decision on which access method to use
339  will be taken late (as rows from the preceeding operation arrive).
340  This operation is therefor not pushable.
341  */
342  DBUG_PRINT("info",
343  ("Operation %d has 'use_quick == 2' -> not pushable",
344  m_tab_no));
345  m_access_type= AT_UNDECIDED;
346  m_index_no= -1;
347  }
348  else
349  {
350  if (join_tab->select != NULL &&
351  join_tab->select->quick != NULL)
352  {
353  QUICK_SELECT_I *quick= join_tab->select->quick;
354 
364  const KEY *key_info= join_tab->table->s->key_info;
365  DBUG_EXECUTE("info", quick->dbug_dump(0, TRUE););
366 
367  // Temporary assert as we are still investigation the relation between
368  // 'quick->index == MAX_KEY' and the different quick_types
369  DBUG_ASSERT ((quick->index == MAX_KEY) ==
370  ((quick->get_type() == QUICK_SELECT_I::QS_TYPE_INDEX_MERGE) ||
371  (quick->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) ||
372  (quick->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_UNION)));
373 
374  // JT_INDEX_MERGE: We have a set of qualifying PKs as root of pushed joins
375  if (quick->index == MAX_KEY)
376  {
377  m_index_no= join_tab->table->s->primary_key;
378  m_access_type= AT_MULTI_PRIMARY_KEY; // Multiple PKs are produced by merge
379  }
380 
381  // Else JT_RANGE: May be both exact PK and/or index scans when sorted index available
382  else if (quick->index == join_tab->table->s->primary_key)
383  {
384  m_index_no= quick->index;
385  if (key_info[m_index_no].algorithm == HA_KEY_ALG_HASH)
386  m_access_type= AT_MULTI_PRIMARY_KEY; // MRR w/ multiple PK's
387  else
388  m_access_type= AT_MULTI_MIXED; // MRR w/ both range and PKs
389  }
390  else
391  {
392  m_index_no= quick->index;
393  if (key_info[m_index_no].algorithm == HA_KEY_ALG_HASH)
394  m_access_type= AT_MULTI_UNIQUE_KEY; // MRR with multiple unique keys
395  else
396  m_access_type= AT_MULTI_MIXED; // MRR w/ both range and unique keys
397  }
398  }
399  else
400  {
401  DBUG_PRINT("info", ("Operation %d is a table scan.", m_tab_no));
402  m_access_type= AT_TABLE_SCAN;
403  }
404  }
405  break;
406 
407  case JT_CONST:
408  case JT_SYSTEM:
409  default:
410  /*
411  Other join_types either cannot be pushed or the code analyze them is
412  not yet in place.
413  */
414  DBUG_PRINT("info",
415  ("Operation %d has join_type %d. -> Not pushable.",
416  m_tab_no, join_tab->type));
417  m_access_type= AT_OTHER;
418  m_index_no= -1;
419  m_other_access_reason = "This table access method can not be pushed.";
420  break;
421  }
422  DBUG_VOID_RETURN;
423  }
424  // Table_access::compute_type_and_index()
425 
426 
427  Table_access::Table_access()
428  :m_join_plan(NULL),
429  m_tab_no(0),
430  m_access_type(AT_VOID),
431  m_other_access_reason(NULL),
432  m_index_no(-1)
433  {}
434 
441  {
442  return get_join_tab()->use_join_cache != JOIN_CACHE::ALG_NONE;
443  }
444 
450  {
451  if (m_access_type == AT_PRIMARY_KEY ||
452  m_access_type == AT_UNIQUE_KEY)
453  {
454  return false;
455  }
456 
457  const JOIN_TAB* const join_tab= get_join_tab();
458  JOIN* const join= join_tab->join;
459 
471  if (join_tab == join->join_tab+join->const_tables &&// First non-const table
472  !join->plan_is_const()) // There are more tables
473  {
474  if (join->need_tmp)
475  return false;
476  else if (join->group_list && join->simple_group)
477  return (join->ordered_index_usage!=JOIN::ordered_index_group_by);
478  else if (join->order && join->simple_order)
479  return (join->ordered_index_usage!=JOIN::ordered_index_order_by);
480  else
481  return false;
482  }
483  return false;
484  }
485 
486 };
487 // namespace AQP