我有一个旧的架构(免责声明!),它为所有表(有很多)的主键使用基于哈希的生成ID。这样的id的示例是:

922475bb-ad93-43ee-9487-d2671b886479


不可能更改这种方法,但是索引访问的性能很差。撇开各种可能的原因,我注意到有一件事似乎不是最优的-尽管所有许多表中的所有id值的长度都恰好是36个字符,但列类型是varchar(36),而不是char(36)

将列类型更改为固定长度是否可以使char(36)提供任何显着的索引性能优势,而不仅仅是每个索引页中的条目数增加很小?等等。

如果

请不要提及微小的存储节省-与更改色谱柱所需的手术相比,这无关紧要。 />

#1 楼

不,根本没有收获。手册明确指出:


提示:这三种类型之间没有性能差异,除了
使用空白填充类型时增加的存储空间和
在存储到
受长度限制的列中时,需要几个额外的CPU周期来检查长度。尽管character(n)在某些其他数据库系统中具有性能优势,但在PostgreSQL中却没有这样的优势。实际上,由于其额外的存储成本,character(n)通常是三者中最慢的。在大多数情况下,应改用textcharacter varying。


加粗地雷。

char(n)是一种过时的,无用的类型。坚持varchar(n)。无需强制使用最大长度,varchartext快一点。 (您将无法测量出差异。)

如果所有字符串的长度恰好都是36个字符,则没有一种方法可以节省存储空间,甚至也不会节省任何存储空间。两者在磁盘和RAM中的大小完全相同。您可以使用pg_column_size()(在表达式和表列上)进行测试。

如果所有字符串都必须包含36个字符,则将其设置为text并强制使用精确的长度,而不是CHECK (length(col) = 36)强制执行最大长度。长度。

相关:


使用数据类型“文本”存储字符串的任何缺点?

您没有问其他选项,但我要提到两个:



varchar(36)-除非您使用“ C”排序规则运行数据库。排序规则通常被忽略并且可能很昂贵。由于您的字符串在自然语言中似乎没有意义,因此遵循COLLATION规则可能毫无意义。相关:


如何有效地获取“最近对应的行”?
不使用索引在函数内执行?

广泛的基准比较(其中)COLLATION对性能的影响:


很明显,按联接表中的列进行查询的顺序很慢



UUID。您的字符串看起来像一个UUID(32个十六进制数字加4个定界符)。将它们存储为实际的COLLATE "C"数据类型会更加有效,它以多种方式更快,并且仅占用16个字节-而不是uuidchar(36)在RAM中存储37个字节(不带分隔符,仅存储32个定义字符) ,或磁盘上的33个字节。但是对齐填充在许多情况下都会以两种方式导致40个字节。)varchar(36)也与COLLATION数据类型无关。

SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid


这可能会有所帮助(最后章节):


将文本表示形式的十六进制转换为十进制数字

另请参见:


开销是多少for varchar(n)?
MD5字段的最佳数据类型是什么?




评论


这是否意味着长度受限制的char / varchar(n)将花费CPU周期检查约束,而可变长度文本字段将以与char相比更难以访问的方式分别存储文本,char在这种情况下会获胜,并且是这次胜利甚至值得考虑说一千万行带有一段文字

– PirateApp
18年3月13日在12:37

@PirateApp:char(n)几乎从不赢。不要使用它。文本和varchar(不带长度修饰符)的数据类型是二进制兼容的,并且具有相同的性能特征。两者在Postgres中共存是有历史原因的。在内部,文本是字符串类型中的“首选”类型(这会影响函数类型的分辨率)。强制执行varchar(n)的CPU周期几乎没有关系。在需要时使用长度限制。在当前情况下,uuid是真正的赢家。

–欧文·布兰德斯特(Erwin Brandstetter)
18-3-13在12:58



在固定长度值的情况下(在这种情况下为36),为什么character(n)比varchar(n)使用更多的存储空间。以及使它变慢的额外存储成本是什么?我假设varchar(n)使用更多的存储空间,因为它存储1字节的长度信息(对于长度<256),并且char(n)可以省去,因为存储的数据长度被烘焙到列定义中。

–波西米亚风格
20-2-6在6:19