Overview
Scenarios
Product Architecture
Instance Types
Compatibility Notes
Usage specification recommendations
sample_sst_blocks, but note that increasing the sampling rate will result in higher overhead for ANALYZE statements. Example:# Example 1: Missing Statisticstdsql> set global tdsql_get_index_stats_from_tdstore = on;Query OK, 0 rows affected (0.01 sec)tdsql> create table t1(a int, b int);Query OK, 0 rows affected (0.21 sec)tdsql> insert into t1 values(1,1),(2,2),(3,3);Query OK, 3 rows affected (0.01 sec)Records: 3 Duplicates: 0 Warnings: 0tdsql> analyze table t1;+---------+---------+----------+----------+| Table | Op | Msg_type | Msg_text |+---------+---------+----------+----------+| test.t1 | analyze | status | OK |+---------+---------+----------+----------+1 row in set (0.01 sec)# Column a lacks appropriate statistics, and the estimated row count of 1 is inaccuratetdsql> explain select * from t1 where a >= 2;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 33.33 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+1 row in set, 1 warning (0.00 sec)tdsql> analyze table t1 update histogram on a;+---------+-----------+----------+----------------------------------------------+| Table | Op | Msg_type | Msg_text |+---------+-----------+----------+----------------------------------------------+| test.t1 | histogram | status | Histogram statistics created for column 'a'. |+---------+-----------+----------+----------------------------------------------+1 row in set (0.01 sec)# After collecting a histogram for Column a, the estimated row count 2 is accuratetdsql> explain select * from t1 where a >= 2;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 3 | 66.67 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+1 row in set, 1 warning (0.00 sec)# Example 2: Expired Statisticstdsql> create table t1(a int, b int);Query OK, 0 rows affected (0.26 sec)tdsql> insert into t1-> with recursive nrows(n) as (-> select 1 union all-> select n+1 from nrows where n < 200-> )-> select n, n from nrows;Query OK, 200 rows affected (0.02 sec)Records: 200 Duplicates: 0 Warnings: 0tdsql> analyze table t1;+---------+---------+----------+----------+| Table | Op | Msg_type | Msg_text |+---------+---------+----------+----------+| test.t1 | analyze | status | OK |+---------+---------+----------+----------+1 row in set (0.01 sec)tdsql> explain select * from t1;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 200 | 100.00 | NULL |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+1 row in set, 1 warning (0.00 sec)tdsql> insert into t1-> with recursive nrows(n) as (-> select 1 union all-> select n+1 from nrows where n < 10-> )-> select n, n from nrows;Query OK, 10 rows affected (0.01 sec)Records: 10 Duplicates: 0 Warnings: 0# Inserting 10 new rows of data is insufficient to trigger auto analyze, and the statistics are outdated.tdsql> explain select * from t1;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 200 | 100.00 | NULL |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+1 row in set, 1 warning (0.00 sec)tdsql> analyze table t1;+---------+---------+----------+----------+| Table | Op | Msg_type | Msg_text |+---------+---------+----------+----------+| test.t1 | analyze | status | OK |+---------+---------+----------+----------+1 row in set (0.01 sec)tdsql> explain select * from t1;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+| 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 210 | 100.00 | NULL |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+1 row in set, 1 warning (0.00 sec)
tdsql> create table t1(a int, b int);Query OK, 0 rows affected (0.19 sec)tdsql> insert into t1 with recursive nrows(n) as ( select 1 union all select n+1 from nrows where n < 200 ) select n, n from nrows;Query OK, 200 rows affected (0.03 sec)Records: 200 Duplicates: 0 Warnings: 0tdsql> analyze table t1;+---------+---------+----------+----------+| Table | Op | Msg_type | Msg_text |+---------+---------+----------+----------+| test.t1 | analyze | status | OK |+---------+---------+----------+----------+1 row in set (0.01 sec)tdsql> create table t2(a int, b int);Query OK, 0 rows affected (0.20 sec)tdsql> insert into t2 values(1,1),(2,2),(3,3);Query OK, 3 rows affected (0.02 sec)Records: 3 Duplicates: 0 Warnings: 0tdsql> analyze table t2;+---------+---------+----------+----------+| Table | Op | Msg_type | Msg_text |+---------+---------+----------+----------+| test.t2 | analyze | status | OK |+---------+---------+----------+----------+1 row in set (0.01 sec)tdsql> explain format=tree select * from t1, t2 where t1.a = t2.a;+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+| EXPLAIN |+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -> Inner hash join (t1.a = t2.a) (cost=67.84 rows=60)-> Table scan on t1 (cost=2.33 rows=200)-> Hash-> Table scan on t2 (cost=2.84 rows=3)|+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set (0.00 sec)tdsql> alter table t1 add key(a);Query OK, 0 rows affected (0.30 sec)Records: 0 Duplicates: 0 Warnings: 0tdsql> analyze table t1;+---------+---------+----------+----------+| Table | Op | Msg_type | Msg_text |+---------+---------+----------+----------+| test.t1 | analyze | status | OK |+---------+---------+----------+----------+1 row in set (0.01 sec)# The join algorithm changed from hash join to bka.tdsql> explain format=tree select * from t1, t2 where t1.a = t2.a;+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| EXPLAIN |+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -> Batched key access inner join (cost=1.33 rows=3)-> Batch input rows-> Filter: (t2.a is not null) (cost=2.84 rows=3)-> Table scan on t2 (cost=2.84 rows=3)-> Multi-range index lookup on t1 using a (a=t2.a) (cost=0.28 rows=1)|+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set (0.02 sec)tdsql> alter table t1 alter index a invisible;Query OK, 0 rows affected (0.12 sec)Records: 0 Duplicates: 0 Warnings: 0# Index a is invisible, and the join algorithm reverts to hash join.tdsql> explain format=tree select * from t1, t2 where t1.a = t2.a;+------------------------------------------------------------------------------------------------------------------------------------------------------------------+| EXPLAIN |+------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -> Inner hash join (t1.a = t2.a) (cost=67.84 rows=3)-> Table scan on t1 (cost=1.70 rows=200)-> Hash-> Table scan on t2 (cost=2.84 rows=3)|+------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set (0.02 sec)
tdsql> create table t1(a int, b int);Query OK, 0 rows affected (0.19 sec)tdsql> insert into t1 with recursive nrows(n) as ( select 1 union all select n+1 from nrows where n < 200 ) select n, n from nrows;Query OK, 200 rows affected (0.02 sec)Records: 200 Duplicates: 0 Warnings: 0tdsql> analyze table t1 update histogram on a;+---------+-----------+----------+----------------------------------------------+| Table | Op | Msg_type | Msg_text |+---------+-----------+----------+----------------------------------------------+| test.t1 | histogram | status | Histogram statistics created for column 'a'. |+---------+-----------+----------+----------------------------------------------+1 row in set (0.02 sec)# Non-partitioned table scans the entire tabletdsql> explain select * from t1 where a <= 10;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| 1 | SIMPLE | t1 | NULL | ALL | NULL | NULL | NULL | NULL | 200 | 5.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+1 row in set, 1 warning (0.01 sec)tdsql> drop table t1;Query OK, 0 rows affected (0.11 sec)tdsql> create table t1(a int, b int) partition by range(a) (-> partition p0 values less than (51),-> partition p1 values less than (101),-> partition p2 values less than (151),-> partition p3 values less than (maxvalue));Query OK, 0 rows affected (0.22 sec)tdsql> insert into t1 with recursive nrows(n) as ( select 1 union all select n+1 from nrows where n < 200 ) select n, n from nrows;Query OK, 200 rows affected (0.04 sec)Records: 200 Duplicates: 0 Warnings: 0tdsql> analyze table t1;+---------+---------+----------+----------+| Table | Op | Msg_type | Msg_text |+---------+---------+----------+----------+| test.t1 | analyze | status | OK |+---------+---------+----------+----------+1 row in set (0.01 sec)tdsql> analyze table t1 update histogram on a;+---------+-----------+----------+----------------------------------------------+| Table | Op | Msg_type | Msg_text |+---------+-----------+----------+----------------------------------------------+| test.t1 | histogram | status | Histogram statistics created for column 'a'. |+---------+-----------+----------+----------------------------------------------+1 row in set (0.01 sec)# The partitioned table only needs to scan p0tdsql> explain select * from t1 where a <= 10;+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+| 1 | SIMPLE | t1 | p0 | ALL | NULL | NULL | NULL | NULL | 50 | 5.00 | Using where |+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+1 row in set, 1 warning (0.01 sec)
optimizer_prune_level and optimizer_search_depth, users can control the number of all candidate JOIN orders searched by the optimizer; if the slow query selects a poor JOIN order and it is discovered through Optimizer Trace that the optimizer did not search for the desired better JOIN order, consider adjusting these two parameters; note that a larger JOIN order search space implies higher optimizer overhead. For specific settings of these two parameters, refer to the MySQL documentation. Generally, these two values should remain at their default values;optimizer_switch or other system parameters: There may be optimization operations that can lead to better execution plans in some scenarios but worse ones in others. These operations typically correspond to a switch in optimizer_switch, such as the commonly used subquery_to_derived option, which controls whether to consider converting subqueries into derived tables before performing JOIN. This option is disabled by default, but enabling it can significantly improve query execution efficiency in certain queries. For more detailed optimizer_switch options, refer to the MySQL documentation; Example:tdsql> create table t1(a int, b int);Query OK, 0 rows affected (0.21 sec)tdsql> create table t2(a int, b int);Query OK, 0 rows affected (0.19 sec)# In the default execution plan, the subquery is executed using the EXISTS method, which scans t2 multiple times.tdsql> explain format=tree select * from t1 where t1.a > (select count(1) from t2 where t2.b = t1.b);+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| EXPLAIN |+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -> Filter: (t1.a > (select #2)) (cost=2.61 rows=1)-> Table scan on t1 (cost=2.61 rows=1)-> Select #2 (subquery in condition; dependent)-> Aggregate: count(1) (cost=2.84 rows=1)-> Filter: (t2.b = t1.b) (cost=2.61 rows=1)-> Table scan on t2 (cost=2.61 rows=1)|+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set, 1 warning (0.01 sec)tdsql> set optimizer_switch='subquery_to_derived=on';Query OK, 0 rows affected (0.00 sec)# After enabling the subquery_to_derived feature, t2 only needs to be scanned once, with intermediate results stored in the temporary table derived_1_2, which is then joined with t1.tdsql> explain format=tree select * from t1 where t1.a > (select count(1) from t2 where t2.b = t1.b);+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| EXPLAIN |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -> Filter: (t1.a > coalesce(derived_1_2.`count(1)`,0)) (cost=3.21 rows=1)-> Nested loop left join (cost=3.21 rows=1)-> Table scan on t1 (cost=2.61 rows=1)-> Index lookup on derived_1_2 using <auto_key0> (b=t1.b) (cost=0.70 rows=2)-> Materialize (cost=10.07..10.07 rows=1)-> Table scan on <temporary> (cost=5.12..5.12 rows=1)-> Aggregate using temporary table (cost=9.14..9.14 rows=1)-> Table scan on t2 (cost=2.61 rows=1)|+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set, 1 warning (0.00 sec)
# In the example above, optimizer_switch can be specified via hint, taking effect only on the single statement.tdsql> set optimizer_switch='subquery_to_derived=off';Query OK, 0 rows affected (0.00 sec)tdsql> explain format=tree select * from t1 where t1.a > (select count(1) from t2 where t2.b = t1.b);+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| EXPLAIN |+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -> Filter: (t1.a > (select #2)) (cost=2.61 rows=1)-> Table scan on t1 (cost=2.61 rows=1)-> Select #2 (subquery in condition; dependent)-> Aggregate: count(1) (cost=2.84 rows=1)-> Filter: (t2.b = t1.b) (cost=2.61 rows=1)-> Table scan on t2 (cost=2.61 rows=1)|+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set, 1 warning (0.00 sec)tdsql> explain format=tree select/*+set_var(optimizer_switch='subquery_to_derived=on')*/ * from t1 where t1.a > (select count(1) from t2 where t2.b = t1.b);+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| EXPLAIN |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -> Filter: (t1.a > coalesce(derived_1_2.`count(1)`,0)) (cost=3.21 rows=1)-> Nested loop left join (cost=3.21 rows=1)-> Table scan on t1 (cost=2.61 rows=1)-> Index lookup on derived_1_2 using <auto_key0> (b=t1.b) (cost=0.70 rows=2)-> Materialize (cost=10.07..10.07 rows=1)-> Table scan on <temporary> (cost=5.12..5.12 rows=1)-> Aggregate using temporary table (cost=9.14..9.14 rows=1)-> Table scan on t2 (cost=2.61 rows=1)|+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set, 1 warning (0.00 sec)# Create an outline rule for the hint of this statementtdsql> call dbms_admin.statement_outline_add_rule("test", "select/*+set_var(optimizer_switch='subquery_to_derived=on')*/ * from t1 where t1.a > (select count(1) from t2 where t2.b = t1.b)");+------+| ID |+------+| 1 |+------+1 row in set (0.01 sec)# Queries can now trigger the subquery_to_derived rewrite without requiring hintstdsql> explain format=tree select * from t1 where t1.a > (select count(1) from t2 where t2.b = t1.b);+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| EXPLAIN |+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+| -> Filter: (t1.a > coalesce(derived_1_2.`count(1)`,0)) (cost=3.21 rows=1)-> Nested loop left join (cost=3.21 rows=1)-> Table scan on t1 (cost=2.61 rows=1)-> Index lookup on derived_1_2 using <auto_key0> (b=t1.b) (cost=0.70 rows=2)-> Materialize (cost=10.07..10.07 rows=1)-> Table scan on <temporary> (cost=5.12..5.12 rows=1)-> Aggregate using temporary table (cost=9.14..9.14 rows=1)-> Table scan on t2 (cost=2.61 rows=1)|+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+1 row in set, 2 warnings (0.02 sec)# warnings will indicate that outline rules have been appliedtdsql> show warnings;+-------+------+---------------------------------------------------------------------------+| Level | Code | Message |+-------+------+---------------------------------------------------------------------------+| Note | 8579 | Statement outline rule 1 was applied, it may have changed the query plan. || Note | 1276 | Field or reference 'test.t1.b' of SELECT #2 was resolved in SELECT #1 |+-------+------+---------------------------------------------------------------------------+2 rows in set (0.01 sec)
피드백