【问题标题】:In Postgres, is it performance critical to define low cardinality column as int and not text?在 Postgres 中,将低基数列定义为 int 而不是 text 对性能至关重要吗?
【发布时间】:2013-04-29 20:29:27
【问题描述】:

我有一列有 4 个选项。 该列被定义为文本。 该表是1亿条记录的大表并继续运行。 该表用作报告表。 表上的索引是 - provider_id,date,enum_field。

我想知道我是否应该将 enum_filed 从 text 更改为 int 以及这对性能有多重要。

使用 postgres 9.1

表: 提供者报告: id bigserial NOT NULL, provider_id bigint, 没有时区的日期时间戳, enum_field 字符不同, ....

索引: provider_id,date,enum_field

【问题讨论】:

  • 给我们表格的完整定义。对于您当前的问题,很难说出任何信息。
  • @IgorRomanchenko 我用部分表定义编辑。

标签: postgresql indexing


【解决方案1】:

TL;DR 版本:担心这个可能不值得你花时间。

长版:

Postgres 中有枚举类型:

create type myenum as enum('foo', 'bar');

与使用 varchar 或整数字段相比,使用它有利有弊。主要是专业人士恕我直言。

就大小而言,它存储为oid,所以int32 类型。这使它比填充了典型值的 varchar 更小(例如,'draft'、'published'、'pending'、'completed',无论您的枚举是什么),并且与 int 类型的大小相同。如果您的值很少,smallint / int16 无疑会更小。您的一些性能变化将来自那里(较小与较大的字段,即几乎可以忽略不计)。

在每种情况下都可以进行验证,无论是通过enum 的内置目录查找,还是varchar 或int 的检查约束或外键。您的一些性能变化将来自那里,而且可能也不值得您花时间。

枚举类型的另一个好处是它是有序的。在上面的示例中,'foo'::myenum < 'bar'::myenum',使得order by enumcol 成为可能。要使用varchar 或int 实现相同的目的,您需要一个带有sortidx 列或其他内容的单独表......在这种情况下,如果您想订购,枚举可以产生巨大的好处通过您的枚举值。这给我们带来了(恕我直言)唯一的问题,这与枚举类型在目录中的存储方式有关......

在内部,每个枚举的值都带有一个oid,后者按原样存储在表中。所以它在技术上是一个int32。创建枚举类型时,其值以正确的顺序存储在目录中。在上面的示例中,'foo' 的oid 将低于'bar'。这使得 Postgres 按枚举值排序非常有效,因为它相当于对 int32 值进行排序。

但是,当您 ALTER 您的枚举时,您最终可能会更改该顺序。例如,假设您将上述枚举更改为 myenum 现在是 ('foo', 'baz', 'bar')。出于与效率相关的原因,Postgres 不会为现有值分配新的oid 并重写使用它们的表,更不用说使使用它们的缓存查询计划无效了。相反,它的作用是在pg_catalog 中填充一个单独的字段,以使其产生正确的排序顺序。从那时起,按枚举字段排序需要额外的查找,这实际上相当于将表与带有sortidx 字段的单独值表连接起来——就像你对varchar 或@ 所做的那样987654351@ 如果您想对它们进行排序。

这通常很好并且完全可以接受。有时,它不是。如果没有,则有解决方案:更改具有枚举类型的表,并将它们的值更改为 varchar。还可以像您一样定位和调整使用它的功能和触发器。然后完全删除该类型,然后重新创建它以获取新的 oid 值。最后将表格改回原来的位置,并重新调整函数和触发器。不是微不足道的,但肯定是可行的。

【讨论】:

  • 该表有数百万条记录并且越来越大,因此很难测试(除非我知道它确实有效,否则我不会对大生产数据进行这种更改)。我一直认为 index int 比 text indexing 好很多。
  • 您的评估是准确的:int 对于 btree 索引确实更快,因为对于 int 的 a char,因此您更有可能将它放在内存中。有十亿个条目,差异可能会开始增加。是否值得与重写表相关的停机时间完全是另一个问题。
【解决方案2】:

最好将 enum_field 定义为 ENUM 类型。它将占用最少的空间并检查允许哪些值。

至于性能:如果它真的影响性能,唯一可靠的方法是测试它(使用适当的正确测试集)。我的猜测 - 差异将小于 5%。

如果你真的想改变桌子 - 不要忘记在改变之后VACUUM它。

【讨论】:

    猜你喜欢
    • 2012-09-04
    • 2014-05-18
    • 2018-10-26
    • 1970-01-01
    • 1970-01-01
    • 2013-01-31
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多