在我工作的地方,我们使用postgres数据库(8.3很快就会迁移到8.4),目前在数据库中使用枚举的问题上有一个小争论,我个人不喜欢db枚举类型,它将应用程序逻辑放在数据库中,并可能造成代码和数据之间的不匹配。我想知道postgres枚举的优点到底是什么(除了可读性),缺点是什么?
bjp0bcyl1#
枚举的优点是:
缺点是:
uoifb46i2#
枚举合并整型和字符串的优点于一身:它们像int一样小而快,像字符串一样可读,还有一个额外的优点是安全(你不会拼错枚举)。然而,如果你不关心可读性,int和enum一样好。
yzuktlbb3#
在PostgreSQL 13中,btree索引现在支持去重。如果我们以下面的真示例子为例,使用ENUM来表示一个拥有1亿行的日志表中的HTTP方法:
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 ---那就去做吧;只需确保避免过早优化并在生产中衡量结果。
在做决定时,请考虑流行的BI工具,如Metabase,不支持对ENUM进行过滤,但是,它们可以很好地对TEXT列进行过滤。@solaris:报告元数据库0.42.1和更高版本支持对ENUM值进行筛选。
2skhul334#
DB检查的好处是,没有其他枚举值不能记录在列中。对我来说最大的缺点是,只能通过在末尾添加值来修改枚举,但从Postgres 9.1开始,这已经是过去式了:https://stackoverflow.com/a/7834949/548473
3duebb1j5#
1.减少存储:当定义了255个或更少的ENUM元素时,Postgres每个元组只使用1个字节,或者256~65535个元素使用2个字节。这是因为,Postgres不是存储值的常量文字,而是存储该值的有序集合中的索引。对于非常大的表,这可能证明是一个显著的存储空间保存。1.任意排序:
CREATE TABLE opening_hours( week_day ENUM ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'), opening_time TIME, closing_time TIME );
如果您按week_day排序,它将按您指定的顺序排序,这在上面的情况下很方便。1.廉价约束:与在应用程序代码或一些复杂的数据库约束中进行检查不同,枚举检查以一种廉价的方式只添加了某些值。
3hvapo4f6#
与ENUM字段或不带外键的文本字段相比,我更喜欢带外键的文本字段。带外键的文本字段的优点:
缺点:
示例:
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... );
bnl4lu3b7#
关键是,如果允许应用程序执行DDL,它们更有可能导致阻塞或冲突。DDL最好离线执行,即在单用户模式下执行。
7条答案
按热度按时间bjp0bcyl1#
枚举的优点是:
缺点是:
uoifb46i2#
枚举合并整型和字符串的优点于一身:它们像int一样小而快,像字符串一样可读,还有一个额外的优点是安全(你不会拼错枚举)。
然而,如果你不关心可读性,int和enum一样好。
yzuktlbb3#
在PostgreSQL 13中,btree索引现在支持去重。如果我们以下面的真示例子为例,使用ENUM来表示一个拥有1亿行的日志表中的HTTP方法:
我们可以看到两者的索引大小是相同的,对于一个非规范化的表,每行节省几个字节并不能真正弥补缺点。
**PG 13+的经验法则:**使用ENUM将列约束为一组固定/静态值;不要使用它们来保存磁盘空间。
**可能的例外:**如果静态值的ENUM可以帮助您避免代价高昂的JOIN或FK ---那就去做吧;只需确保避免过早优化并在生产中衡量结果。
在做决定时,请考虑流行的BI工具,如Metabase,不支持对ENUM进行过滤,但是,它们可以很好地对TEXT列进行过滤。@solaris:报告元数据库0.42.1和更高版本支持对ENUM值进行筛选。
2skhul334#
DB检查的好处是,没有其他枚举值不能记录在列中。对我来说最大的缺点是,只能通过在末尾添加值来修改枚举,但从Postgres 9.1开始,这已经是过去式了:https://stackoverflow.com/a/7834949/548473
3duebb1j5#
优点
1.减少存储:当定义了255个或更少的ENUM元素时,Postgres每个元组只使用1个字节,或者256~65535个元素使用2个字节。这是因为,Postgres不是存储值的常量文字,而是存储该值的有序集合中的索引。对于非常大的表,这可能证明是一个显著的存储空间保存。
1.任意排序:
如果您按week_day排序,它将按您指定的顺序排序,这在上面的情况下很方便。
1.廉价约束:与在应用程序代码或一些复杂的数据库约束中进行检查不同,枚举检查以一种廉价的方式只添加了某些值。
缺点
3hvapo4f6#
与ENUM字段或不带外键的文本字段相比,我更喜欢带外键的文本字段。
带外键的文本字段的优点:
缺点:
示例:
bnl4lu3b7#
关键是,如果允许应用程序执行DDL,它们更有可能导致阻塞或冲突。DDL最好离线执行,即在单用户模式下执行。