关于堆表,看官方文档里说对于并发插入极为有效果,但却没有提及并发更新(或删除)及并发查询的情况,特写此贴来总结下并发情况下堆表的执行计划。
堆表创建:
SQL> create table t_obj(name VARCHAR(128),id int) storage(branch 64); 操作已执行 已用时间: 13.093(毫秒). 执行号:903. |
目前发现堆表创建尚不支持ctas的方式创建。
创建实验用表:
SQL> create table t_obj2 as select * from dba_objects; 操作已执行 已用时间: 220.311(毫秒). 执行号:906. |
未打开parallel_policy参数观察并发情况。
插入的执行计划:
SQL> explain insert into t_obj select object_name,object_id from t_obj2; 1 #INSERT_LIST : [0, 0, 0]; table(T_OBJ), type(select), hp_opt(0), mpp_opt(0) 2 #PRJT2: [1, 14873, 78]; exp_num(2), is_atom(FALSE) 3 #CSCN2: [1, 14873, 78]; INDEX33563140(T_OBJ2) 已用时间: 0.375(毫秒). 执行号:0. |
可以看到此时并发插入的执行计划已经开始。
而此时查询的执行计划如下:
SQL> explain select /*+ parallel(t_obj) 8 */ count(*) from t_obj; 1 #NSET2: [1, 1, 0] 2 #PRJT2: [1, 1, 0]; exp_num(1), is_atom(FALSE) 3 #FAGR2: [1, 1, 0]; sfun_num(1), 已用时间: 0.421(毫秒). 执行号:0. |
可以看到在未打开parallel_policy参数的时候,即便加入了hints也依旧走的是串行执行计划。
打开parallel_policy执行计划
Insert执行计划(没有hints):
SQL> explain insert into t_obj select object_name,object_id from t_obj2; 1 #INSERT_LIST : [0, 0, 0]; table(T_OBJ), type(select), hp_opt(0), mpp_opt(0) 2 #PRJT2: [1, 14873, 78]; exp_num(2), is_atom(FALSE) 3 #CSCN2: [1, 14873, 78]; INDEX33563140(T_OBJ2) 已用时间: 0.786(毫秒). 执行号:0. |
Insert执行计划(有hints):
SQL> explain insert into t_obj select /*+ parallel(t_obj) 2 */ object_name,object_id from t_obj2; 1 #INSERT_LIST : [0, 0, 0]; table(T_OBJ), type(select), hp_opt(0), mpp_opt(0) 2 #PRJT2: [1, 14873, 78]; exp_num(2), is_atom(FALSE) 3 #CSCN2: [1, 14873, 78]; INDEX33563140(T_OBJ2) |
可以看出执行计划是一样的。而此时查询的执行计划和并行查询非堆表的执行计划是一样的。
并行查询:
SQL> explain select /*+ parallel(64) */ name from t_obj; 1 #NSET2: [1, 14873, 60] 2 #LOCAL COLLECT: [1, 14873, 60]; op_id(1) n_grp_by (0) n_cols(0) n_keys(0) for_sync(FALSE) 3 #PRJT2: [1, 14873, 60]; exp_num(2), is_atom(FALSE) 4 #CSCN2: [1, 14873, 60]; INDEX33563139(T_OBJ) |
并行update:
SQL> explain update /*+ parallel(2) */ t_obj set name='AA' where id=2; 1 #UPDATE : [0, 0, 0]; table(T_OBJ), type(select), mpp_opt(0), hp_opt(0) 2 #NTTS2: [1, 1, 16]; for_mdis(FALSE) 3 #LOCAL GATHER: [1, 1, 16]; op_id(1) n_grp_by (0) n_cols(0) n_keys(0) invoke_flag(0) top_flag(0) 4 #PRJT2: [1, 1, 16]; exp_num(2), is_atom(FALSE) 5 #SLCT2: [1, 1, 16]; T_OBJ.ID = 2 6 #CSCN2: [1, 1, 16]; INDEX33563139(T_OBJ) |
并行删除:
SQL> explain delete from /*+ parallel(2) */ t_obj where id=2; 1 #DELETE : [0, 0, 0]; table(T_OBJ), type(select), mpp_opt(0), hp_opt(0) 2 #NTTS2: [1, 1, 16]; for_mdis(FALSE) 3 #LOCAL GATHER: [1, 1, 16]; op_id(1) n_grp_by (0) n_cols(0) n_keys(0) invoke_flag(0) top_flag(0) 4 #PRJT2: [1, 1, 16]; exp_num(1), is_atom(FALSE) 5 #SLCT2: [1, 1, 16]; T_OBJ.ID = 2 6 #CSCN2: [1, 1, 16]; INDEX33563139(T_OBJ) 已用时间: 0.463(毫秒). 执行号:0. |
总结:
堆表在插入的环境下可以自动打开并发功能,使得性能得到很大的提升。而在其他场景中,依旧需要配合parallel_policy等参数共同作用才可以达到并行的效果。
达梦数据库技术社区:https://eco.dameng.com