当所有值都是 36 个字符时,使用 char 和 varchar 进行索引查找会明显更快吗

Boh*_*ian 38 postgresql performance index varchar

我有一个旧模式(免责声明!),它使用基于哈希生成的 id 作为所有表的主键(有很多)。这种 id 的一个例子是:

922475bb-ad93-43ee-9487-d2671b886479
Run Code Online (Sandbox Code Playgroud)

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

将列类型更改为固定长度是否会char(36)提供任何显着的索引性能优势,除了每个索引页的条目数量增加很小等之外?

即在处理固定长度类型时 postgres 的执行速度是否比处理可变长度类型快得多?

请不要提及微小的存储节省 - 与对列进行更改所需的手术相比,这无关紧要。

Erw*_*ter 49

没有在所有增益该手册明确指出

提示:这三种类型之间没有性能差异,除了使用空白填充类型时增加了存储空间,以及在存储到长度受限列时需要额外的一些 CPU 周期来检查长度。虽然character(n)在其他一些数据库系统中具有性能优势,但在 PostgreSQL 中没有这样的优势;事实上character(n)通常是三个中最慢的,因为它有额外的存储成本。在大多数情况下text 还是character varying应该用它来代替

大胆强调我的。

char(n)是一种过时的、无用的类型。坚持varchar(n)。无需强制执行最大长度,varchar或者text稍微快一点。(您将无法衡量差异。)

如果所有字符串的长度正好是 36 个字符,那么无论哪种方式都不会节省存储空间,甚至是一个微不足道的存储空间。两者在磁盘和 RAM 中的大小完全相同。您可以使用pg_column_size()(对表达式和表列进行测试)。

如果所有字符串都必须有 36 个字符,那么text使用CHECK (length(col) = 36)强制执行精确长度的约束,而varchar(36)不仅仅是强制执行最大长度。长度。

有关的:

你没有要求其他选项,但我会提到两个:

  1. COLLATION- 除非您使用“C”排序规则运行数据库。整理经常被忽视并且可能很昂贵。由于您的字符串在自然语言中似乎没有意义,因此遵循COLLATION规则可能没有意义。有关的:

    广泛的基准比较(除其他外)COLLATE "C"对性能的影响:

  2. UUID,显然。您的字符串看起来像一个 UUID(32 个十六进制数字加 4 个分隔符)。将这些存储为实际uuid数据类型会更有效,这在多种方式中速度更快,并且只占用16个字节 - 而不是RAM 中的37个字节,char(36)或者varchar(36)(没有分隔符存储,只有 32 个定义字符)或33磁盘上的字节数。但在许多情况下,对齐填充会导致40个字节。)COLLATION也与uuid数据类型无关。

    SELECT '922475bb-ad93-43ee-9487-d2671b886479'::uuid
    
    Run Code Online (Sandbox Code Playgroud)

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

    也可以看看: