目前,KingbaseES对MySQL的兼容性,已从功能兼容阶段过渡到强性能兼容、生态全面兼容阶段,针对客户常常遇到的用户变量问题,KingbaseES在兼容MySQL用户变量功能的基础上,优化了MySQL用户变量的一些原生问题,使数据库的易用性得到了极大优化,下面来一探究竟吧!
什么是用户变量?
用户变量是用户自定义的保存单个特定类型数据值的临时对象,是为了适应在数据库使用时需要临时暂存值的场景而设计的,目的是提高数据库系统的易用性。
用户变量的应用场景十分广泛,以下是两个典型的使用场景:
(1) 用于暂存值,当某个数值需要出现在不同的查询中,或者是同一个查询内的不同位置时,可以先将该数值赋给用户变量,在查询中使用该数值的位置用用户变量替代。例如:
(2) 用于表达式递归计算,递归计算中需要用到变量的值,同时要将计算结果重新赋给变量,循环往复。比如投影列中需要标记结果集的行号时,可以写成如下语句:
KingbaseES的GUC参数和局部变量的区别
”
KingbaseES的GUC参数是控制数据库系统运行时状态所必须的,因此它的数量,名字都是固定的,不允许用户自行添加和删除。部分GUC参数的值可以修改,通过SET语法设置,通过RESET或DISCARD语法重置。
在KingbaseES的PLSQL语言中允许使用局部变量,局部变量仅在PLSQL程序块内使用,可以随意命名、赋值。脱离了程序块以后,局部变量将变得不可见。程序块嵌套时,内层的局部变量将覆盖外层同名的局部变量。KingbaseES中,GUC参数、用户变量和局部变量的实现是互相分离的,因此其命名也没有冲突。
KingbaseES
用户变量特性
1
命名规则
用户变量命名以@为前缀,变量名包含字母(大小写不敏感),数字,中文字符以及“.”“_”,和“$”符号。如果用单引号引上,变量名可以是任意字符串,比如@’var-name’也是支持的。这点和MySQL一致。
2
存储类型
KingbaseES用户变量支持的存储类型有五种,分别为bool, int8(bigint), float8(double), numeric, char(string);默认的存储类型为char。其他类型的值存储为用户变量时会依据内部规则转换为以上五种类型。KingbaseES在存储类型上比MySQL多出一个bool类型。
3
使用方式
KingbaseES用户变量的使用比较灵活。在使用时不必事先声明,可以先赋值后引用,也可以直接引用。赋值时数据库会自动确定用户变量的存储类型,因此不必显式指定类型。KingbaseES允许对用户变量多次赋值,赋值时不限定类型(类型可变)。在未赋值条件下直接引用用户变量时,存储类型为char, 显示类型为text,值为null。这点和MySQL一致。
4
可见性
KingbaseES用户变量在连接内可见,连接外不可见,连接断开时用户变量自动释放。这点和MySQL一致。
5
用户变量的语法
KingbaseES完全兼容MySQL用户变量的SET赋值语法、SELECT INTO赋值语法、表达式赋值和取值语法。同时增加了KingbaseES特有的删除语法,用户可以通过“RESET @var_name;”删除单个用户变量,或者通过“DISCARD USER VARIABLES;”删除所有用户变量。
KingbaseES
兼容+优化MySQL用户变量特性
1
MySQL用户变量的使用问题
MySQL用户变量类型易变,单值存储,赋值和取值是表达式的一部分,可以出现在查询中的大多数地方,这样的特性或特性组合造成了MySQL用户变量的使用问题。第一类问题是由于类型的易变性引起的。第二个问题是MySQL手册中明确说明用户变量的计算顺序是不确定的。第三个问题是由于单值存储导致的。
因此,MySQL手册中也明确表示在使用过程中用户需自行保证带有用户变量查询的结果集的正确性。虽然用户变量的表达式赋值会带来许多的问题,但是由于表达式赋值在实际使用中非常普遍,我们实现了表达式赋值。
2
KingbaseES在表达式上对MySQL的改进
在KingbaseES中,对投影列中用户变量取值时类型的根据KingbaseES的语义解析顺序,离该取值最近的赋值类型确定为用户变量的数据类型。如果用户变量没有赋值,使用已存在用户变量类型;如果用户变量不存在,则取默认类型(字符串)。举例如下:
在查询执行时,KingbaseES中用户变量的计算顺序也是确定的,即依据KingbaseES的语义解析顺序处理。
除此之外,KingbaseES对用户变量的优化和并行,并发进行了限制。
由于用户变量是单值存储,类型可变的,如果遇上并发,并行与用户变量赋值混合的情况,用户变量的值将变得不可预测。因此,在使用用户变量时,禁止查询并发,并行。KingbaseES在数据库内部对这两个特性进行了禁止,使用者无需做任何操作。
在执行包含用户变量的语句时,执行性能相比无用户变量的语句会有下降,这是正常的。为了保证结果集的正确性,包含用户变量的语句需要尽可能按输入语法的顺序执行。因此不能使用优化器进行优化,也不能并行执行其中的某些步骤。
3
KingbaseES用户变量表达式的使用注意事项
用户变量的类型是可变的,但是在SELECT查询中,需要确保列类型前后保持一致。如果在计算过程中用户变量类型发生了变化,结果集将会变得不可预期。因此,在使用用户变量时,用户需要自行保证结果集的正确性。比如,确保用户变量类型在计算过程中不发生变化,如果发生了变化,可以通过隐式转换转为预期类型等。
如果在单个 SELECT 语句中有多个用户变量赋值子句,KingbaseES会依据内部的解析顺序执行,不能完全保证表达式求值的顺序符合用户期望。KingbaseES尽可能使表达式按照KingbaseES语义顺序求值,但是由于优化器的影响,求值顺序可能无法完全保证。
为了保证用户变量类型在计算过程中保持不变,给用户变量赋值尽可能使用SET语法和SELECT INTO语法,避免使用表达式赋值语法(该语法主要为兼容MySQL历史用例而设计)。必须要使用表达式赋值时,尽可能将赋值用在投影列最外层,尽量少用在其他的位置,比如JOIN ON,HAVING, GROUP BY,ORDER BY子句中,在这些子句中使用表达式赋值语法可能会造成无法预期的结果集。
一个常见的用法是在投影列中使用@var_name := @var_name +1的方式来标记结果集的行号,KingbaseES提供的row_number函数能够替代上述使用方式。
如果事务执行时语句中包含用户变量赋值,事务回滚时用户变量不会被回滚。
在KingbaseES的操作符中有许多包含@字符的操作符,用户变量在和操作符混用时,为了避免产生语法错误,需要将用户变量和操作符用空格隔开。例如@var_name:=@var_name+1虽然可以执行,但还是建议写成@var_name := @var_name + 1的形式。因为我们无法避免用户将:=@定义为操作符。
字符“@”在KingbaseES中也可作为操作符,为了兼容原生KingbaseES,@var_name中的var_name将解析成用户变量,这里“@”为用户变量引导符。而@ var_name中的var_name将解析成标识符,“@”为操作符。
END
用户变量的设计是KingbaseES为数据库用户提供易用性方面的一次探索。用户可以利用用户变量暂存中间值,该中间值既可以在同一连接内跨语句使用,也可以在同一条语句的不同运算中使用。和局部变量相比,用户变量突破了块的作用域限制,使用范围更大。此外,由于用户变量自身的特点(单值存储,类型可变),造成了用户变量使用受到了限制。在未来,KingbaseES会继续秉承以客户为中心的理念,为数据库使用者提供更加易用的功能。
推荐阅读 (点击下图了解更多↓↓↓↓)
供稿:产品研发中心
编辑:王堇
审核:日尧