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

create table优化--ixconstraints表空间跟随表

原创 NickYoung 2024-10-04
185

前言

在学习PG表空间时,发现一个独特的现象,创建表时指定了自定义表空间,但是表的主键还是使用的默认表空间。
tbl_tbs表的表空间为mytbs,主键tbl_tbs_pkey为默认表空间pg_default,可以看到他们所处的物理目录是不同的。

image.png
主键的表空间不应该是跟随表吗?这是PG的BUG?

原理

查看官方文档,在创建表时,对于Primary key、unique、exclude这些ixconstraints可以使用USING INDEX TABLESPACE tablespace_name语法来指定表空间。不指定则选择默认表空间。

CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXISTS ] table_name ( [ { column_name data_type [ STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } ] [ COMPRESSION compression_method ] [ COLLATE collation ] [ column_constraint [ ... ] ] | table_constraint | LIKE source_table [ like_option ... ] } [, ... ] ] ) [ INHERITS ( parent_table [, ... ] ) ] [ PARTITION BY { RANGE | LIST | HASH } ( { column_name | ( expression ) } [ COLLATE collation ] [ opclass ] [, ... ] ) ] [ USING method ] [ WITH ( storage_parameter [= value] [, ... ] ) | WITHOUT OIDS ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ TABLESPACE tablespace_name ] where column_constraint is: [ CONSTRAINT constraint_name ] { NOT NULL | NULL | CHECK ( expression ) [ NO INHERIT ] | DEFAULT default_expr | GENERATED ALWAYS AS ( generation_expr ) STORED | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] | UNIQUE [ NULLS [ NOT ] DISTINCT ] index_parameters | PRIMARY KEY index_parameters | REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] and table_constraint is: [ CONSTRAINT constraint_name ] { CHECK ( expression ) [ NO INHERIT ] | UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] ) index_parameters | PRIMARY KEY ( column_name [, ... ] ) index_parameters | EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] | FOREIGN KEY ( column_name [, ... ] ) REFERENCES reftable [ ( refcolumn [, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are: [ INCLUDE ( column_name [, ... ] ) ] [ WITH ( storage_parameter [= value] [, ... ] ) ] [ USING INDEX TABLESPACE tablespace_name ]
复制

经过验证,使用USING INDEX TABLESPACE的语法是可以指定和表相同的表空间的。
image.png

对于这个语法,没有什么异议,可以灵活指定ixconstraints的表空间。但是对于它的缺省值,不管表是否指定了表空间ixconstraints都放到默认表空间,这个不太合理吧。假如我将表定义到特定表空间,就是为了分散io,或者存储隔离,主键还在默认表空间,就达不到我们的预期。

分析

那么可以修改下默认逻辑,当未使用USING INDEX TABLESPACE语法指定ixconstraints的表空间时,默认跟随表的表空间。

首先我们要debug下create table的过程,看下整体逻辑确定下修改的位置。
在transformCreateStmt函数中,两个ixconstraints的tablespace为NULL
image.png

所以T_IndexStmt在DefineIndex时tablespace为NULL
企业微信截图_40b195bcdd9f4a6dabfc908304d4154a.png

因此可以在transformCreateStmt函数中,获取到ixconstraints信息后,copy指定的表空间。

方案

当建表语句中指定了表空间并创建ixconstraints,并且ixconstraint的表空间为NULL时(并没有使用USING INDEX TABLESPACE语法指定表空间)。遍历ixconstraints链表,将表空间赋值为表指定的表空间。
image.png

验证

1、建表时ixconstraints未指定表空间,默认跟随表的表空间,符合预期。
image.png
2、建表时USING INDEX TABLESPACE语句指定ixconstraints的表空间,也是符合预期。
image.png

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

评论