1 /*
2 Copyright (c) 2013 Monty Program Ab
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 Street, Fifth Floor, Boston, MA 02110-1335 USA */
16
17 /*
18
19 == EXPLAIN/ANALYZE architecture ==
20
21 === [SHOW] EXPLAIN data ===
22 Query optimization produces two data structures:
23 1. execution data structures themselves (eg. JOINs, JOIN_TAB, etc, etc)
24 2. Explain data structures.
25
26 #2 are self contained set of data structures that has sufficient info to
27 produce output of SHOW EXPLAIN, EXPLAIN [FORMAT=JSON], or
28 ANALYZE [FORMAT=JSON], without accessing the execution data structures.
29
30 (the only exception is that Explain data structures keep Item* pointers,
31 and we require that one might call item->print(QT_EXPLAIN) when printing
32 FORMAT=JSON output)
33
34 === ANALYZE data ===
35 EXPLAIN data structures have embedded ANALYZE data structures. These are
36 objects that are used to track how the parts of query plan were executed:
37 how many times each part of query plan was invoked, how many rows were
38 read/returned, etc.
39
40 Each execution data structure keeps a direct pointer to its ANALYZE data
41 structure. It is needed so that execution code can quickly increment the
42 counters.
43
44 (note that this increases the set of data that is frequently accessed
45 during the execution. What is the impact of this?)
46
47 Since ANALYZE/EXPLAIN data structures are separated from execution data
48 structures, it is easy to have them survive until the end of the query,
49 where we can return ANALYZE [FORMAT=JSON] output to the user, or print
50 it into the slow query log.
51
52 */
53
54 #ifndef SQL_EXPLAIN_INCLUDED
55 #define SQL_EXPLAIN_INCLUDED
56
57 class String_list: public List<char>
58 {
59 public:
60 const char *append_str(MEM_ROOT *mem_root, const char *str);
61 };
62
63 class Json_writer;
64
65 /**************************************************************************************
66
67 Data structures for producing EXPLAIN outputs.
68
69 These structures
70 - Can be produced inexpensively from query plan.
71 - Store sufficient information to produce tabular EXPLAIN output (the goal is
72 to be able to produce JSON also)
73
74 *************************************************************************************/
75
76
77 const int FAKE_SELECT_LEX_ID= (int)UINT_MAX;
78
79 class Explain_query;
80
81 /*
82 A node can be either a SELECT, or a UNION.
83 */
84 class Explain_node : public Sql_alloc
85 {
86 public:
87 Explain_node(MEM_ROOT *root) :
88 cache_tracker(NULL),
89 connection_type(EXPLAIN_NODE_OTHER),
90 children(root)
91 {}
92 /* A type specifying what kind of node this is */
93 enum explain_node_type
94 {
95 EXPLAIN_UNION,
96 EXPLAIN_SELECT,
97 EXPLAIN_BASIC_JOIN,
98 EXPLAIN_UPDATE,
99 EXPLAIN_DELETE,
100 EXPLAIN_INSERT
101 };
102
103 /* How this node is connected */
104 enum explain_connection_type {
105 EXPLAIN_NODE_OTHER,
106 EXPLAIN_NODE_DERIVED, /* Materialized derived table */
107 EXPLAIN_NODE_NON_MERGED_SJ /* aka JTBM semi-join */
108 };
109
110 virtual enum explain_node_type get_type()= 0;
111 virtual int get_select_id()= 0;
112
113 /**
114 expression cache statistics
115 */
116 Expression_cache_tracker* cache_tracker;
117
118 /*
119 How this node is connected to its parent.
120 (NOTE: EXPLAIN_NODE_NON_MERGED_SJ is set very late currently)
121 */
122 enum explain_connection_type connection_type;
123
124 protected:
125 /*
126 A node may have children nodes. When a node's explain structure is
127 created, children nodes may not yet have QPFs. This is why we store ids.
128 */
129 Dynamic_array<int> children;
130 public:
131 void add_child(int select_no)
132 {
133 children.append(select_no);
134 }
135
136 virtual int print_explain(Explain_query *query, select_result_sink *output,
137 uint8 explain_flags, bool is_analyze)=0;
138 virtual void print_explain_json(Explain_query *query, Json_writer *writer,
139 bool is_analyze)= 0;
140
141 int print_explain_for_children(Explain_query *query, select_result_sink *output,
142 uint8 explain_flags, bool is_analyze);
143 void print_explain_json_for_children(Explain_query *query,
144 Json_writer *writer, bool is_analyze);
145 bool print_explain_json_cache(Json_writer *writer, bool is_analyze);
146 virtual ~Explain_node(){}
147 };
148
149
150 class Explain_table_access;
151
152
153 /*
154 A basic join. This is only used for SJ-Materialization nests.
155
156 Basic join doesn't have ORDER/GROUP/DISTINCT operations. It also cannot be
157 degenerate.
158
159 It has its own select_id.
160 */
161 class Explain_basic_join : public Explain_node
162 {
163 public:
164 enum explain_node_type get_type() { return EXPLAIN_BASIC_JOIN; }
165
166 Explain_basic_join(MEM_ROOT *root) : Explain_node(root), join_tabs(NULL) {}
167 ~Explain_basic_join();
168
169 bool add_table(Explain_table_access *tab, Explain_query *query);
170
171 int get_select_id() { return select_id; }
172
173 int select_id;
174
175 int print_explain(Explain_query *query, select_result_sink *output,
176 uint8 explain_flags, bool is_analyze);
177 void print_explain_json(Explain_query *query, Json_writer *writer,
178 bool is_analyze);
179
180 void print_explain_json_interns(Explain_query *query, Json_writer *writer,
181 bool is_analyze);
182
183 /* A flat array of Explain structs for tables. */
184 Explain_table_access** join_tabs;
185 uint n_join_tabs;
186 };
187
188
189 class Explain_aggr_node;
190 /*
191 EXPLAIN structure for a SELECT.
192
193 A select can be:
194 1. A degenerate case. In this case, message!=NULL, and it contains a
195 description of what kind of degenerate case it is (e.g. "Impossible
196 WHERE").
197 2. a non-degenrate join. In this case, join_tabs describes the join.
198
199 In the non-degenerate case, a SELECT may have a GROUP BY/ORDER BY operation.
200
201 In both cases, the select may have children nodes. class Explain_node
202 provides a way get node's children.
203 */
204
205 class Explain_select : public Explain_basic_join
206 {
207 public:
208 enum explain_node_type get_type() { return EXPLAIN_SELECT; }
209
210 Explain_select(MEM_ROOT *root, bool is_analyze) :
211 Explain_basic_join(root),
212 #ifndef DBUG_OFF
213 select_lex(NULL),
214 #endif
215 linkage(UNSPECIFIED_TYPE),
216 is_lateral(false),
217 message(NULL),
218 having(NULL), having_value(Item::COND_UNDEF),
219 using_temporary(false), using_filesort(false),
220 time_tracker(is_analyze),
221 aggr_tree(NULL)
222 {}
223
224 void add_linkage(Json_writer *writer);
225
226 public:
227 #ifndef DBUG_OFF
228 SELECT_LEX *select_lex;
229 #endif
230 const char *select_type;
231 enum sub_select_type linkage;
232 bool is_lateral;
233
234 /*
235 If message != NULL, this is a degenerate join plan, and all subsequent
236 members have no info
237 */
238 const char *message;
239
240 /* Expensive constant condition */
241 Item *exec_const_cond;
242 Item *outer_ref_cond;
243 Item *pseudo_bits_cond;
244
245 /* HAVING condition */
246 Item *having;
247 Item::cond_result having_value;
248
249 /* Global join attributes. In tabular form, they are printed on the first row */
250 bool using_temporary;
251 bool using_filesort;
252
253 /* ANALYZE members */
254 Time_and_counter_tracker time_tracker;
255
256 /*
257 Part of query plan describing sorting, temp.table usage, and duplicate
258 removal
259 */
260 Explain_aggr_node* aggr_tree;
261
262 int print_explain(Explain_query *query, select_result_sink *output,
263 uint8 explain_flags, bool is_analyze);
264 void print_explain_json(Explain_query *query, Json_writer *writer,
265 bool is_analyze);
266
267 Table_access_tracker *get_using_temporary_read_tracker()
268 {
269 return &using_temporary_read_tracker;
270 }
271 private:
272 Table_access_tracker using_temporary_read_tracker;
273 };
274
275 /////////////////////////////////////////////////////////////////////////////
276 // EXPLAIN structures for ORDER/GROUP operations.
277 /////////////////////////////////////////////////////////////////////////////
278 typedef enum
279 {
280 AGGR_OP_TEMP_TABLE,
281 AGGR_OP_FILESORT,
282 //AGGR_OP_READ_SORTED_FILE, // need this?
283 AGGR_OP_REMOVE_DUPLICATES,
284 AGGR_OP_WINDOW_FUNCS
285 //AGGR_OP_JOIN // Need this?
286 } enum_explain_aggr_node_type;
287
288
289 class Explain_aggr_node : public Sql_alloc
290 {
291 public:
292 virtual enum_explain_aggr_node_type get_type()= 0;
293 virtual ~Explain_aggr_node() {}
294 Explain_aggr_node *child;
295 };
296
297 class Explain_aggr_filesort : public Explain_aggr_node
298 {
299 List<Item> sort_items;
300 List<ORDER::enum_order> sort_directions;
301 public:
302 enum_explain_aggr_node_type get_type() { return AGGR_OP_FILESORT; }
303 Filesort_tracker tracker;
304
305 Explain_aggr_filesort(MEM_ROOT *mem_root, bool is_analyze,
306 Filesort *filesort);
307
308 void print_json_members(Json_writer *writer, bool is_analyze);
309 };
310
311 class Explain_aggr_tmp_table : public Explain_aggr_node
312 {
313 public:
314 enum_explain_aggr_node_type get_type() { return AGGR_OP_TEMP_TABLE; }
315 };
316
317 class Explain_aggr_remove_dups : public Explain_aggr_node
318 {
319 public:
320 enum_explain_aggr_node_type get_type() { return AGGR_OP_REMOVE_DUPLICATES; }
321 };
322
323 class Explain_aggr_window_funcs : public Explain_aggr_node
324 {
325 List<Explain_aggr_filesort> sorts;
326 public:
327 enum_explain_aggr_node_type get_type() { return AGGR_OP_WINDOW_FUNCS; }
328
329 void print_json_members(Json_writer *writer, bool is_analyze);
330 friend class Window_funcs_computation;
331 };
332
333 /////////////////////////////////////////////////////////////////////////////
334
335 extern const char *unit_operation_text[4];
336
337 /*
338 Explain structure for a UNION.
339
340 A UNION may or may not have "Using filesort".
341 */
342
343 class Explain_union : public Explain_node
344 {
345 public:
346 Explain_union(MEM_ROOT *root, bool is_analyze) :
347 Explain_node(root),
348 is_recursive_cte(false),
349 fake_select_lex_explain(root, is_analyze)
350 {}
351
352 enum explain_node_type get_type() { return EXPLAIN_UNION; }
353 unit_common_op operation;
354
355 int get_select_id()
356 {
357 DBUG_ASSERT(union_members.elements() > 0);
358 return union_members.at(0);
359 }
360 /*
361 Members of the UNION. Note: these are different from UNION's "children".
362 Example:
363
364 (select * from t1) union
365 (select * from t2) order by (select col1 from t3 ...)
366
367 here
368 - select-from-t1 and select-from-t2 are "union members",
369 - select-from-t3 is the only "child".
370 */
371 Dynamic_array<int> union_members;
372
373 void add_select(int select_no)
374 {
375 union_members.append(select_no);
376 }
377 int print_explain(Explain_query *query, select_result_sink *output,
378 uint8 explain_flags, bool is_analyze);
379 void print_explain_json(Explain_query *query, Json_writer *writer,
380 bool is_analyze);
381
382 const char *fake_select_type;
383 bool using_filesort;
384 bool using_tmp;
385 bool is_recursive_cte;
386
387 /*
388 Explain data structure for "fake_select_lex" (i.e. for the degenerate
389 SELECT that reads UNION result).
390 It doesn't have a query plan, but we still need execution tracker, etc.
391 */
392 Explain_select fake_select_lex_explain;
393
394 Table_access_tracker *get_fake_select_lex_tracker()
395 {
396 return &fake_select_lex_tracker;
397 }
398 Table_access_tracker *get_tmptable_read_tracker()
399 {
400 return &tmptable_read_tracker;
401 }
402 private:
403 uint make_union_table_name(char *buf);
404
405 Table_access_tracker fake_select_lex_tracker;
406 /* This one is for reading after ORDER BY */
407 Table_access_tracker tmptable_read_tracker;
408 };
409
410
411 class Explain_update;
412 class Explain_delete;
413 class Explain_insert;
414
415
416 /*
417 Explain structure for a query (i.e. a statement).
418
419 This should be able to survive when the query plan was deleted. Currently,
420 we do not intend for it survive until after query's MEM_ROOT is freed. It
421 does surivive freeing of query's items.
422
423 For reference, the process of post-query cleanup is as follows:
424
425 >dispatch_command
426 | >mysql_parse
427 | | ...
428 | | lex_end()
429 | | ...
430 | | >THD::cleanup_after_query
431 | | | ...
432 | | | free_items()
433 | | | ...
434 | | <THD::cleanup_after_query
435 | |
436 | <mysql_parse
437 |
438 | log_slow_statement()
439 |
440 | free_root()
441 |
442 >dispatch_command
443
444 That is, the order of actions is:
445 - free query's Items
446 - write to slow query log
447 - free query's MEM_ROOT
448
449 */
450
451 class Explain_query : public Sql_alloc
452 {
453 public:
454 Explain_query(THD *thd, MEM_ROOT *root);
455 ~Explain_query();
456
457 /* Add a new node */
458 void add_node(Explain_node *node);
459 void add_insert_plan(Explain_insert *insert_plan_arg);
460 void add_upd_del_plan(Explain_update *upd_del_plan_arg);
461
462 /* This will return a select, or a union */
463 Explain_node *get_node(uint select_id);
464
465 /* This will return a select (even if there is a union with this id) */
466 Explain_select *get_select(uint select_id);
467
468 Explain_union *get_union(uint select_id);
469
470 /* Produce a tabular EXPLAIN output */
471 int print_explain(select_result_sink *output, uint8 explain_flags,
472 bool is_analyze);
473
474 /* Send tabular EXPLAIN to the client */
475 int send_explain(THD *thd);
476
477 /* Return tabular EXPLAIN output as a text string */
478 bool print_explain_str(THD *thd, String *out_str, bool is_analyze);
479
480 void print_explain_json(select_result_sink *output, bool is_analyze);
481
482 /* If true, at least part of EXPLAIN can be printed */
483 bool have_query_plan() { return insert_plan || upd_del_plan|| get_node(1) != NULL; }
484
485 void query_plan_ready();
486
487 MEM_ROOT *mem_root;
488
489 Explain_update *get_upd_del_plan() { return upd_del_plan; }
490 private:
491 /* Explain_delete inherits from Explain_update */
492 Explain_update *upd_del_plan;
493
494 /* Query "plan" for INSERTs */
495 Explain_insert *insert_plan;
496
497 Dynamic_array<Explain_union*> unions;
498 Dynamic_array<Explain_select*> selects;
499
500 THD *thd; // for APC start/stop
501 bool apc_enabled;
502 /*
503 Debugging aid: count how many times add_node() was called. Ideally, it
504 should be one, we currently allow O(1) query plan saves for each
505 select or union. The goal is not to have O(#rows_in_some_table), which
506 is unacceptable.
507 */
508 longlong operations;
509 };
510
511
512 /*
513 Some of the tags have matching text. See extra_tag_text for text names, and
514 Explain_table_access::append_tag_name() for code to convert from tag form to text
515 form.
516 */
517 enum explain_extra_tag
518 {
519 ET_none= 0, /* not-a-tag */
520 ET_USING_INDEX_CONDITION,
521 ET_USING_INDEX_CONDITION_BKA,
522 ET_USING, /* For quick selects of various kinds */
523 ET_RANGE_CHECKED_FOR_EACH_RECORD,
524 ET_USING_WHERE_WITH_PUSHED_CONDITION,
525 ET_USING_WHERE,
526 ET_NOT_EXISTS,
527
528 ET_USING_INDEX,
529 ET_FULL_SCAN_ON_NULL_KEY,
530 ET_SKIP_OPEN_TABLE,
531 ET_OPEN_FRM_ONLY,
532 ET_OPEN_FULL_TABLE,
533
534 ET_SCANNED_0_DATABASES,
535 ET_SCANNED_1_DATABASE,
536 ET_SCANNED_ALL_DATABASES,
537
538 ET_USING_INDEX_FOR_GROUP_BY,
539
540 ET_USING_MRR, // does not print "Using mrr".
541
542 ET_DISTINCT,
543 ET_LOOSESCAN,
544 ET_START_TEMPORARY,
545 ET_END_TEMPORARY,
546 ET_FIRST_MATCH,
547
548 ET_USING_JOIN_BUFFER,
549
550 ET_CONST_ROW_NOT_FOUND,
551 ET_UNIQUE_ROW_NOT_FOUND,
552 ET_IMPOSSIBLE_ON_CONDITION,
553
554 ET_total
555 };
556
557
558 /*
559 Explain data structure describing join buffering use.
560 */
561
562 class EXPLAIN_BKA_TYPE
563 {
564 public:
565 EXPLAIN_BKA_TYPE() : join_alg(NULL) {}
566
567 size_t join_buffer_size;
568
569 bool incremental;
570
571 /*
572 NULL if no join buferring used.
makePattern(const DenseSet<Operation * > & parallelLoops,int vectorRank,ArrayRef<int64_t> fastestVaryingPattern)573 Other values: BNL, BNLH, BKA, BKAH.
574 */
575 const char *join_alg;
576
577 /* Information about MRR usage. */
578 StringBuffer<64> mrr_type;
579
580 bool is_using_jbuf() { return (join_alg != NULL); }
581 };
582
583
584 /*
585 Data about how an index is used by some access method
586 */
587 class Explain_index_use : public Sql_alloc
588 {
589 char *key_name;
590 uint key_len;
591 public:
592 String_list key_parts_list;
593
594 Explain_index_use()
vectorTransferPattern()595 {
596 clear();
597 }
598
599 void clear()
600 {
601 key_name= NULL;
602 key_len= (uint)-1;
603 }
604 bool set(MEM_ROOT *root, KEY *key_name, uint key_len_arg);
605 bool set_pseudo_key(MEM_ROOT *root, const char *key_name);
606
607 inline const char *get_key_name() const { return key_name; }
608 inline uint get_key_len() const { return key_len; }
609 };
610
611
612 /*
613 QPF for quick range selects, as well as index_merge select
Vectorize(ArrayRef<int64_t> virtualVectorSize)614 */
615 class Explain_quick_select : public Sql_alloc
616 {
617 public:
618 Explain_quick_select(int quick_type_arg) : quick_type(quick_type_arg)
619 {}
620
621 const int quick_type;
622
623 bool is_basic()
624 {
625 return (quick_type == QUICK_SELECT_I::QS_TYPE_RANGE ||
626 quick_type == QUICK_SELECT_I::QS_TYPE_RANGE_DESC ||
627 quick_type == QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX);
628 }
629
630 /* This is used when quick_type == QUICK_SELECT_I::QS_TYPE_RANGE */
631 Explain_index_use range;
632
633 /* Used in all other cases */
634 List<Explain_quick_select> children;
635
636 void print_extra(String *str);
637 void print_key(String *str);
638 void print_key_len(String *str);
639
640 void print_json(Json_writer *writer);
641
642 void print_extra_recursive(String *str);
643 private:
644 const char *get_name_by_type();
645 };
analyzeProfitability(ArrayRef<NestedMatch> matches,unsigned depthInPattern,unsigned patternDepth,VectorizationStrategy * strategy)646
647
648 /*
649 Data structure for "range checked for each record".
650 It's a set of keys, tabular explain prints hex bitmap, json prints key names.
651 */
652
653 typedef const char* NAME;
654
655 class Explain_range_checked_fer : public Sql_alloc
656 {
657 public:
658 String_list key_set;
659 key_map keys_map;
660 private:
661 ha_rows full_scan, index_merge;
662 ha_rows *keys_stat;
663 NAME *keys_stat_names;
664 uint keys;
665
666 public:
VectorizationState__anonb1a5bee80311::VectorizationState667 Explain_range_checked_fer()
668 :Sql_alloc(), full_scan(0), index_merge(0),
669 keys_stat(0), keys_stat_names(0), keys(0)
670 {}
671
672 int append_possible_keys_stat(MEM_ROOT *alloc,
673 TABLE *table, key_map possible_keys);
674 void collect_data(QUICK_SELECT_I *quick);
675 void print_json(Json_writer *writer, bool is_analyze);
676 };
677
678 /*
679 EXPLAIN data structure for a single JOIN_TAB.
680 */
681
682 class Explain_table_access : public Sql_alloc
683 {
684 public:
685 Explain_table_access(MEM_ROOT *root) :
686 derived_select_number(0),
687 non_merged_sjm_number(0),
688 extra_tags(root),
689 range_checked_fer(NULL),
690 full_scan_on_null_key(false),
691 start_dups_weedout(false),
692 end_dups_weedout(false),
693 where_cond(NULL),
694 cache_cond(NULL),
695 pushed_index_cond(NULL),
696 sjm_nest(NULL),
697 pre_join_sort(NULL)
698 {}
699 ~Explain_table_access() { delete sjm_nest; }
700
701 void push_extra(enum explain_extra_tag extra_tag);
702
703 /* Internals */
704
705 /* id and 'select_type' are cared-of by the parent Explain_select */
706 StringBuffer<32> table_name;
707 StringBuffer<32> used_partitions;
708 String_list used_partitions_list;
709 // valid with ET_USING_MRR
710 StringBuffer<32> mrr_type;
711 StringBuffer<32> firstmatch_table_name;
712
713 /*
714 Non-zero number means this is a derived table. The number can be used to
715 find the query plan for the derived table
716 */
717 int derived_select_number;
718 /* TODO: join with the previous member. */
719 int non_merged_sjm_number;
720
721 enum join_type type;
722
723 bool used_partitions_set;
724
725 /* Empty means "NULL" will be printed */
726 String_list possible_keys;
727
728 bool rows_set; /* not set means 'NULL' should be printed */
729 bool filtered_set; /* not set means 'NULL' should be printed */
730 // Valid if ET_USING_INDEX_FOR_GROUP_BY is present
731 bool loose_scan_is_scanning;
732
733 /*
734 Index use: key name and length.
735 Note: that when one is accessing I_S tables, those may show use of
736 non-existant indexes.
737
738 key.key_name == NULL means 'NULL' will be shown in tabular output.
739 key.key_len == (uint)-1 means 'NULL' will be shown in tabular output.
740 */
741 Explain_index_use key;
742
743 /*
744 when type==JT_HASH_NEXT, 'key' stores the hash join pseudo-key.
745 hash_next_key stores the table's key.
746 */
747 Explain_index_use hash_next_key;
748
749 String_list ref_list;
750
751 ha_rows rows;
752 double filtered;
753
754 /*
755 Contents of the 'Extra' column. Some are converted into strings, some have
756 parameters, values for which are stored below.
757 */
758 Dynamic_array<enum explain_extra_tag> extra_tags;
759
760 // Valid if ET_USING tag is present
761 Explain_quick_select *quick_info;
762
763 /* Non-NULL value means this tab uses "range checked for each record" */
764 Explain_range_checked_fer *range_checked_fer;
765
766 bool full_scan_on_null_key;
767
768 // valid with ET_USING_JOIN_BUFFER
769 EXPLAIN_BKA_TYPE bka_type;
770
771 bool start_dups_weedout;
772 bool end_dups_weedout;
773
774 /*
775 Note: lifespan of WHERE condition is less than lifespan of this object.
registerOpVectorReplacement(Operation * replaced,Operation * replacement)776 The below two are valid if tags include "ET_USING_WHERE".
777 (TODO: indexsubquery may put ET_USING_WHERE without setting where_cond?)
778 */
779 Item *where_cond;
780 Item *cache_cond;
781
782 /*
783 This is either pushed index condition, or BKA's index condition.
784 (the latter refers to columns of other tables and so can only be checked by
785 BKA code). Examine extra_tags to tell which one it is.
786 */
787 Item *pushed_index_cond;
788
789 Explain_basic_join *sjm_nest;
790
791 /*
792 This describes a possible filesort() call that is done before doing the
793 join operation.
794 */
795 Explain_aggr_filesort *pre_join_sort;
796
797 /* ANALYZE members */
798
799 /* Tracker for reading the table */
800 Table_access_tracker tracker;
801 Exec_time_tracker op_tracker;
802 Table_access_tracker jbuf_tracker;
803
registerValueVectorReplacement(Value replaced,Operation * replacement)804 int print_explain(select_result_sink *output, uint8 explain_flags,
805 bool is_analyze,
806 uint select_id, const char *select_type,
807 bool using_temporary, bool using_filesort);
808 void print_explain_json(Explain_query *query, Json_writer *writer,
809 bool is_analyze);
810
811 private:
812 void append_tag_name(String *str, enum explain_extra_tag tag);
813 void fill_key_str(String *key_str, bool is_json) const;
814 void fill_key_len_str(String *key_len_str) const;
815 double get_r_filtered();
816 void tag_to_json(Json_writer *writer, enum explain_extra_tag tag);
817 };
818
registerBlockArgVectorReplacement(BlockArgument replaced,BlockArgument replacement)819
820 /*
821 EXPLAIN structure for single-table UPDATE.
822
823 This is similar to Explain_table_access, except that it is more restrictive.
824 Also, it can have UPDATE operation options, but currently there aren't any.
825
826 Explain_delete inherits from this.
827 */
828
829 class Explain_update : public Explain_node
830 {
831 public:
832
833 Explain_update(MEM_ROOT *root, bool is_analyze) :
834 Explain_node(root),
835 filesort_tracker(NULL),
836 command_tracker(is_analyze)
837 {}
838
839 virtual enum explain_node_type get_type() { return EXPLAIN_UPDATE; }
840 virtual int get_select_id() { return 1; /* always root */ }
841
842 const char *select_type;
843
844 StringBuffer<32> used_partitions;
845 String_list used_partitions_list;
846 bool used_partitions_set;
847
848 bool impossible_where;
849 bool no_partitions;
850 StringBuffer<64> table_name;
851
852 enum join_type jtype;
853 String_list possible_keys;
854
855 /* Used key when doing a full index scan (possibly with limit) */
856 Explain_index_use key;
857
858 /*
859 MRR that's used with quick select. This should probably belong to the
860 quick select
861 */
862 StringBuffer<64> mrr_type;
863
864 Explain_quick_select *quick_info;
865
866 bool using_where;
867 Item *where_cond;
868
869 ha_rows rows;
870
871 bool using_io_buffer;
872
873 /* Tracker for doing reads when filling the buffer */
874 Table_access_tracker buf_tracker;
875
876 bool is_using_filesort() { return filesort_tracker? true: false; }
877 /*
878 Non-null value of filesort_tracker means "using filesort"
879
880 if we are using filesort, then table_tracker is for the io done inside
881 filesort.
882
883 'tracker' is for tracking post-filesort reads.
884 */
885 Filesort_tracker *filesort_tracker;
886
887 /* ANALYZE members and methods */
888 Table_access_tracker tracker;
889
890 /* This tracks execution of the whole command */
891 Time_and_counter_tracker command_tracker;
892
893 /* TODO: This tracks time to read rows from the table */
894 Exec_time_tracker table_tracker;
895
896 virtual int print_explain(Explain_query *query, select_result_sink *output,
897 uint8 explain_flags, bool is_analyze);
898 virtual void print_explain_json(Explain_query *query, Json_writer *writer,
899 bool is_analyze);
900 };
901
902
903 /*
904 EXPLAIN data structure for an INSERT.
905
906 At the moment this doesn't do much as we don't really have any query plans
907 for INSERT statements.
908 */
909
910 class Explain_insert : public Explain_node
911 {
912 public:
913 Explain_insert(MEM_ROOT *root) :
914 Explain_node(root)
isVectorizableLoopPtrFactory(const DenseSet<Operation * > & parallelLoops,int fastestVaryingMemRefDimension)915 {}
916
__anonb1a5bee80402(Operation &forOp) 917 StringBuffer<64> table_name;
918
919 enum explain_node_type get_type() { return EXPLAIN_INSERT; }
920 int get_select_id() { return 1; /* always root */ }
921
922 int print_explain(Explain_query *query, select_result_sink *output,
923 uint8 explain_flags, bool is_analyze);
924 void print_explain_json(Explain_query *query, Json_writer *writer,
925 bool is_analyze);
926 };
927
928
929 /*
930 EXPLAIN data of a single-table DELETE.
931 */
932
933 class Explain_delete: public Explain_update
getVectorType(Type scalarTy,const VectorizationStrategy * strategy)934 {
935 public:
936 Explain_delete(MEM_ROOT *root, bool is_analyze) :
937 Explain_update(root, is_analyze)
938 {}
939
940 /*
941 TRUE means we're going to call handler->delete_all_rows() and not read any
942 rows.
943 */
944 bool deleting_all_rows;
945
946 virtual enum explain_node_type get_type() { return EXPLAIN_DELETE; }
947 virtual int get_select_id() { return 1; /* always root */ }
948
949 virtual int print_explain(Explain_query *query, select_result_sink *output,
950 uint8 explain_flags, bool is_analyze);
951 virtual void print_explain_json(Explain_query *query, Json_writer *writer,
952 bool is_analyze);
953 };
954
955
956 #endif //SQL_EXPLAIN_INCLUDED
957