本期介绍openGauss系数据库的几个案例:
- rowid使用案例
- GUC参数非全局设定
- hash分区键限制
astore引擎下的rowid使用问题
Oracle迁移经常会遇到rowid兼容性问题:可能是不支持rowid,也可能是rowid类型或行为有差异。
rowid的常用场景:
- 确保无主键表排序结果稳定性
- 删除表中的重复记录
- 方便DML操作定位行
很多openGauss发行版都支持了rowid功能,最近在项目中遇到一个问题,业务使用JDBC驱动pbe方式执行如下语句:
deletefromtab1whererowid=?;执行计划走了Seq Scan,没走预期的Tid Scan
preparestmt(varchar)asselect*fromtab1whererowid=$1;postgres=# explain execute stmt('nMYAAA==5sAAAA==gAA=');QUERYPLAN--------------------------------------------------------------Seq Scanontab1(cost=0.00..230557.40rows=50000width=36)Filter:(rowid=($1)::rowid)(2rows)如果直接使用静态值,则能走Tid Scan
postgres=# explain delete from tab1 where rowid ='nMYAAA==5sAAAA==gAA=';QUERYPLAN----------------------------------------------------------Deleteontab1(cost=0.00..4.02rows=1width=6)->Tid Scanontab1(cost=0.00..4.02rows=1width=6)TID Cond:(ctid='(49382,128)'::tid)Filter:(tableoid=50844)(4rows)在服务端打开rowidexpr_tidscan选项后达到预期:
postgres=# explain execute stmt('nMYAAA==5sAAAA==gAA=');QUERYPLAN---------------------------------------------------------Tid Scanontab1(cost=0.01..4.02rows=50000width=36)TID Cond:(rowid=($1)::rowid)(2rows)JDBC使用pbe方式如果没开那个选项,PBE方式会走全表扫。
GUC参数非全局设定
哪些GUC参数能使用set进行局部配置,而非cluster全局范围生效呢?
可以使用SET在user、database进行设置,有三种设置形态:
alteruserset...alterdatabaseset...alteruserindatabaseset...但数据库里并非所有的参数都能使用set在session范围进行设置,否则可能会遇到
- xxx cannot be changed now
- xxx cannot be set after connection start
这类错误提示,而当前数据库内核哪些参数可以设置,我们可以使用如下代码提前了解:
DOLANGUAGEplpgsql $do$declarev_rec record;v_sqlvarchar;beginforv_recinselect*frompg_settingswherecontextnotin('internal','postmaster')loopbeginv_sql='alter database postgres set '||v_rec.name||'='||quote_literal(v_rec.setting)||';';executev_sql;raise notice'%',v_rec.name;exceptionwhenothersthen--raise notice 'state=%,error=%',SQLSTATE,SQLERRM;end;endloop;end;$do$;分布式场景hash分区键问题
openGauss系分布式扩缩容时遇到一个问题,分析定位与分区表hash分区键类型有关。
- 分区表使用普通的create table方式,hash分区支持分区键支持浮点数类型或时间类型。
- 分区表使用create table including方式,hash分区分区键只支持整型。
测试语句如下:
- 普通的create table方式可以成功
createtabletest1(idintegernotnull,widdecimal(4,4))DISTRIBUTEBYHASH(id)PARTITIONBYHASH(wid)(PARTITIONp1,PARTITIONp2,PARTITIONp3);createtabletest2(idintegernotnull,sincetimestamp)DISTRIBUTEBYHASH(id)PARTITIONBYHASH(since)(PARTITIONp1,PARTITIONp2,PARTITIONp3);test1表的hash分区键为浮点类型,test2表的hash分区键为时间类型。
- create table including方式失败
CREATETABLEtmp1(LIKEtest1 INCLUDING DISTRIBUTION INCLUDINGPARTITION);CREATETABLEtmp2(LIKEtest2 INCLUDING DISTRIBUTION INCLUDINGPARTITION);复制test1表分区键类型为浮点型时,tmp1表创建失败,报错:
ERROR:numericfield overflow复制test2表分区键类型为时间类型时,tmp2表创建失败,报错:
ERROR: invalid input syntaxfortypetimestamp:"2"这次的分享就到这里,后续会继续分享~