如何在PostgreSQL正确的 使用UUID 作为主键
UUID 经常用作数据库表主键。它们易于生成,易于在分布式系统之间共享并保证唯一性。
考虑到 UUID 的大小,这是否是一个正确的选择值得怀疑,但通常这不是由我们决定的。
本文的重点不是“UUID 是否是主键的正确格式”,而是如何有效地使用 UUID 作为 PostgreSQL 的主键。
Postgres 数据的UUID类型
UUID 可以被视为一个字符串,并且可能很容易将它们存储为字符串。 Postgres 具有用于存储字符串的灵活数据类型: text
,并且通常用作存储 UUID 值的主键。
它是正确的数据类型吗?当然不是。
Postgres 有一个专用于 UUID 的数据类型: uuid
。 UUID 是 128 位数据类型,因此存储单个值需要 16 个字节。 text
数据类型有 1 或 4 个字节的开销加上存储实际的字符串。
这些差异在小表中并不那么重要,但一旦开始存储数十万或数百万行,就会成为问题。
我进行了一个实验,看看实践中有何不同。有两个表只有一列 - id
作为主键。第一个表使用 text
,第二个表使用 uuid
:
create table bank_transfer(
id text primary key
);
create table bank_transfer_uuid(
id uuid primary key
);
我没有指定主键索引的类型,因此 Postgres 使用默认的 B 树。
然后我使用 Spring 的 JdbcTemplate
中的 batchUpdate
向每个表插入 10 000 000
行:
jdbcTemplate.batchUpdate("insert into bank_transfer (id) values (?)",
new BatchPreparedStatementSetter() {
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, UUID.randomUUID().toString());
}
@Override
public int getBatchSize() {
return 10_000_000;
}
});
jdbcTemplate.