1

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

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

使用 postgres 9.1

表:provider_report:id bigserial NOT NULL,provider_id bigint,没有时区的日期时间戳,enum_field 字符变化,...。

索引:provider_id,date,enum_field

4

2 回答 2

2

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

长版:

Postgres 中有一个枚举类型:

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

使用它与 varchar 或整数字段相关的优点和缺点。主要是专业人士恕我直言。

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

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

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

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

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

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

于 2013-05-06T10:27:32.063 回答
0

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

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

而且,如果您真的想更改表 - 更改后不要忘记VACUUM它。

于 2013-05-06T10:22:54.890 回答