暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

GPDB - 内核特性 - 分区表如何处理表名超长

原创 闫宗帅 2024-03-23
219

GPDB - 内核特性 - 分区表如何处理表名超长

GPDB分区表创建时有可能表名已存在,此时报错退出。但当分区表名超过64字符时,会进行截断,仅保留前63字符,此时就可能出现分区表名不同,截断后创建的分区表名相同从而创建失败的情况;还会出现分区表父表创建成功,但分区子表名创建失败,报表名已存在等错误导致创建失败。本文基于GreenPlum7.0分区表经典语法详细分析分区表名及分区子表名生成机制。

1、分区表名超过64字符

在语法解析阶段将分区表名进行截断,保留前63个字符,并将第64个字符赋予”\0”。该截断功能由函数truncate_identifier完成:

void
truncate_identifier(char *ident, int len, bool warn)
{
	if (len >= NAMEDATALEN)
	{
		len = pg_mbcliplen(ident, len, NAMEDATALEN - 1);
		if (warn)
		{
			/*
			 * We avoid using %.*s here because it can misbehave if the data
			 * is not valid in what libc thinks is the prevailing encoding.
			 */
			char		buf[NAMEDATALEN];

			memcpy(buf, ident, len);
			buf[len] = '\0';
			ereport(NOTICE,
					(errcode(ERRCODE_NAME_TOO_LONG),
					 errmsg("identifier \"%s\" will be truncated to \"%s\"",
							ident, buf)));
		}
		ident[len] = '\0';
	}
}

2、子分区表名的生成

makePartitionCreateStmt函数生成每个层级所有分区创建的CreateStmt链表,当创建分区表时针对分区使用WITH子句指定子分区表名,那么就使用指定的子分区表名创建子分区表,否则调用ChoosePartitionName生成分区表名。

指定子分区表名建表案例如下所示:

CREATE TABLE update_gp_foo (
    a_dist int,
    b int,
    c_part int,
    d int
)
WITH (appendonly=false) DISTRIBUTED BY (a_dist) PARTITION BY RANGE(c_part)
          (
          PARTITION p20190305 START (1) END (2) WITH (tablename='update_gp_foo_1_prt_p20190305', appendonly=false)
          );
CREATE TABLE update_gp_foo1 (
        a_dist int,
        b int,
        c_part int,
        d int
)
WITH (appendonly=false) DISTRIBUTED BY (a_dist) PARTITION BY RANGE(c_part)
          (
          PARTITION p20190305 START (1) END (2) WITH (tablename='update_gp_foo1_1_prt_p20190305', appendonly=false)
          );


ChoosePartitionName函数中对于指定分区名字的,直接将parentnamelevelprt_partname通过函数makeObjectName函数组合起来,即形成子分区表名:parentname_level_prt_partname。当三者超过63字符(最后一个字符需要保存为\0)就会发生截断,其中prt_partname部分不会截断,总是会保留下来;parentnamelevel两个截断长度较长者,知道三者长度最长不超过63字符。

对于没有指定分区名,则将当前分区层级分区序号(默认分区作为第一个)作为分区名,其中若默认分区指定了名字,而其他分区没有指定,那么其他分区序号从2开始,即prt_2作为分区名。由此parentname、level和prt_partnum通过makeObjectName函数组成的分区表名后,从pg_class中进行查询,若分区表名冲突,则在prt_partnum后追加冲突次数,比如冲突了23次,则形成分区表名为:parentname_level_prt_partnum23

生成分区表名后,通过heap_create_with_catalog创建磁盘文件前,首先根据分区表名在pg_class和pg_type中进行校验,若分区表名已存在则报错退出,否则创建成功后向pg_class中插入一条记录,pg_type中插入2条记录,其typname分别为分区表名和”_分区表名”,当然若超过63字符则分区表名会截断,若仍旧冲突,则继续在前部加”_”,比如“__分区表名”。

当然,若分区表主表名超过64字符,则在语法解析阶段就会阶段,通过函数truncate_identifier函数来完成。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论