注册
达梦 SQL 优化——基础篇 03
专栏/金的探索记录/ 文章详情 /

达梦 SQL 优化——基础篇 03

2021/01/19 2187 2 0
摘要 本文主要介绍过滤和分组排序时用到的操作符。

本文主要介绍过滤和分组排序时用到的操作符。

过滤条件:SLCT

这类操作符比较简单,是对结果集进行过滤,需要注意的是操作符的描述信息,从描述信息中我们可以看到对于下层操作有哪些可用的过滤条件,这些条件往往是优化方向的来源。

--SEL 14 SQL>explain select * from t2 where id > 5 and id not like '%c%'; 1 #NSET2:[0,1,56] 2 #PRJT2:[0,1,56];exp_num(2),is_atom(FALSE) 3 #slct2:[0,1,56];(exp_cast(T2.ID) > 5 AND exp 11 <= 0) 4 #CSCN2:[0,1,56];INDEX33555447(T2)

需要关注的是 SLCT 的描述部分 (exp_cast(T2.ID) > 5 AND exp11 <= 0),这里括号中的内容将 ID > 5 标注为了 EXP_CAST(T2.ID)> 5,ID NOT LIKE ‘%c%’ 标注为了 EXP11 <= 0。其中 EXP_CAST(T2.ID)> 5 提供的信息告诉我们,列 ID 和数字 5 进行比较,是要将列作类型转换的,那么也就是说,就算 ID 列上存在索引,可能也不能进行范围扫描,因为索引范围扫描的输入要求是和索引列上的类型相同,我们验证一下。

--SEL 15 SQL>explain select * from t2 where id = 5; 1 #NSET2:[0,1,56] 2 #PRJT2:[0,1,56];exp_num(2),is_atom(FALSE) 3 #SLCT2:[0,1,56];exp_cast(T2.ID) = 5 4 #CSCN2:[0,8,56];INDEX33555447(T2)

确实,在存在索引(create indexi_index3 on t2(id))的情况下,单列等值查询也没有走索引进行查询,这个在此也只说明一个大致原理,不同类型数据进行比较时会先选取一种比较类型,再确定比较方法。比如在此例中,比较 ID(VARCHAR)= 5(INT),服务器优先选择把类型转换成 INT 进行比较,所以导致 ID 列需要做类型转换,从而不能利用索引(没有索引存储了转换之后的数据)。碰到这种情况,我们需要把索引列的对比对象转换为和索引列一样的格式。

--SEL 16 SQL>explain select * from t2 where id ='5'; 1 #NSET2:[0,1,56] 2 #PRJT2:[0,1,56];exp_num(2),is_atom(FALSE) 3 # SSEK2:[0.1.56];scan_type(ASC),I_INDEX3 (T2),scan_range[‘5’,’5’]

另外一个条件 ID NOT LIKE ‘%c%’,转换为 EXP11 <= 0 ,实际上是把 NOT LIKE 转换成了 INSTR(ID,‘c’) <= 0, 原理在此暂不多赘述,我们希望做到的是对于 SLCT 描述项中的每一个,都能在原始 SQL 中找到对应的条件,并看下是否存在优化的可能性。

分组:HAGR,SAGR

这类操作符都是对取到的数据做一些处理,或归并,或排序,而归并和排序在某些情况下是互通的我们先看这些操作符出现的基本情况。存在 GROUP 的语句,大概率会出现这两个之一:

SQL> create table t4(id int,id1varchar); SQL> insert into t4 select level,levelfrom dual connect by level < 10000; SQL> commit;
--SEL 17 SQL>EXPLAIN SELECT id,sum(id1) from t4 group by id; 1 #NSET2:[2,99,52] 2 #PRJT2:[2,99,52];exp_num(2),is_atom(FALSE) 3 #HAGR2:[2,99,52];grp_num(1),sfun_num(1); 4 #PRJT2:[1,9999,52];exp_num(2),is_atom(FALSE) 5 #CSCN2:[1,9999,52];INDEX33555450(T4)

HAGR 是最基础的分组方式,HASH AGR 操作,对于没有优化条件的分组语句,一般都会按这种方式进行分组,分组原理和 HASH INNER JOIN 的方式类似,将原表数据取出,每个计算 FOLD,发现有 FOLD 相同,且满足后续条件的合并为一组(不难发现,如果基表数据非常庞大时,HAGR 的计算量是不容忽视的,那么满足一定条件的情况下,我们可以利用有序性走 SAGR 操作符。

SQL> create or replace index i_test4 ont4(id,id1);
--SEL 18 SQL>explain select id,sum(id1) from t4 group by id; 1 #NSET2:[2,99,52] 2 #PRJT2:[2,99,52];exp_num(2),is_atom(FALSE) 3 #SAGR2:[2,99,52];grp_num(1),sfun_num(1) 4 #PRJT2:[1,9999,52];exp_num(2),is_atom(FALSE) 5 #SSCN:[1,9999,52];I_TEST4(T4)

这里出现 SAGR 操作符,说明下层的输出是按分组列排序的,下层为 SSCN I_TEST4,而 I_TEST4为(ID,ID1) 组合索引,按照 ID 有序,满足 SAGR 条件。

SAGR,SORTED AGR 操作,不同于 HASH AGR,由于下层数据有序,同一分组的数据按照顺序取出就行,节省了大量的计算。

排序:SORT:

SORT 是做排序操作时使用到的操作符,我们可以进行如下实验。

--SEL 19 SQL>explain select id,id1 from t4 order by id; 1 #NSET2:[1,9999,60] 2 #PRJT2:[1,9999,60];exp_num(3),is_stom(FALSE) 3 #SSCN:[1,9999,60];I_TEST(T4)

可以看到,这里并没有出现 SORT 操作符。如前文所说,索引 I_TEST 已经是以 ID 有序的了,所以在下层的 SSCN 中已经把排序的任务做完了。如果我们换一列来测试。

SQL> explain select id,id1 from t4order by id1 desc;
1 #NSET2:[1,9999,60] 2 #PRJT2:[1,9999,60];exp_num(3),is_atom(FALSE) 3 #SORT3:[1,9999,60];key_num(1),is_distinct(FALSE),top_flag(0),is_sdaptive(0) 4 #SSCN:[1,9999,60];I_TEST4(T4)

如果是对 id1 列进行排序,则在 SSCN 之后,还需要针对 id1 做一次 SORT,这对数据库也是一笔不小的开销。所以在实际运用中,我们也可以想办法利用索引的有序性来完成排序的操作。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服