这个文档主要说明在Apache Calcite中如何对谓词进行优化的。先列举几个场景说明一下这个文档主要论述的问题。
样例
针对NULL值的优化
example:
"a <> 1 or a = 1"
// 如果a不能为NULL。则能优化为:
TRUE
// 如果a可能为NULL,将UNKNOW当TRUE,则优化结果为:
TRUE
// 如果a可能为NULL,将UNKNOW当false,则优化结果为:
a IS NOT NULL
// 如果a可能为NULL,将UNKNOW当UNKNOW,则优化结果为:
OR(IS NOT NULL(?0.int0), null)
code:
// a可能为NULL
checkSimplify3_(
or(ne(vInt(0), literal(1)),
eq(vInt(0), literal(1))),
"OR(IS NOT NULL(?0.int0), null)",
"IS NOT NULL(?0.int0)",
"true");
// a如果不可能为NULL,则肯定是TRUE,我们这里不做验证
针对数字比较重合的优化(Point)
example:
"a <> 1 and a = 2"
// 如果a不能为NULL。则能优化为:
a = 2
// 如果a可能为NULL,将UNKNOW当TRUE,则优化结果为:
a IS NULL or a = 2
// 如果a可能为NULL,将UNKNOW当false,则优化结果为:
a IS NOT NULL AND a = 2
// 如果a可能为NULL,将UNKNOW当UNKNOW,则优化结果为:
CASE(IS NULL(a), null, a = 2)
但是实际上代码中的优化为(这是因为优化完成后仍然保持a为nullable):
code:
checkSimplify3_(
and(ne(vInt(0), literal(1)),
eq(vInt(0), literal(2))),
"=(?0.int0, 2)",
"=(?0.int0, 2)",
"=(?0.int0, 2)");
优化过程(这里举两个例子)


说明
1:在源码中,RexNode用来表示行表达式,常用的 RexNode 类型有 RexLiteral (常量),RexVariable (变量),RexCall
(含操作符和操作数的表达式).
2:SQL中无法使用比较运算符来测试 NULL 值,比如 =, <, 或者 <>。 我们必须使用 IS NULL 和 IS NOT NULL 操作符,只有这两个操作符能确定这个值是不是NULL。
其余操作符的都是都会得到UNKNOW的结果。
注意事项
其中在谓词优化过程中,NULL的值的处理决定了有些谓词的优化结果可能不同。例如NULL在与其他常量或者值进行比较时都会得到UNKNOW值。
And表达式
AND | TRUE | FALSE | UNKNOW |
---|---|---|---|
TRUE | TRUE | FALSE | UNKNOW |
FALSE | FALSE | FALSE | FALSE |
UNKNOW | UNKNOW | FLASE | UNKNOW |
OR表达式
OR | TRUE | FALSE | UNKNOW |
---|---|---|---|
TRUE | TRUE | TRUE | TRUE |
FALSE | TRUE | FALSE | UNKNOW |
UNOKONW | TRUE | UNOKONW | UNKNOW |
其实上面的UNKONW的表达式转化比较好理解,如果我们把UNKONW当作”不确定值“,就能很容易推理出OR或者AND表达式的结果,例如 TRUE
AND UNKNOW,我们这时候的结果就完全由UNKNOW决定,因此整个表达式的值为UNKONW。
网友评论