这类操作符比较简单,是对结果集进行过滤,需要注意的是这类操作符的描述信息,从描述信息中我们可以看到对于下层操作有哪些可用的过滤条件,这些过滤条件往往是优化方向的来源。
延用上篇文章DM7操作符优化系列(二)——多表关系处理中的测试用表
CREATE TABLE T1(ID VARCHAR);
CREATE TABLE T2(ID VARCHAR);
INSERT INTO T1 VALUES('AMEE'),('AMSS'),('BURNING'),('ABED'),('CHALICE');
INSERT INTO T2 VALUES('AAAA'),('AAAA'),('BBBB'),('CCCC'),('DDDD'),('AAME'),('AMEE'),('EEEE');
--SEL 14
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 exp11 <= 0)
4 #CSCN2: [0, 8, 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 列上存在索引,可能也不能进行范围扫描,因为索引范围扫描的输入要求是和索引列上的数据类型相同,我们验证一下
--SEL15
CREATE INDEX I_INDEX3 ON T2(ID);
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)
确实,在存在索引 (I_INDEX3) 的情况下,单列等值查询也没有走索引进行查询。
这个例子也说明了一个大致原理:在 DM7 中,内部提供多种对比数据的方法以及转换类型的方法,但这些方法是没有覆盖所有类型的,不同类型数据进行比较时,会先选取一种用于比较的数据类型,再确定比较方法。
比如在此例中,比较 ID(VARCHAR) = 5(INT),服务器优先选择把类型转换成INT进行比较,导致ID列需要做类型转换,从而不能利用索引(索引存储的是转换之前的数据)。碰到这种情况,我们需要把索引列的对比对象(此例中的INT)转换为和索引列一样的类型。
--SEL16
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(VARCHAR) = 5(INT) 中的 5(INT) 转换为 5(VARCHAR) 之后,就走索引进行查询了。
对于过滤条件操作符,我们希望做到的是:对于SLCT描述项中的每一个具体描述,都能在原始SQL查询语句中找到对应的条件,并思考是否存在优化的可能性。
文章
阅读量
获赞