053、查询优化之执行计划

执行计划的查看

使用EXPLAIN/DESC查看执行计划

insert into trips(client_id,driver_id,city_id,status,request_at) select  client_id,driver_id,city_id,status,request_at from trips
mysql> explain select count(*) from Trips where request_at BETWEEN '2011-01-01' and  '2032-01-01';
+------------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------------------+
| id                           | estRows  | task      | access object | operator info                                                                                                |
+------------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------------------+
| StreamAgg_20                 | 1.00     | root      |               | funcs:count(Column#9)->Column#7                                                                              |
| └─TableReader_21             | 1.00     | root      |               | data:StreamAgg_9                                                                                             |
|   └─StreamAgg_9              | 1.00     | cop[tikv] |               | funcs:count(1)->Column#9                                                                                     |
|     └─Selection_19           | 40960.00 | cop[tikv] |               | ge(test.trips.request_at, 2011-01-01 00:00:00.000000), le(test.trips.request_at, 2032-01-01 00:00:00.000000) |
|       └─TableFullScan_18     | 40960.00 | cop[tikv] | table:Trips   | keep order:false                                                                                             |
+------------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

EXPLAIN 的输出

  • id: 算子的ID。是算子在整个执行计划中唯一的标识,从上到下,从右至左
  • estRows: 估算返回的行数,算子语句将会输出的数据条数
  • task: 算子的种类
    • root: TiDB执行的
    • cop[tikv]: 下推到tikv上执行的
  • access object: 访问的对象,例如索引或者表或者分区
  • operator info : 算子详细信息

EXPLAIN ANALYZE的输出

EXPLAIN ANALYZE 会执行对应的SQL语句,记录其运行的信息,并且和执行计划一起返回。并且它会多少消耗内存和磁盘的信息

  • memory : 算子占用内存空间的阿晓
  • disk : 占用磁盘空间的大小
mysql> explain analyze select count(*) from Trips where request_at BETWEEN '2011-01-01' and  '2032-01-01';
+------------------------------+----------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+-----------+------+
| id                           | estRows  | actRows | task      | access object | execution info                                                                                                                      | operator info                                                                                                | memory    | disk |
+------------------------------+----------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+-----------+------+
| StreamAgg_20                 | 1.00     | 1       | root      |               | time:790.6µs, loops:2                                                                                                               | funcs:count(Column#9)->Column#7                                                                              | 388 Bytes | N/A  |
| └─TableReader_21             | 1.00     | 1       | root      |               | time:784.5µs, loops:2, cop_task: {num: 1, max: 693.6µs, proc_keys: 0, rpc_num: 1, rpc_time: 663.4µs, copr_cache_hit_ratio: 1.00}    | data:StreamAgg_9                                                                                             | 221 Bytes | N/A  |
|   └─StreamAgg_9              | 1.00     | 1       | cop[tikv] |               | tikv_task:{time:31ms, loops:41}                                                                                                     | funcs:count(1)->Column#9                                                                                     | N/A       | N/A  |
|     └─Selection_19           | 40960.00 | 40960   | cop[tikv] |               | tikv_task:{time:31ms, loops:41}                                                                                                     | ge(test.trips.request_at, 2011-01-01 00:00:00.000000), le(test.trips.request_at, 2032-01-01 00:00:00.000000) | N/A       | N/A  |
|       └─TableFullScan_18     | 40960.00 | 40960   | cop[tikv] | table:Trips   | tikv_task:{time:27ms, loops:41}                                                                                                     | keep order:false                                                                                             | N/A       | N/A  |
+------------------------------+----------+---------+-----------+---------------+-------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+-----------+------+
5 rows in set (0.00 sec)

顺序查看

id的顺序顺序查看技巧:由上至下,从右向左,并列的上边先执行。
在这里插入图片描述
18和37 是并列, 向上的先执行 16-》17-》18-》36-》37-》27-》13

管理执行计划

优化器 Hint

  • 通过/*+ … */ 注释的行为跟在select、update、或delete后面
  • Hint 不区分大小写
  • 多个不同的Hint需要使用逗号隔开

在这里插入图片描述

绑定执行计划(SPM)

  • 创建绑定
create binding for 									-- 创建绑定的关键字
select * from t where a> 1							---被绑定的SQL语句
using
select * from t use index(idx) where a > 2;			---期望替换的带有hint的语句
  • 查看绑定
show [global|session] bindings 				--查看绑定的关键字
select * from t where a > 1					--被绑定的SQL
  • 删除绑定
drop[global|session] binding 				--删除绑定的关键字
select * from t where a > 1					--被绑定的SQL

执行计划中的算子

  • 执行计划中的算子
    • 汇聚数据类算子
      • hash aggregate
      • stream aggregate
    • 扫描数据类算子
      • Point Get/Batch Point Get
      • Table Reader
      • Index Reader
      • Index Lookup Reader
      • Index Merge Reader
    • 表连接类算子
      • Hash Join算子
      • Merge Join 算子
      • Index Join 算子

汇聚类算子 - Hash Aggregate

  1. 阻塞时执行,需要整个计算完成才可以对上层算子输出结果
  2. 不需要提前排序
  3. 支持并行
  4. 内存占用较大
  • Hash Aggregate 示例
mysql> explain select /*+ hash_agg() */ count(*) from planets;
+---------------------------+---------+-----------+---------------------------------+-----------------------------------+
| id                        | estRows | task      | access object                   | operator info                     |
+---------------------------+---------+-----------+---------------------------------+-----------------------------------+
| HashAgg_10                | 1.00    | root      |                                 | funcs:count(Column#27)->Column#25 |
| └─IndexReader_11          | 1.00    | root      |                                 | index:HashAgg_5                   |
|   └─HashAgg_5             | 1.00    | cop[tikv] |                                 | funcs:count(1)->Column#27         |
|     └─IndexFullScan_9     | 10.00   | cop[tikv] | table:planets, index:name(name) | keep order:false, stats:pseudo    |
+---------------------------+---------+-----------+---------------------------------+-----------------------------------+
4 rows in set (0.00 sec)
  • Hash Aggregate工作流程
    例如将部门映射成一张hash表,通过hash函数取得对应相同值,进行分析
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    优点: 不需要预先排序,因为它是通过hash函数取得对应的值 然后进行统计分析
    缺点: 如果只有一个线程处理,后面的内容需要一行一行的处理,会造成阻塞,结果在最后得出

  • 优化措施
    优化措施,它会分多个线程,对hash值进行聚合
    在这里插入图片描述
    实际是两张临时表 来扫描两个区域,如果有N个线程,那就N张临时表
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

汇聚类算子 - Stream Aggregate

  1. 非阻塞式执行,对于类似limit操作友好
  2. 内存占用小
  3. 单线程执行
  • Stream Aggregate 示例
mysql> explain select /*+ stream_agg() */ count(*) from planets;
+----------------------------+---------+-----------+---------------------------------+-----------------------------------+
| id                         | estRows | task      | access object                   | operator info                     |
+----------------------------+---------+-----------+---------------------------------+-----------------------------------+
| StreamAgg_15               | 1.00    | root      |                                 | funcs:count(Column#27)->Column#25 |
| └─IndexReader_16           | 1.00    | root      |                                 | index:StreamAgg_8                 |
|   └─StreamAgg_8            | 1.00    | cop[tikv] |                                 | funcs:count(1)->Column#27         |
|     └─IndexFullScan_14     | 10.00   | cop[tikv] | table:planets, index:name(name) | keep order:false, stats:pseudo    |
+----------------------------+---------+-----------+---------------------------------+-----------------------------------+
4 rows in set (0.00 sec)
  • Stream Aggregate工作流程
    先排序在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    优点:非阻塞,计算出一行结果便可以返回
    缺点: 需要预先排序

扫描类算子-PointGet

  • 示例
mysql> explain select * from planets where id = 2;
+-------------+---------+------+---------------+---------------+
| id          | estRows | task | access object | operator info |
+-------------+---------+------+---------------+---------------+
| Point_Get_1 | 1.00    | root | table:planets | handle:2      |
+-------------+---------+------+---------------+---------------+
1 row in set (0.00 sec)
mysql> explain select * from planets where id in (2,3,4,5);
+-------------------+---------+------+---------------+------------------------------------------------+
| id                | estRows | task | access object | operator info                                  |
+-------------------+---------+------+---------------+------------------------------------------------+
| Batch_Point_Get_1 | 4.00    | root | table:planets | handle:[2 3 4 5], keep order:false, desc:false |
+-------------------+---------+------+---------------+------------------------------------------------+
1 row in set (0.00 sec)

扫描类算子-indexReader

indexReader:不用回表,从索引上取得数据

mysql> explain select count(*) from planets ;
+----------------------------+---------+-----------+---------------------------------+-----------------------------------+
| id                         | estRows | task      | access object                   | operator info                     |
+----------------------------+---------+-----------+---------------------------------+-----------------------------------+
| StreamAgg_20               | 1.00    | root      |                                 | funcs:count(Column#30)->Column#25 |
| └─IndexReader_21           | 1.00    | root      |                                 | index:StreamAgg_8                 |
|   └─StreamAgg_8            | 1.00    | cop[tikv] |                                 | funcs:count(1)->Column#30         |
|     └─IndexFullScan_19     | 10.00   | cop[tikv] | table:planets, index:name(name) | keep order:false, stats:pseudo    |
+----------------------------+---------+-----------+---------------------------------+-----------------------------------+
4 rows in set (0.01 sec)

扫描类算子-indexLookup

index lookup: 走索引,但要回表

mysql> explain select * from planets use index (name);
+-------------------------------+---------+-----------+---------------------------------+--------------------------------+
| id                            | estRows | task      | access object                   | operator info                  |
+-------------------------------+---------+-----------+---------------------------------+--------------------------------+
| IndexLookUp_6                 | 10.00   | root      |                                 |                                |
| ├─IndexFullScan_4(Build)      | 10.00   | cop[tikv] | table:planets, index:name(name) | keep order:false, stats:pseudo |
| └─TableRowIDScan_5(Probe)     | 10.00   | cop[tikv] | table:planets                   | keep order:false, stats:pseudo |
+-------------------------------+---------+-----------+---------------------------------+--------------------------------+
3 rows in set (0.00 sec)

扫描类算子-TableReader

没有索引,或者索引不合适,直接走表的数据

mysql> explain select * from  planets where mass>0.1;
+-------------------------+---------+-----------+---------------+--------------------------------+
| id                      | estRows | task      | access object | operator info                  |
+-------------------------+---------+-----------+---------------+--------------------------------+
| TableReader_7           | 3.33    | root      |               | data:Selection_6               |
| └─Selection_6           | 3.33    | cop[tikv] |               | gt(universe.planets.mass, 0.1) |
|   └─TableFullScan_5     | 10.00   | cop[tikv] | table:planets | keep order:false, stats:pseudo |
+-------------------------+---------+-----------+---------------+--------------------------------+
3 rows in set (0.00 sec)

扫描类算子-IndexMerge

当谓词条件中上有多个索引进行数据合并操作的时候

mysql> set @@tidb_enable_index_merge=1;
Query OK, 0 rows affected (0.00 sec)
mysql> explain select * from t use index(idx_a,idx_b) where a>1 or   b>1;

表连接类算子-HashJoin

hash join 通常对 没有索引,并且是等值查询

  • 示例
mysql> explain select /*+ hash_join(planets,stars) */ planets.mass from planets,stars where planets.sun_iid=stars.id ;
+-----------------------------+---------+-----------+-------------------------------+--------------------------------------------------------------------+
| id                          | estRows | task      | access object                 | operator info                                                      |
+-----------------------------+---------+-----------+-------------------------------+--------------------------------------------------------------------+
| HashJoin_16                 | 2.50    | root      |                               | inner join, equal:[eq(universe.planets.sun_id, universe.stars.id)] |
| ├─IndexReader_23(Build)     | 2.00    | root      |                               | index:IndexFullScan_22                                             |
| │ └─IndexFullScan_22        | 2.00    | cop[tikv] | table:stars, index:name(name) | keep order:false, stats:pseudo                                     |
| └─TableReader_19(Probe)     | 10.00   | root      |                               | data:TableFullScan_18                                              |
|   └─TableFullScan_18        | 10.00   | cop[tikv] | table:planets                 | keep order:false, stats:pseudo                                     |
+-----------------------------+---------+-----------+-------------------------------+--------------------------------------------------------------------+
5 rows in set (0.00 sec)
  • 原理
    两张表:country city
    假设通过对外表/小表/驱动表进行hash运算例如求模100建立一张hash表
    在这里插入图片描述
    内表在匹配的的时候,例如101这条记录通过求模得到1,匹配hash表当中的2行记录,这个时候只需要扫描2次即可。
    在这里插入图片描述

  • 优化措施:并行
    将city分成几个区块,然后多个线程并行处理
    在这里插入图片描述

表连接类算子-Merge Join

  • 示例
    在这里插入图片描述
    注意:operator info中可以查查看到排序的动作。

  • 原理
    国家和城市两张表在这里插入图片描述
    这种算法下,会先进行排序
    在这里插入图片描述
    匹配的时候,因为数据经过排序,一旦匹配到,后续的数据就不需要在扫描匹配了。它的效率不如hashJoin,但比它节约内存
    在这里插入图片描述
    在这里插入图片描述

表连接类算子-Index Join

  • 示例
mysql> explain select /*+ inl_join(planets,stars) */  planets.name,stars.name from planets,stars where planets.sun_id=stars.id;
+-----------------------------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id                          | estRows | task      | access object | operator info                                                                                                                                              |
+-----------------------------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| IndexJoin_11                | 2.50    | root      |               | inner join, inner:TableReader_8, outer key:universe.planets.sun_id, inner key:universe.stars.id, equal cond:eq(universe.planets.sun_id, universe.stars.id) |
| ├─TableReader_17(Build)     | 10.00   | root      |               | data:TableFullScan_16                                                                                                                                      |
| │ └─TableFullScan_16        | 10.00   | cop[tikv] | table:planets | keep order:false, stats:pseudo                                                                                                                             |
| └─TableReader_8(Probe)      | 0.25    | root      |               | data:TableRangeScan_7                                                                                                                                      |
|   └─TableRangeScan_7        | 0.25    | cop[tikv] | table:stars   | range: decided by [universe.planets.sun_id], keep order:false, stats:pseudo                                                                                |
+-----------------------------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

表连接类算子-IndexHashJoin

相较于hash join 不同的地方是,非驱动表 替换成了索引

mysql> explain select /*+ inl_hash_join(planets,stars) */  planets.name,stars.name from planets,stars where planets.sun_id=stars.id;
+-----------------------------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| id                          | estRows | task      | access object | operator info                                                                                                                                              |
+-----------------------------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
| IndexHashJoin_13            | 2.50    | root      |               | inner join, inner:TableReader_8, outer key:universe.planets.sun_id, inner key:universe.stars.id, equal cond:eq(universe.planets.sun_id, universe.stars.id) |
| ├─TableReader_17(Build)     | 10.00   | root      |               | data:TableFullScan_16                                                                                                                                      |
| │ └─TableFullScan_16        | 10.00   | cop[tikv] | table:planets | keep order:false, stats:pseudo                                                                                                                             |
| └─TableReader_8(Probe)      | 0.25    | root      |               | data:TableRangeScan_7                                                                                                                                      |
|   └─TableRangeScan_7        | 0.25    | cop[tikv] | table:stars   | range: decided by [universe.planets.sun_id], keep order:false, stats:pseudo                                                                                |
+-----------------------------+---------+-----------+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

表连接类算子-BatchedNestedLoopJoinBasedOnIndex

在这里插入图片描述
一条条的在分布式的TiKV中处理很慢,优化措施:

  1. 通过分布式的原生特性,可以并行多线程处理
  2. 每次处理不是一条条,而是多条,批量处理
    在这里插入图片描述

实验

查看执行计划

1、造数

mysql> create table t1(a int,b int);
Query OK, 0 rows affected (0.24 sec)

mysql> create table t2(a int ,b int, index idx(b));
Query OK, 0 rows affected (0.17 sec)

mysql> 

[root@tidb2 ~]# for i in `seq 10000`; do mysql -uroot -P4000 -h192.168.16.13 -pAa123ab! -e "insert into test.t1 values ($i,floor(rand()*10000000))"; done;

[root@tidb2 ~]# for i in `seq 10000`; do mysql -uroot -P4000 -h192.168.16.13 -pAa123ab! -e "insert into test.t2 values ($i,floor(rand()*10000000))"; done;

2、查看执行计划

mysql> explain select * from t1 where  t1.a < (select sum(t2.a) from t2 where t2.b=t1.b);
+----------------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------------------+
| id                               | estRows  | task      | access object | operator info                                                                                                |
+----------------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------------------+
| HashJoin_11                      | 10112.88 | root      |               | inner join, equal:[eq(test.t1.b, test.t2.b)], other cond:lt(cast(test.t1.a, decimal(20,0) BINARY), Column#7) |
| ├─HashAgg_18(Build)              | 10112.37 | root      |               | group by:Column#18, funcs:sum(Column#16)->Column#7, funcs:firstrow(Column#17)->test.t2.b                     |
| │ └─Projection_39                | 10114.00 | root      |               | cast(test.t2.a, decimal(10,0) BINARY)->Column#16, test.t2.b, test.t2.b                                       |
| │   └─TableReader_31             | 10114.00 | root      |               | data:Selection_30                                                                                            |
| │     └─Selection_30             | 10114.00 | cop[tikv] |               | not(isnull(test.t2.b))                                                                                       |
| │       └─TableFullScan_29       | 10114.00 | cop[tikv] | table:t2      | keep order:false                                                                                             |
| └─TableReader_15(Probe)          | 10112.88 | root      |               | data:Selection_14                                                                                            |
|   └─Selection_14                 | 10112.88 | cop[tikv] |               | not(isnull(test.t1.b))                                                                                       |
|     └─TableFullScan_13           | 10123.00 | cop[tikv] | table:t1      | keep order:false                                                                                             |
+----------------------------------+----------+-----------+---------------+--------------------------------------------------------------------------------------------------------------+
9 rows in set (0.01 sec)

3、执行并查看执行计划

mysql> explain analyze select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1.b);
+----------------------------------+----------+---------+-----------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+----------+---------+
| id                               | estRows  | actRows | task      | access object | execution info                                                                                                                                                                                                                                                                                                                                                        | operator info                                                                                                | memory   | disk    |
+----------------------------------+----------+---------+-----------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+----------+---------+
| HashJoin_11                      | 10000.00 | 0       | root      |               | time:84ms, loops:1, build_hash_table:{total:79.9ms, fetch:74.9ms, build:5.04ms}, probe:{concurrency:5, total:414.7ms, max:83.3ms, probe:2.34ms, fetch:412.3ms}                                                                                                                                                                                                        | inner join, equal:[eq(test.t1.b, test.t2.b)], other cond:lt(cast(test.t1.a, decimal(20,0) BINARY), Column#7) | 1.07 MB  | 0 Bytes |
| ├─HashAgg_18(Build)              | 9995.00  | 9995    | root      |               | time:75.1ms, loops:12, partial_worker:{wall_time:67.869444ms, concurrency:5, task_num:10, tot_wait:210.402437ms, tot_exec:9.078728ms, tot_time:220.66839ms, max:45.617063ms, p95:45.617063ms}, final_worker:{wall_time:79.824609ms, concurrency:5, task_num:25, tot_wait:330.977695ms, tot_exec:44.187184ms, tot_time:375.177565ms, max:76.089309ms, p95:76.089309ms} | group by:Column#18, funcs:sum(Column#16)->Column#7, funcs:firstrow(Column#17)->test.t2.b                     | 3.80 MB  | N/A     |
| │ └─Projection_39                | 10000.00 | 10000   | root      |               | time:40.6ms, loops:11, Concurrency:5                                                                                                                                                                                                                                                                                                                                  | cast(test.t2.a, decimal(10,0) BINARY)->Column#16, test.t2.b, test.t2.b                                       | 189.1 KB | N/A     |
| │   └─TableReader_31             | 10000.00 | 10000   | root      |               | time:32.4ms, loops:11, cop_task: {num: 1, max: 32.2ms, proc_keys: 10000, tot_proc: 9ms, tot_wait: 10ms, rpc_num: 1, rpc_time: 32.2ms, copr_cache_hit_ratio: 0.00}                                                                                                                                                                                                     | data:Selection_30                                                                                            | 156.8 KB | N/A     |
| │     └─Selection_30             | 10000.00 | 10000   | cop[tikv] |               | tikv_task:{time:7ms, loops:14}, scan_detail: {total_process_keys: 10000, total_process_keys_size: 449822, total_keys: 10001, rocksdb: {delete_skipped_count: 0, key_skipped_count: 10000, block: {cache_hit_count: 1, read_count: 0, read_byte: 0 Bytes}}}                                                                                                            | not(isnull(test.t2.b))                                                                                       | N/A      | N/A     |
| │       └─TableFullScan_29       | 10000.00 | 10000   | cop[tikv] | table:t2      | tikv_task:{time:7ms, loops:14}                                                                                                                                                                                                                                                                                                                                        | keep order:false                                                                                             | N/A      | N/A     |
| └─TableReader_15(Probe)          | 10000.00 | 10000   | root      |               | time:80.5ms, loops:11, cop_task: {num: 1, max: 80.5ms, proc_keys: 10000, tot_proc: 53ms, rpc_num: 1, rpc_time: 80.5ms, copr_cache_hit_ratio: 0.00}                                                                                                                                                                                                                    | data:Selection_14                                                                                            | 156.8 KB | N/A     |
|   └─Selection_14                 | 10000.00 | 10000   | cop[tikv] |               | tikv_task:{time:53ms, loops:14}, scan_detail: {total_process_keys: 10000, total_process_keys_size: 449806, total_keys: 25563, rocksdb: {delete_skipped_count: 7781, key_skipped_count: 33343, block: {cache_hit_count: 9, read_count: 0, read_byte: 0 Bytes}}}                                                                                                        | not(isnull(test.t1.b))                                                                                       | N/A      | N/A     |
|     └─TableFullScan_13           | 10000.00 | 10000   | cop[tikv] | table:t1      | tikv_task:{time:36ms, loops:14}                                                                                                                                                                                                                                                                                                                                       | keep order:false                                                                                             | N/A      | N/A     |
+----------------------------------+----------+---------+-----------+---------------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------+----------+---------+
9 rows in set (0.10 sec)

绑定执行计划

任务:采用hint和SPM的方法绑定还行计划

  1. 造数
create table t1 (a int,b int,c varchar(10),d varchar(20));
create table t2 (a int,b int,c varchar(10),d varchar(20));
[root@tidb2 ~]# for i in `seq 10000`; do mysql -uroot -P4000 -h192.168.16.13 -pAa123ab! -e "insert into test.t1 values ($i,floor(rand()*10000000),substring(MD5(RAND()),1,5),substring(md5(rand()),1,10))"; done;


[root@tidb2 ~]# for i in `seq 10000`; do mysql -uroot -P4000 -h192.168.16.13 -pAa123ab! -e "insert into test.t2 values ($i,floor(rand()*10000000),substring(MD5(RAND()),1,5),substring(md5(rand()),1,10))"; done;

2、添加索引

create index t1_ind_1 on t1(a);
create index t1_ind_2 on t1(a,b,c);
create index t2_ind_1 on t2(a);
create index t2_ind_2 on t2(a,b,c)

3、查看原执行计划

mysql> explain select t1.a,t1.b,t1.c,t2.b from t1,t2 where t1.a = t2.a and t1.b > t2.b order by t1.b,t2.b;
+--------------------------------+----------+-----------+-----------------------------------+------------------------------------------------------------------------------------------+
| id                             | estRows  | task      | access object                     | operator info                                                                            |
+--------------------------------+----------+-----------+-----------------------------------+------------------------------------------------------------------------------------------+
| Sort_8                         | 10000.00 | root      |                                   | test.t1.b, test.t2.b                                                                     |
| └─MergeJoin_11                 | 10000.00 | root      |                                   | inner join, left key:test.t1.a, right key:test.t2.a, other cond:gt(test.t1.b, test.t2.b) |
|   ├─IndexReader_42(Build)      | 10000.00 | root      |                                   | index:Selection_41                                                                       |
|   │ └─Selection_41             | 10000.00 | cop[tikv] |                                   | not(isnull(test.t2.b))                                                                   |
|   │   └─IndexFullScan_40       | 10000.00 | cop[tikv] | table:t2, index:t2_ind_2(a, b, c) | keep order:true                                                                          |
|   └─IndexReader_39(Probe)      | 10000.00 | root      |                                   | index:Selection_38                                                                       |
|     └─Selection_38             | 10000.00 | cop[tikv] |                                   | not(isnull(test.t1.b))                                                                   |
|       └─IndexFullScan_37       | 10000.00 | cop[tikv] | table:t1, index:t1_ind_2(a, b, c) | keep order:true                                                                          |
+--------------------------------+----------+-----------+-----------------------------------+------------------------------------------------------------------------------------------+
8 rows in set (0.00 sec)

4、通过hint强制走指定的索引

mysql> explain select t1.a,t1.b,t1.c,t2.b from t1,t2 use index(t2_ind_1) where t1.a = t2.a and t1.b > t2.b order by t1.b,t2.b;
+-------------------------------------+----------+-----------+-----------------------------------+-----------------------------------------------------------------------------------+
| id                                  | estRows  | task      | access object                     | operator info                                                                     |
+-------------------------------------+----------+-----------+-----------------------------------+-----------------------------------------------------------------------------------+
| Sort_8                              | 10000.00 | root      |                                   | test.t1.b, test.t2.b                                                              |
| └─HashJoin_40                       | 10000.00 | root      |                                   | inner join, equal:[eq(test.t1.a, test.t2.a)], other cond:gt(test.t1.b, test.t2.b) |
|   ├─IndexLookUp_56(Build)           | 10000.00 | root      |                                   |                                                                                   |
|├─IndexFullScan_53(Build)       | 10000.00 | cop[tikv] | table:t2, index:t2_ind_1(a)       | keep order:false                                                                  |
|└─Selection_55(Probe)           | 10000.00 | cop[tikv] |                                   | not(isnull(test.t2.b))                                                            |
|   │   └─TableRowIDScan_54           | 10000.00 | cop[tikv] | table:t2                          | keep order:false                                                                  |
|   └─IndexReader_52(Probe)           | 10000.00 | root      |                                   | index:Selection_51                                                                |
|     └─Selection_51                  | 10000.00 | cop[tikv] |                                   | not(isnull(test.t1.b))                                                            |
|       └─IndexFullScan_50            | 10000.00 | cop[tikv] | table:t1, index:t1_ind_2(a, b, c) | keep order:false                                                                  |
+-------------------------------------+----------+-----------+-----------------------------------+-----------------------------------------------------------------------------------+
9 rows in set (0.01 sec)


5、通过SPM创建执行计划绑定

create binding for 
select t1.a,t1.b,t1.c,t2.b from t1,t2 where t1.a = t2.a and t1.b > t2.b order by t1.b,t2.b
using 
select t1.a,t1.b,t1.c,t2.b from t1,t2 use index(t2_ind_1) where t1.a = t2.a and t1.b > t2.b order by t1.b,t2.b
mysql> explain select t1.a,t1.b,t1.c,t2.b from t1,t2 where t1.a = t2.a and t1.b > t2.b order by t1.b,t2.b;
+-------------------------------------+----------+-----------+-----------------------------------+-----------------------------------------------------------------------------------+
| id                                  | estRows  | task      | access object                     | operator info                                                                     |
+-------------------------------------+----------+-----------+-----------------------------------+-----------------------------------------------------------------------------------+
| Sort_8                              | 10000.00 | root      |                                   | test.t1.b, test.t2.b                                                              |
| └─HashJoin_40                       | 10000.00 | root      |                                   | inner join, equal:[eq(test.t1.a, test.t2.a)], other cond:gt(test.t1.b, test.t2.b) |
|   ├─IndexLookUp_56(Build)           | 10000.00 | root      |                                   |                                                                                   |
|├─IndexFullScan_53(Build)       | 10000.00 | cop[tikv] | table:t2, index:t2_ind_1(a)       | keep order:false                                                                  |
|└─Selection_55(Probe)           | 10000.00 | cop[tikv] |                                   | not(isnull(test.t2.b))                                                            |
|   │   └─TableRowIDScan_54           | 10000.00 | cop[tikv] | table:t2                          | keep order:false                                                                  |
|   └─IndexReader_52(Probe)           | 10000.00 | root      |                                   | index:Selection_51                                                                |
|     └─Selection_51                  | 10000.00 | cop[tikv] |                                   | not(isnull(test.t1.b))                                                            |
|       └─IndexFullScan_50            | 10000.00 | cop[tikv] | table:t1, index:t1_ind_2(a, b, c) | keep order:false                                                                  |
+-------------------------------------+----------+-----------+-----------------------------------+-----------------------------------------------------------------------------------+
9 rows in set (0.00 sec)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
《Oracle性能优化篇之执行计划详解》是一篇介绍Oracle数据库性能优化中的关键概念和技术的文章。通过深入讲解Oracle执行计划的相关内容,帮助读者更好地理解和优化数据库查询性能。 在Oracle数据库中,执行计划查询优化器生成的一种执行方案,用于指导数据库在执行SQL语句时的操作步骤和顺序。执行计划会根据表、索引、统计信息等内容,通过优化器的选择逻辑来生成,从而提高查询效率和性能。 《Oracle性能优化篇之执行计划详解》首先介绍了执行计划的基本组成结构,包括操作、访问方法、操作对象等。然后深入解析了执行计划的生成过程,包括Cost-Based Optimizer(CBO)和Rule-Based Optimizer(RBO)两种优化器的工作原理和区别。 接着,文章详细讲解了执行计划的查看方法和解读技巧。通过使用Oracle提供的多种工具和命令,如EXPLAIN PLAN、AUTOTRACE等,可以获取和分析执行计划,并根据结果进行性能优化。同时,文章还解释了执行计划中的关键指标和信息,如Cost、Cardinality、Bytes等,以及其对性能的影响和解决方法。 除此之外,《Oracle性能优化篇之执行计划详解》还介绍了一些常见的执行计划优化技术和策略。如索引的优化、统计信息的收集、SQL语句的调整等,通过优化执行计划中的关键因素,可以提高数据库查询效率和性能。 通过阅读《Oracle性能优化篇之执行计划详解》,读者可以深入了解Oracle数据库性能优化中的执行计划概念和技术,掌握相关工具和方法,从而更好地优化数据库查询性能。该文章对于数据库开发人员、DBA等有着重要的参考价值,帮助他们解决实际问题,提高数据库系统的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值