GaussDB存储引擎之Astore和Ustore
存储引擎概述
好比存储引擎向上对接SQL引擎,为SQL引擎提供或接收标准化的数据格式(元组或向量);向下对接存储介质,按照特定的数据组织方式,以数据页、压缩单元或其他形式为单位,通过存储介质提供的特定接口,对存储介质中的数据完成读写操作。
存储引擎需要满足一些通用的技术特征:
- 并发(Concurrency):通过合理的锁机制来控制并发,减少开销、提升整体性能。存储引擎可以提供多版本并发控制(MVCC)和快照读的功能。
- 事务(Transaction):满足事务ACID要求,即原子性、一致性、隔离性、持久性。
- 内存缓存(Buffer/Cache):通过专门的缓存池直接从内存中处理经常使用的数据,提升数据库处理速度。
- 检查点(Checkpoint):不同存储引擎一般都支持增量checkpoint/double write或全量checkpoint/full page write模式。
- 日志(Log):GaussDB采用物理日志,写入、传输和回放都对存储引擎透明。
GaussDB目前支持两种存储引擎:Astore和Ustore。
GaussDB中通过orientation
参数指定表数据存储方式(默认行存储),storage_type
参数指定存储引擎类型(默认Ustore)。
gaussdb=# create table t1(c1 int) with(orientation=row, storage_type=ustore);
gaussdb=# create table t2(c1 int) with(orientation=row, storage_type=astore);
gaussdb=# create table t3(c1 int) with(orientation=column, storage_type=astore);
🐬 如果orientation指定为ROW,且storage_type为空,此时创建出的表类型取决于GUC参数
enable_default_ustore_table
。该参数默认值为ON。
Astore存储引擎
Astore的优势
- Astore存储引擎没有回滚段机制,旧数据和最新版本的数据存储在一起。数据库Crash后重启时,不需要像Ustore那样进行复杂的恢复。
- Astore由于旧数据直接存储在数据文件中,不会报Snapshot too old这种错误。
- 由于回滚不用删除数据,因此数据的回滚很快。
- WAL日志更简单,仅需记录数据文件的变化,无需记录回滚段的变化。
- 支持回收站功能(闪回Drop和闪回Truncate)。
Ustore存储引擎
Ustore是目前GaussDB数据库的默认行存储引擎。
Ustore的优势
- 最新版本和历史版本数据分开存储,扫描范围比Astore更小。移除Astore的Hot Chain,非索引列、索引列更新,Heap均可原位更新,ROWID保持不变。历史版本可以批量回收,空间膨胀可控。
- B树索引增加事务信息,可以独立进行MVCC。增加了IndexOnlyScan的比例,大大减少回表次数。
- 不依赖Vacuum进行旧版本清理。独立的空间回收能力,索引与堆表解耦,可独立清理,IO平稳度度更优。
- 大并发更新同一行的场景,相对于Astore的ROWID会偏移,Ustore的原位更新机制保证了元组ROWID的稳定,先到先得,更新时延相对稳定。
- 支持闪回功能。
使用限制
- 单张表的字段数不能超过1600列。
- 在创建表或索引时可以指定初始的事务目录大小
init_td
,取值范围[2,128]
,默认为4。单页支持的最大并发不超过128。- Ustore表的最大元组长度(不含Toast)不能超过
8192 - MAXALIGN(56 + init_td * 26 + 4)
,其中MAXALIGN表示8字节对齐。否则会报错元组过长无法插入的报错。- Ustore索引元组长度不能超过
(8192 - MAXALIGN(28 + 3*4 + 3*10) - MAXALIGN(42))/3
,其中MAXALIGN表示8字节对齐。否则会报错元组过长无法插入的报错。- 索引最大列数不能超过32列。全局分区索引不能超过31列。
- 回滚段容量最大支持16TB。
最佳实践
- init_td怎么配置?
事务目录(TD)是Ustore表独有的用于存储页面事务信息的结构,TD的数量决定该数据页支持的最大并发数。
在创建表或索引时可以指定事务目录大小init_td
,取值范围[2,128]
。默认为4,表示同时支持4个并发事务修改该页。单页支持的最大并发不超过128。
init_td的配置需要考虑以下因素:
- 结合业务并发度分析是否需要手动配置该参数;
- 结合
wait available td
等待事件出现的频率来分析事物需要调整该参数。wait available td
等待事件可以通常查询pg_thread_wait_status
视图中wait_status
字段的值来统计。 - 如果需要扩容该参数,推荐按倍数进行测试。依次尝试8、16、32、48、…,并观测等待事件是否明显减少。
查看和修改init_td
参数:
--创建表指定init_td参数
gaussdb=# create table t1(title varchar) with(storage_type=ustore,init_td=2);
--查看init_td参数
gaussdb=# \d+ t1
--修改init_td参数
gaussdb=# alter table t1 set(init_td=8);
--查看线程等待事件
gaussdb=# select * from pg_thread_wait_status;
- fillfactor怎么配置?
页面填充率(fillfactor)与数据页能存储的元组数量、大小以及表的物理空间直接相关。
Ustore表的默认页面填充率为92%,预留8%的空间用于更新表的扩展、或用于TD列表的扩展。
fillfactor的配置需要考虑以下因素:
- 结合业务分析是否需要手动配置该参数;
- 如果表数据导入后只有查询或定长更新操作,可以将fillfactor设置为100%;
- 如果表数据导入后存在大量非定长更新,建议使用默认配置、或者调整为更小的值,以减少跨页更新带来的性能损耗。
查看和修改fillfactor
参数:
--创建表指定fillfactor参数
gaussdb=# create table tesla(x int) with(fillfactor=100);
--查看fillfactor参数
gaussdb=# \d+ tesla
--修改fillfactor参数
gaussdb=# alter table tesla set(fillfactor=92);
- 在线校验功能
在线校验功能可以有效预防数据块因编码逻辑错误而导致的逻辑坏块,默认开启UPAGE:UBTREE:UNDO
三个模块校验。
在线校验功能是Ustore存储引擎特有的。
关闭在线校验:
gs_guc reload -Z datanode -N all -I all -c "ustore_attr=''"
开启在线校验:
gs_guc reload -Z datanode -N all -I all -c "ustore_attr='ustore_verify_level=fast;ustore_verify_module=upage:ubtree:undo'"
- 回滚段大小怎么配置?
回滚段可以使用默认的参数值。也可以针对性地调整以下参数:
- (1)
undo_retention_time
:保留指定时间内的历史版本数据。
该参数的默认值为0,推荐值为900s,取值范围为0到3天,单位可以为s、min、h、d。
undo_retention_time的值越大,可以保留的历史版本数据越多,同时undo占用空间也会越大,对数据的扫描更新性能也会有影响。
使用undo统计信息系统函数gs_stat_undo
,入参为false时,查看输出的info
列中推荐的undo_retention_time推荐值。
- (2)
undo_space_limit_size
:保留指定空间大小的历史版本数据。
该参数的默认值为256GB,取值范围为800MB到16TB。
如果业务中存在长事务可能导致undo空间膨胀时,需要调大undo_space_limit_size参数。
如果查询视图系统函数gs_stat_undo
的curr_used_undo_size
发现不存在undo空间膨胀,可以恢复为原值。
- (3)
undo_limit_size_per_transaction
:单事务的占用undo空间。
如果调大了undo_space_limit_size参数,可以相应提高单事务平均占用undo空间限制undo_limit_size_per_transaction。
该参数默认值为32GB,取值范围为2MB到16TB。建议取值不超过undo_space_limit_size参数。
🐬 回滚段参数的优先级:
undo_retention_time
、undo_space_limit_size
、undo_limit_size_per_transaction
三个参数,先触发的阈值会先进行约束。