Catalog

TIPS

This article is based on MySQL 8.0 To write , theoretical support MySQL 5.6 And higher .

OPTIMIZER_TRACE yes MySQL 5.6 A tracking feature introduced , It can track various decisions made by the optimizer ( For example, the method of accessing the table 、 Various overhead calculations 、 Various conversions, etc ), And record the tracking results to INFORMATION_SCHEMA.OPTIMIZER_TRACE In the table . This function is off by default , After opening , The following statements can be analyzed :

  • SELECT
  • INSERT
  • REPLACE
  • UPDATE
  • DELETE
  • EXPLAIN
  • SET
  • DECLARE
  • CASE
  • IF
  • RETURN
  • CALL

TIPS

Reference resources https://dev.mysql.com/doc/internals/en/system-variables-controlling-trace.html

  • optimizer_trace

    • optimizer_trace Main switch , The default value is :enabled=off,one_line=off
    • enabled: Open or not optimizer_trace;on Open for indication ,off Means closing .
    • one_line: Whether to open single line storage .on Open for indication ;off Means closing , Will use standard JSON Format storage . Set to on There will be good format , Set to off Can save some space .
  • optimizer_trace_features

    • control optimizer_trace What to track , The default value is :greedy_search=on,range_optimizer=on,dynamic_range=on,repeated_subselect=on , Indicates that all tracking items are turned on .
  • greedy_search: Whether to track greedy search , The greedy algorithm can be found in https://blog.csdn.net/weixin_42813521/article/details/105563103

    • range_optimizer: Whether to track the scope optimizer
  • dynamic_range: Whether to track dynamic range optimization

    • repeated_subselect: Whether to track subqueries , If I set it to off, Just follow the first one Item_subselect Implementation
  • See https://dev.mysql.com/doc/internals/en/optimizer-features-to-trace.html

  • optimizer_trace_limit: control optimizer_trace How many results to show , Default 1

  • optimizer_trace_max_mem_size:optimizer_trace Maximum memory allowed for stack information , Default 1048576

  • optimizer_trace_offset: The first thing to show optimizer trace The offset , Default -1.

  • end_markers_in_json: If JSON Large structure , It's hard to pair the right bracket with the left bracket . To help readers read , It can be set to on, This will add a comment around the right parenthesis , Default off.

    Reference resources : https://dev.mysql.com/doc/internals/en/end-markers-in-json-system-variable.html

TIPS

  • The above parameters are available SET Statement operation , for example , Use the following command to open OPTIMIZER TRACE

    1
    2
    >   SET OPTIMIZER_TRACE="enabled=on",END_MARKERS_IN_JSON=on;
    >

Also available SET GLOBAL Global on . But even if it turns on globally OPTIMIZER_TRACE, Every Session It can only track the statements it executes itself :

1
2
>   SET GLOBAL OPTIMIZER_TRACE="enabled=on",END_MARKERS_IN_JSON=on;
>
  • optimizer_trace_limit and optimizer_trace_offset These two parameters are often used together , for example :

    1
    2
    >   SET optimizer_trace_offset=<OFFSET>, optimizer_trace_limit=<LIMIT>
    >

These two parameters are used together , It's kind of similar MySQL Inside limit sentence .

By default , because optimizer_trace_offset=-1,optimizer_trace_limit=1, Record the last one SQL sentence , Display time , Every show 1 Data ;

If change to SET optimizer_trace_offset=-2, optimizer_trace_limit=1 , The next to last entry will be recorded SQL sentence ;

of optimizer_trace_offset 、optimizer_trace_limit For more details , May refer to https://dev.mysql.com/doc/internals/en/tuning-trace-purging.html

OPTIMIZER_TRACE Use

  • Turn on OPTIMIZER_TRACE function , And set the number of data entries to be displayed :

    1
    2
    SET OPTIMIZER_TRACE="enabled=on",END_MARKERS_IN_JSON=on;
    SET optimizer_trace_offset=-30, optimizer_trace_limit=30;
  • Send what you want to analyze SQL sentence , for example :

    1
    2
    3
    4
    select *
    from salaries
    where from_date = '1986-06-26'
    and to_date = '1987-06-26';
  • Use the following statements to analyze , The following results can be obtained :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
      mysql> SELECT * FROM INFORMATION_SCHEMA.OPTIMIZER_TRACE limit 30 \G;
    *************************** 1. row ***************************
    QUERY: select *
    from salaries
    where from_date = '1986-06-26'
    and to_date = '1987-06-26'
    TRACE: {
    "steps": [
    {
    "join_preparation": {
    "select#": 1,
    "steps": [
    {
    "expanded_query": "/* select#1 */ select `salaries`.`emp_no` AS `emp_no`,`salaries`.`salary` AS `salary`,`salaries`.`from_date` AS `from_date`,`salaries`.`to_date` AS `to_date` from `salaries` where ((`salaries`.`from_date` = '1986-06-26') and (`salaries`.`to_date` = '1987-06-26'))"
    }
    ] /* steps */
    } /* join_preparation */
    },
    {
    "join_optimization": {
    "select#": 1,
    "steps": [
    {
    "condition_processing": {
    "condition": "WHERE",
    "original_condition": "((`salaries`.`from_date` = '1986-06-26') and (`salaries`.`to_date` = '1987-06-26'))",
    "steps": [
    {
    "transformation": "equality_propagation",
    "resulting_condition": "(multiple equal('1986-06-26', `salaries`.`from_date`) and multiple equal('1987-06-26', `salaries`.`to_date`))"
    },
    {
    "transformation": "constant_propagation",
    "resulting_condition": "(multiple equal('1986-06-26', `salaries`.`from_date`) and multiple equal('1987-06-26', `salaries`.`to_date`))"
    },
    {
    "transformation": "trivial_condition_removal",
    "resulting_condition": "(multiple equal(DATE'1986-06-26', `salaries`.`from_date`) and multiple equal(DATE'1987-06-26', `salaries`.`to_date`))"
    }
    ] /* steps */
    } /* condition_processing */
    },
    {
    "substitute_generated_columns": {
    } /* substitute_generated_columns */
    },
    {
    "table_dependencies": [
    {
    "table": "`salaries`",
    "row_may_be_null": false,
    "map_bit": 0,
    "depends_on_map_bits": [
    ] /* depends_on_map_bits */
    }
    ] /* table_dependencies */
    },
    {
    "ref_optimizer_key_uses": [
    {
    "table": "`salaries`",
    "field": "from_date",
    "equals": "DATE'1986-06-26'",
    "null_rejecting": false
    },
    {
    "table": "`salaries`",
    "field": "to_date",
    "equals": "DATE'1987-06-26'",
    "null_rejecting": false
    }
    ] /* ref_optimizer_key_uses */
    },
    {
    "rows_estimation": [
    {
    "table": "`salaries`",
    "range_analysis": {
    "table_scan": {
    "rows": 2838216,
    "cost": 286799
    } /* table_scan */,
    "potential_range_indexes": [
    {
    "index": "PRIMARY",
    "usable": false,
    "cause": "not_applicable"
    },
    {
    "index": "salaries_from_date_to_date_index",
    "usable": true,
    "key_parts": [
    "from_date",
    "to_date",
    "emp_no"
    ] /* key_parts */
    }
    ] /* potential_range_indexes */,
    "setup_range_conditions": [
    ] /* setup_range_conditions */,
    "group_index_range": {
    "chosen": false,
    "cause": "not_group_by_or_distinct"
    } /* group_index_range */,
    "skip_scan_range": {
    "potential_skip_scan_indexes": [
    {
    "index": "salaries_from_date_to_date_index",
    "usable": false,
    "cause": "query_references_nonkey_column"
    }
    ] /* potential_skip_scan_indexes */
    } /* skip_scan_range */,
    "analyzing_range_alternatives": {
    "range_scan_alternatives": [
    {
    "index": "salaries_from_date_to_date_index",
    "ranges": [
    "0xda840f <= from_date <= 0xda840f AND 0xda860f <= to_date <= 0xda860f"
    ] /* ranges */,
    "index_dives_for_eq_ranges": true,
    "rowid_ordered": true,
    "using_mrr": false,
    "index_only": false,
    "rows": 86,
    "cost": 50.909,
    "chosen": true
    }
    ] /* range_scan_alternatives */,
    "analyzing_roworder_intersect": {
    "usable": false,
    "cause": "too_few_roworder_scans"
    } /* analyzing_roworder_intersect */
    } /* analyzing_range_alternatives */,
    "chosen_range_access_summary": {
    "range_access_plan": {
    "type": "range_scan",
    "index": "salaries_from_date_to_date_index",
    "rows": 86,
    "ranges": [
    "0xda840f <= from_date <= 0xda840f AND 0xda860f <= to_date <= 0xda860f"
    ] /* ranges */
    } /* range_access_plan */,
    "rows_for_plan": 86,
    "cost_for_plan": 50.909,
    "chosen": true
    } /* chosen_range_access_summary */
    } /* range_analysis */
    }
    ] /* rows_estimation */
    },
    {
    "considered_execution_plans": [
    {
    "plan_prefix": [
    ] /* plan_prefix */,
    "table": "`salaries`",
    "best_access_path": {
    "considered_access_paths": [
    {
    "access_type": "ref",
    "index": "salaries_from_date_to_date_index",
    "rows": 86,
    "cost": 50.412,
    "chosen": true
    },
    {
    "access_type": "range",
    "range_details": {
    "used_index": "salaries_from_date_to_date_index"
    } /* range_details */,
    "chosen": false,
    "cause": "heuristic_index_cheaper"
    }
    ] /* considered_access_paths */
    } /* best_access_path */,
    "condition_filtering_pct": 100,
    "rows_for_plan": 86,
    "cost_for_plan": 50.412,
    "chosen": true
    }
    ] /* considered_execution_plans */
    },
    {
    "attaching_conditions_to_tables": {
    "original_condition": "((`salaries`.`to_date` = DATE'1987-06-26') and (`salaries`.`from_date` = DATE'1986-06-26'))",
    "attached_conditions_computation": [
    ] /* attached_conditions_computation */,
    "attached_conditions_summary": [
    {
    "table": "`salaries`",
    "attached": "((`salaries`.`to_date` = DATE'1987-06-26') and (`salaries`.`from_date` = DATE'1986-06-26'))"
    }
    ] /* attached_conditions_summary */
    } /* attaching_conditions_to_tables */
    },
    {
    "finalizing_table_conditions": [
    {
    "table": "`salaries`",
    "original_table_condition": "((`salaries`.`to_date` = DATE'1987-06-26') and (`salaries`.`from_date` = DATE'1986-06-26'))",
    "final_table_condition ": null
    }
    ] /* finalizing_table_conditions */
    },
    {
    "refine_plan": [
    {
    "table": "`salaries`"
    }
    ] /* refine_plan */
    }
    ] /* steps */
    } /* join_optimization */
    },
    {
    "join_execution": {
    "select#": 1,
    "steps": [
    ] /* steps */
    } /* join_execution */
    }
    ] /* steps */
    }
    MISSING_BYTES_BEYOND_MAX_MEM_SIZE: 0
    INSUFFICIENT_PRIVILEGES: 0
    1 row in set (0.00 sec)
  • Analysis completed , close OPTIMIZER_TRACE

    1
    SET optimizer_trace="enabled=off";

OPTIMIZER_TRACE Result analysis

From the above results we can see that ,OPTIMIZER_TRACE There are four fields :

  • QUERY: Query statement
  • TRACE:QUERY The tracking information of the statement corresponding to the field
  • MISSING_BYTES_BEYOND_MAX_MEM_SIZE: When the tracking information is too long , The number of bytes of truncated trace information .
  • INSUFFICIENT_PRIVILEGES: Whether the user executing the trace statement has permission to view the object . When you don't have permission , The column information is 1 And TRACE Field is empty , In general, when calling with SQL SECURITY DEFINER In the case of stored procedures , This problem will arise .

TIPS

Reference resources : https://dev.mysql.com/doc/refman/8.0/en/optimizer-trace-table.html

The bottom line is this TRACE The contents of the field . Let's analyze it paragraph by paragraph :

join_preparation

join_preparation The paragraph shows the execution of the preparation phase .

1
2
3
4
5
6
7
8
9
10
11
12
13
{
"join_preparation": {
"select#": 1,
"steps": [
{
-- Compare the original sentence , You can know , This step has done a format .
"expanded_query": "/* select#1 */ select `salaries`.`emp_no` AS `emp_no`,`salaries`.`salary` AS `salary`,`salaries`.`from_date` AS `from_date`,`salaries`.`to_date` AS `to_date` from `salaries` where ((`salaries`.`from_date` = '1986-06-26') and (`salaries`.`to_date` = '1987-06-26'))"
}
]
/* steps */
}
/* join_preparation */
}

join_optimization

join_optimization It shows the execution process of the optimization phase , Is to analyze the OPTIMIZER TRACE Key points of . It's super long , And there are many steps , You might as well follow the steps to analyze :

condition_processing

This section is used for conditional processing , Mainly for WHERE Conditions are optimized .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"condition_processing": {
"condition": "WHERE",
"original_condition": "((`salaries`.`from_date` = '1986-06-26') and (`salaries`.`to_date` = '1987-06-26'))",
"steps": [
{
"transformation": "equality_propagation",
"resulting_condition": "(multiple equal('1986-06-26', `salaries`.`from_date`) and multiple equal('1987-06-26', `salaries`.`to_date`))"
},
{
"transformation": "constant_propagation",
"resulting_condition": "(multiple equal('1986-06-26', `salaries`.`from_date`) and multiple equal('1987-06-26', `salaries`.`to_date`))"
},
{
"transformation": "trivial_condition_removal",
"resulting_condition": "(multiple equal(DATE'1986-06-26', `salaries`.`from_date`) and multiple equal(DATE'1987-06-26', `salaries`.`to_date`))"
}
] /* steps */
} /* condition_processing */

among :

  • condition: Optimize object types .WHERE A conditional sentence or HAVING Conditional sentence
  • original_condition: The original statement before optimization
  • steps: It mainly includes three steps , Namely quality_propagation( Equivalent conditional sentence conversion ),constant_propagation( Constant conditional sentence conversion ),trivial_condition_removal( Invalid condition removed conversion )
    • transformation: Transformational sentences
    • resulting_condition: The result of the transformation is output

substitute_generated_columns

substitute_generated_columns Used to replace the virtual generated column

1
2
"substitute_generated_columns": {
} /* substitute_generated_columns */

table_dependencies

Analyze the dependencies between tables

1
2
3
4
5
6
7
8
9
10
11
{
"table_dependencies": [
{
"table": "`salaries`",
"row_may_be_null": false,
"map_bit": 0,
"depends_on_map_bits": [
] /* depends_on_map_bits */
}
] /* table_dependencies */
}

among :

  • table: Table names involved , If there are aliases , It will also show
  • row_may_be_null: Is it possible for NULL, Here means JOIN After the operation , This may not be the data in the table NULL. If you use LEFT JOIN, On the last table row_may_be_null Will be displayed as true
  • map_bit: The mapping number of the table , from 0 Began to increase
  • depends_on_map_bits: Dependency mapping table . Mainly when using STRAIGHT_JOIN Forcibly control the connection order or LEFT JOIN/RIGHT JOIN When there is a difference in order , Will be in depends_on_map_bits Showing the front table in map_bit value .

ref_optimizer_key_uses

List all available ref Index of type . If multiple parts of a composite index are used ( For example, in this case , Yes index(from_date, to_date) Multi column index of ), Will be in ref_optimizer_key_uses Several elements are listed below , Each element will list ref The index used and the corresponding value .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"ref_optimizer_key_uses": [
{
"table": "`salaries`",
"field": "from_date",
"equals": "DATE'1986-06-26'",
"null_rejecting": false
},
{
"table": "`salaries`",
"field": "to_date",
"equals": "DATE'1987-06-26'",
"null_rejecting": false
}
] /* ref_optimizer_key_uses */
}

rows_estimation

seeing the name of a thing one thinks of its function , Used to estimate the number of records that need to be scanned .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
{
"rows_estimation": [
{
"table": "`salaries`",
"range_analysis": {
"table_scan": {
"rows": 2838216,
"cost": 286799
} /* table_scan */,
"potential_range_indexes": [
{
"index": "PRIMARY",
"usable": false,
"cause": "not_applicable"
},
{
"index": "salaries_from_date_to_date_index",
"usable": true,
"key_parts": [
"from_date",
"to_date",
"emp_no"
] /* key_parts */
}
] /* potential_range_indexes */,
"setup_range_conditions": [
] /* setup_range_conditions */,
"group_index_range": {
"chosen": false,
"cause": "not_group_by_or_distinct"
} /* group_index_range */,
"skip_scan_range": {
"potential_skip_scan_indexes": [
{
"index": "salaries_from_date_to_date_index",
"usable": false,
"cause": "query_references_nonkey_column"
}
] /* potential_skip_scan_indexes */
} /* skip_scan_range */,
"analyzing_range_alternatives": {
"range_scan_alternatives": [
{
"index": "salaries_from_date_to_date_index",
"ranges": [
"0xda840f <= from_date <= 0xda840f AND 0xda860f <= to_date <= 0xda860f"
] /* ranges */,
"index_dives_for_eq_ranges": true,
"rowid_ordered": true,
"using_mrr": false,
"index_only": false,
"rows": 86,
"cost": 50.909,
"chosen": true
}
] /* range_scan_alternatives */,
"analyzing_roworder_intersect": {
"usable": false,
"cause": "too_few_roworder_scans"
} /* analyzing_roworder_intersect */
} /* analyzing_range_alternatives */,
"chosen_range_access_summary": {
"range_access_plan": {
"type": "range_scan",
"index": "salaries_from_date_to_date_index",
"rows": 86,
"ranges": [
"0xda840f <= from_date <= 0xda840f AND 0xda860f <= to_date <= 0xda860f"
] /* ranges */
} /* range_access_plan */,
"rows_for_plan": 86,
"cost_for_plan": 50.909,
"chosen": true
} /* chosen_range_access_summary */
} /* range_analysis */
}
] /* rows_estimation */
}

among :

  • table: Table name
  • range_analysis:

    • table_scan: If it's a full table scan , How many lines need to be scanned (row,2838216), And the cost of it (cost,286799)

    • potential_range_indexes: List all indexes in the table and analyze whether they are available . If not available , It lists the reasons for the unavailability ; If available, lists the available fields in the index ;

    • setup_range_conditions: If there's a pushdown condition , Then query with conditional consideration range

    • group_index_range: When using the GROUP BY or DISTINCT when , Is there a suitable index available . When not used GROUP BY or DISTINCT when , Will be displayed chosen=false, cause=not_group_by_or_distinct; If used GROUP BY or DISTINCT, But when querying multiple tables , Will be displayed chosen=false,cause =not_single_table. In other cases, an attempt is made to analyze the available indexes (potential_group_range_indexes) And calculate the number of scanning lines and the cost

    • skip_scan_range: Have you used skip scan

      TIPS

      skip_scan_range yes MySQL 8.0 New features , Please refer to https://blog.csdn.net/weixin_43970890/article/details/89494915

    • analyzing_range_alternatives: Analyze the cost of using each index

      • range_scan_alternatives:range Scanning analysis
        • index: Index name
        • ranges:range Range of scanning conditions
        • index_dives_for_eq_ranges: Have you used index dive, The value will be set by the parameter eq_range_index_dive_limit Variable value influence .
        • rowid_ordered: The range Whether the result set of the scan is based on PK Value to sort
        • using_mrr: Have you used mrr
        • index_only: Indicates whether the overlay index is used
        • rows: Number of lines scanned
        • cost: The cost of using the index
        • chosen: Indicates whether the index is used
      • analyzing_roworder_intersect: Analyze whether index merging is used (index merge), If not used , Will be in cause Why ; If index merging is used , The cost of index merging is shown in this section .
    • chosen_range_access_summary: In the previous step, we analyzed the methods and costs of using various indexes , After getting some intermediate results , stay summary The stage summarizes the intermediate results of the previous stage to confirm the final plan

      • range_access_plan:range Scan the final selected execution plan .
        • type: Show the execution plan type, If index merging is used , Is displayed index_roworder_intersect
        • index: Index name
        • rows: Number of lines scanned
        • ranges:range Range of scanning conditions
      • rows_for_plan: The number of scan lines for this execution plan
      • cost_for_plan: The implementation cost of the implementation plan
      • chosen: Whether to select the execution plan

considered_execution_plans

Responsible for comparing the cost of each feasible plan , And choose the relatively optimal execution plan .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
{
"considered_execution_plans": [
{
"plan_prefix": [
] /* plan_prefix */,
"table": "`salaries`",
"best_access_path": {
"considered_access_paths": [
{
"access_type": "ref",
"index": "salaries_from_date_to_date_index",
"rows": 86,
"cost": 50.412,
"chosen": true
},
{
"access_type": "range",
"range_details": {
"used_index": "salaries_from_date_to_date_index"
} /* range_details */,
"chosen": false,
"cause": "heuristic_index_cheaper"
}
] /* considered_access_paths */
} /* best_access_path */,
"condition_filtering_pct": 100,
"rows_for_plan": 86,
"cost_for_plan": 50.412,
"chosen": true
}
] /* considered_execution_plans */
}

among :

  • plan_prefix: Front end execution plan for the current plan .
  • table: Table names involved , If there are aliases , It will also show
  • best_access_path: by force of contrast considered_access_paths, Choose an optimal access path
    • considered_access_paths: Currently considered access path
      • access_type: How to use the index , May refer to explain Medium type Field
      • index: Indexes
      • rows: Row number
      • cost: expenses
      • chosen: Whether to choose this execution path
  • condition_filtering_pct: Be similar to explain Of filtered Column , It's an estimate
  • rows_for_plan: The final number of scan lines in the execution plan , from considered_access_paths.rows X condition_filtering_pct Obtained by calculation .
  • cost_for_plan: The cost of implementing the plan , from considered_access_paths.cost Add to get
  • chosen: Whether the execution plan has been selected

attaching_conditions_to_tables

be based on considered_execution_plans The execution plan selected in , Transform the original where Conditions , And add appropriate additional conditions to the table , In order to facilitate the filtering of single table data .

TIPS

  • This part of the condition is added mainly for the convenience of ICP( Push... Under index conditions ), but ICP Whether it is opened or not does not affect the construction of this part of the content .
  • ICP Reference documents :https://www.cnblogs.com/Terry-Wu/p/9273177.html
1
2
3
4
5
6
7
8
9
10
11
12
13
{
"attaching_conditions_to_tables": {
"original_condition": "((`salaries`.`to_date` = DATE'1987-06-26') and (`salaries`.`from_date` = DATE'1986-06-26'))",
"attached_conditions_computation": [
] /* attached_conditions_computation */,
"attached_conditions_summary": [
{
"table": "`salaries`",
"attached": "((`salaries`.`to_date` = DATE'1987-06-26') and (`salaries`.`from_date` = DATE'1986-06-26'))"
}
] /* attached_conditions_summary */
} /* attaching_conditions_to_tables */
}

among :

  • original_condition: The original conditional statement
  • attached_conditions_computation: Use a heuristic algorithm to calculate the used index , If the access type of the used index is ref, It is used for calculation range Can I use more columns in the composite index , If possible , Then use range Mode substitution ref.
  • attached_conditions_summary: Add up the situation after
    • table: Table name
    • attached: The additional condition or the condition in the original sentence that can be directly pushed down to the single table filter .

finalizing_table_conditions

The final 、 Optimized table conditions .

1
2
3
4
5
6
7
8
9
{
"finalizing_table_conditions": [
{
"table": "`salaries`",
"original_table_condition": "((`salaries`.`to_date` = DATE'1987-06-26') and (`salaries`.`from_date` = DATE'1986-06-26'))",
"final_table_condition ": null
}
] /* finalizing_table_conditions */
}

refine_plan

Improve the implementation plan :

1
2
3
4
5
6
7
{
"refine_plan": [
{
"table": "`salaries`"
}
] /* refine_plan */
}

among :

  • table: Table name and alias

join_execution

join_execution The paragraph shows the execution process of the execution phase .

1
2
3
4
5
"join_execution": {
"select#": 1,
"steps": [
] /* steps */
}

Reference documents

Related articles