我工作的地方使用PostgreSQL数据库(目前是8.3版本,即将迁移到8.4版本)。目前有一个小辩论关于在数据库中使用枚举。个人而言,我不喜欢数据库中的枚举类型。它会将应用程序逻辑放置在数据库中,并且可能导致代码和数据之间的不匹配。
我想知道除了可读性之外,PostgreSQL枚举类型的优点是什么?还有哪些缺点?
我工作的地方使用PostgreSQL数据库(目前是8.3版本,即将迁移到8.4版本)。目前有一个小辩论关于在数据库中使用枚举。个人而言,我不喜欢数据库中的枚举类型。它会将应用程序逻辑放置在数据库中,并且可能导致代码和数据之间的不匹配。
我想知道除了可读性之外,PostgreSQL枚举类型的优点是什么?还有哪些缺点?
枚举类型的优点包括:
缺点包括:
public | test_http_enum_idx | index | postgres | test | permanent | 789 MB |
public | test_http_test_idx | index | postgres | test | permanent | 789 MB |
我们可以看到,两者的索引大小相同。对于一个非规范化的表来说,每行节省几个字节并不能弥补其劣势。
PG 13+的经验法则: 使用ENUM约束列为一组固定/静态值;不要使用它们来节省磁盘空间。
可能有例外: 如果静态值的ENUM将帮助您避免昂贵的JOIN或FK-请继续;只需确保避免过早优化,并在生产中测量您的结果。
在做出决策时,请考虑到像Metabase这样的流行BI工具不支持枚举过滤,但是它们可以在TEXT列上正常工作。 @solaris:报告称,Metabase 0.42.1及更高版本支持对ENUM值进行过滤。
枚举类型将 int 类型和字符串类型的优势结合起来:它们像 int 类型一样小巧快速,又像字符串一样易读,此外还具有额外的安全性(您无法拼错枚举类型)。
但是,如果您不关心可读性,那么 int 类型就跟枚举类型一样好用。
作为优势,您还可以进行数据库检查,以确保在列中没有其他枚举值。对我来说最大的缺点是,只能通过将值添加到末尾来修改枚举,但自从Postgres 9.1以来,这已经过去了:https://dev59.com/0nI-5IYBdhLWcg3wm5lH#7834949
减少存储空间:当定义了255个或更少的ENUM元素时,Postgres每个元组只使用1个字节,对于256~65535个元素则使用2个字节。这是因为,Postgres不是存储值的常量文字,而是存储该值在有序集合中的索引。对于非常大的表格,这可能会节省大量的存储空间。
任意排序:
CREATE TABLE opening_hours(
week_day ENUM ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
opening_time TIME,
closing_time TIME
);
如果按照星期几排序,它将按照您指定的顺序排序,在上述情况下非常方便。
我更喜欢使用带有外键的文本字段,而不是枚举字段或没有外键的文本字段。
带有外键的文本字段的优点:
缺点:
示例:
create table example_table_example_type (
example_type text primary key
);
create table example_table (
example_type text not null references example_table_example_type(example_type),
...other fields...
);
问题在于,如果允许应用程序执行DDL操作,它们更有可能导致阻塞或冲突。最好将DDL操作离线执行,即在单用户模式下执行。