当所有值均为36个字符时,使用char vs varchar可使索引查找明显更快


30

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

922475bb-ad93-43ee-9487-d2671b886479

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

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

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

请不要提及微不足道的存储节省-与更改色谱柱所需的手术相比,这已不再重要。

Answers:


40

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

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

大胆强调我的。

char(n)是一种过时的,无用的类型。坚持下去varchar(n)。如果您不需要强制长度,varchar或者text会快一点。您将无法衡量差异。

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

有关:

您没有要求其他选择,但是我会提到两个:

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

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

  2. UUID,效果显着。您的字符串看起来像一个UUID(32个十六进制数字加4个定界符)。将它们存储为实际uuid数据类型会更加有效,它以多种方式更快,并且仅占用 16个字节-相对于RAM中的或,只有 37个字节(不带分隔符,仅存储32个定义字符)或 33磁盘上的字节数。但是对齐填充在许多情况下都会以任何一种方式导致 40个字节。)对于数据类型也将是无关紧要的。char(36)varchar(36)COLLATIONuuid

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

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

    也可以看看:


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

1
@PirateApp:char(n)几乎在任何方面都不会赢。不要使用它。数据类型textvarchar(不带长度修饰符)是二进制兼容的,并具有相同的性能特征。两者在Postgres中共存是有历史原因的。在内部,text是字符串类型中的“首选”类型(这会影响函数类型的分辨率)。用于强制执行的CPU周期varchar(n)无关紧要。在需要时使用长度限制。在眼前的情况下uuid才是真正的赢家。
Erwin Brandstetter
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.