Explain

UDDB的explain主要解释select、insert、replace、delete、update语句,可分为两层:在中间件层的explain和存储节点的explain,两者分别返回不同的执行计划结果。

中间件层的explain

展示SQL语句在中间件层经查询优化器生成的执行计划,该执行计划是由一系列算子按执行的先后顺序构成的树形结构。

使用方法:在SQL语句前面加上uexplain关键字

存储节点的explain

展示SQL语句在存储节点的执行计划,将explain语句直接下推到存储节点执行,返回的结果即在存储节点的执行计划。

使用方法:在SQL语句前面加上explain关键字

使用举例

以经典的用户表、订单表、商品表 三表 join 为例:

CREATE TABLE `t_user` (
  `uid` int(11) DEFAULT NULL,
  `uname` varchar(128) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
UPARTITION BY HASH(uid)
UPARTITIONS 4;  

CREATE TABLE `t_order` (
  `oid` int(11) DEFAULT NULL,
  `oname` varchar(128) DEFAULT NULL,
  `create_time` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
UPARTITION BY range(oid)
(
UPARTITION p1 values less than (100),
UPARTITION p2 values less than (1000),
UPARTITION p3 values less than maxvalue
);

CREATE TABLE `t_product` (
  `pid` int(11) DEFAULT NULL,
  `pname` varchar(128) DEFAULT NULL,
  `price` double DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
UPARTITION BY HASH(pid)
UPARTITIONS 4;

多表跨分片复杂join

SQL语句:

select * from t_user join t_order on t_user.uid = t_order.oid join t_product on t_order.oname=t_product.pname;

a) 中间件层explain

在SQL语句前面加uexplain关键字,到Uddb执行即可得到执行计划,如下图所示:

image

该语句的查询执行计划是由JoinNode算子和SelectNode算子构成的二叉树,其结构如下图所示:

image

1、执行计划从最小node_id开始执行,SelectNode-1算子中的表t_user是驱动表先执行,获得SelectNode-1算子的结果

2、SelectNode-2算子的执行依赖于SelectNode-1的结果,将SelectNode-1的结果以where条件的形式放到SelectNode-2算子的sql语句中,重写SQL语句后在执行,获得SelectNode-2算子的结果

3、在JoinNode-3算子中对SelectNode-1的结果和SelectNode-2的结果进行等值连接计算,得到表t_user和t_order连接的中间结果

4、SelectNode-4算子的执行依赖JoinNode-3的结果,将JoinNode-3的结果以where条件的形式放到SelectNode-4算子的sql语句中,重写SQL语句后在执行,获得SelectNode-4算子的结果

5、在JoinNode-5算子中对JoinNode-3的结果和SelectNode-4的结果进行等值连接计算,得到t_user、t_order和t_product 3表连接的结果

b) 存储节点explain

取出uexplain结果中SelectNode-1算子的sql语句。加上explain关键字,将sql语句中的表名t_user替换为子表名,生成4条新的子sql如下所示:

explain select t_user.uid , t_user.uname from t_user_0000 as t_user order by t_user.uid asc;
explain select t_user.uid , t_user.uname from t_user_0001 as t_user order by t_user.uid asc;
explain select t_user.uid , t_user.uname from t_user_0002 as t_user order by t_user.uid asc;
explain select t_user.uid , t_user.uname from t_user_0003 as t_user order by t_user.uid asc;

分别下发到存储节点执行,在中间件层对每条子sql的结果进行合并,即可得到该语句在存储节点的执行计划。结果如下所示:

image

uexplain结果每列的说明如下:

node_id 在整个执行计划中唯一的标识一个算子节点,由两部分组成:操作类型+序号。

算子类型

SelectNode:代表简单select语句(无表)、单表select语句和分片规则一致的多表select语句,如果是子查询则需要标识出子查询类型

DmlNode:代表insert/replace/update/delete语句,并标识出dml类型

JoinNode:将两个结果集做连接计算的算子

UnionNode:将两个结果集做并集计算的算子

序号是创建执行计划时生成的,序号越小算子越先执行。

table 当前算子涉及到的表名,需标识出驱动表

upartition_type 表的分区类型

subtables 分区表的子表名

parent 当前算子的父节点,每个算子的parent有且仅有一个

children 当前算子的子节点,也即这个算子的数据来源

sql 算子下发至存储节点的SQL语句,这里显示的并非真正下发的SQL语句,在执行时会将表名替换为子表名

operator_info 当前算子需要在中间件层执行的操作信息(如merge result、join、union、group by、order by、limit等)

hint SQL语句中的隐含信息,如/*force_master*/指定只读主节点

单表查询

SQL语句:

select * from t_user order by uid;

a) 中间件层explain

在SQL语句前面加uexplain关键字,到Uddb执行即可得到执行计划,如下图所示:

image

只有一张表,生成一个SelectNode算子。

b) 存储节点explain

取出uexplain结果中的sql语句,加上explain关键字,将sql语句中的表名t_user替换为子表名生成4条新的子sql如下所示:

explain select * from t_user_0000 as t_user order by uid;
explain select * from t_user_0001 as t_user order by uid;
explain select * from t_user_0002 as t_user order by uid;
explain select * from t_user_0003 as t_user order by uid;

分别下发到存储节点执行,在中间件层对每条子sql的结果进行合并,即可得到该语句在存储节点的执行计划。结果如下所示:

image

分片规则一致的多表join

SQL语句:

select * from t_user,t_product where uid=pid;

a) 中间件层explain

在SQL语句前面加uexplain关键字,到Uddb执行即可得到执行计划,如下图所示:

image

两表的分片规则一致,在中间件层只生产一个SelectNode算子。

b) 存储节点explain

取出uexplain结果中的sql语句,加上explain关键字,将sql语句中的表名t_user替换为子表名,表名t_product替换为和t_user相同后缀的子表名,生成4条新的子sql如下所示:

explain select * from t_user_0000 as t_user, t_product_0000 as t_product where uid=pid;
explain select * from t_user_0001 as t_user, t_product_0001 as t_product where uid=pid;
explain select * from t_user_0002 as t_user, t_product_0002 as t_product where uid=pid;
explain select * from t_user_0003 as t_user, t_product_0003 as t_product where uid=pid;

分别下发到存储节点执行,在中间件层对每条子sql的结果进行合并,即可得到该语句在存储节点的执行计划。结果如下所示:

image

使用限制

1、不支持explain语句中带extended/partitions关键字

2、不支持json格式的explain