在PG中,有一种表的类型为unlogged table,名如其字,该种类型的表不会写入wal日志中,所以在写入的速度上比普通的堆表快很多,但是该表在数据库崩溃的时候,会被truncate,数据会丢失,而且该表也不支持流复制,所以在standby节点是无法查到该表数据的。在该表上创建的索引也是unlogged索引。最近看到一篇博客描述了unlogged table的一些优缺点。我这里也再次解读一下,留下一些自己的见解。
建表语句如下:
create unlogged table unlogged_table (a int primary key);
CREATE TABLE
insert into unlogged_table select generate_series(1,1000000);
INSERT 0 1000000
unlogged表和logged表可以互相转换,如下例子:
#接上面例子,主键索引也是unlogged
postgres=# \di+ unlogged_table_pkey
List of relations
Schema | Name | Type | Owner | Table | Persistence | Size | Description
--------+---------------------+-------+----------+----------------+-------------+-------+-------------
public | unlogged_table_pkey | index | postgres | unlogged_table | unlogged | 21 MB |
(1 row)
#查看表物理存放路径
postgres=# select pg_relation_filepath('unlogged_table');
pg_relation_filepath
----------------------
base/13580/43099
(1 row)
#转为logged表,物理文件路径已变更,说明表重建了,而且索引也重建了
postgres=# alter table unlogged_table set logged;
ALTER TABLE
postgres=# select pg_relation_filepath('unlogged_table');
pg_relation_filepath
----------------------
base/13580/43104
(1 row)
postgres=# \di+ unlogged_table_pkey
List of relations
Schema | Name | Type | Owner | Table | Persistence | Size | Description
--------+---------------------+-------+----------+----------------+-------------+-------+-------------
public | unlogged_table_pkey | index | postgres | unlogged_table | permanent | 21 MB |
(1 row)
#转换回unlogged表,物理文件变化了,可见表和索引还是重建了
postgres=# alter table unlogged_table set unlogged;
ALTER TABLE
postgres=# select pg_relation_filepath('unlogged_table');
pg_relation_filepath
----------------------
base/13580/43108
(1 row)
postgres=# select pg_relation_filepath('unlogged_table_pkey');
pg_relation_filepath
----------------------
base/13580/43111
(1 row)
由以上实验得出,在互相转换的时候一定要注意,在表转换的时候是无法被操作的。如果表很大,那么也会额外占用资源。因为要重建表和索引。另外注意一点,从logged转为unlogged会相对好一些,因为不写wal日志,只写表数据。
unlogged表的优缺点:
- 在实例奔溃后,unlogged表数据会被truncate,也就是会丢失数据
- unlogged表只能在主节点访问,备节点无法访问
- unlogged表不支持物理复制,也不支持逻辑复制
解释一下上图:
- 由于unlogged表不写wal,所以dml的效率更高,比如insert ,update会更快。
- vacuum的影响也更小,因为unlogged表不需要写wal,vacuum的效率也会提升,正常表的vacuum会写wal。
- 因为不写wal,所以在备份的时候不会备份unlogged表,备份集会更小。
- 普通表,也就是logged表,不会因为数据库崩溃而截断表,丢失所有数据,物理复制和逻辑复制都可用。
总结:
- 一般情况下我们是不需要使用unlogged表的,因为不能保证数据的持久性,这对于数据库来说是致命的。
- 正常的关闭数据库,或者正常的重启数据库,unlogged表的数据不会丢失,只有在不干净的关闭数据库,比如断电,或者因为其他原因数据库crash了,那么unlogged表的数据会被截断,用一个空的xxxx_init表文件代替。
- unlogged表也是要写物理文件的,只是不写wal日志,所以不是内存表,不要以为unlogged表都是在内存中操作的。
- unlogged表在生产环境建议不要使用,测试环境可以把玩一下。
参考:
https://www.crunchydata.com/blog/postgresl-unlogged-tables
https://pganalyze.com/blog/5mins-postgres-unlogged-tables