签到成功

知道了

CNDBA社区CNDBA社区

openGauss 内存优化表(Memory-Optimized Table:MOT) 说明

2023-05-31 15:58 1456 0 原创 openGauss
作者: dave

1. MOT 概述

openGauss引入了MOT存储引擎,它是一种事务性行存储,针对多核和大内存服务器进行了优化。MOT完全支持ACID特性,并包括严格的持久性和高可用性支持。

MOT与基于磁盘的普通(堆)表并排创建。MOT的有效设计实现了几乎完全的SQL覆盖,并且支持完整的数据库功能集,如存储过程和自定义函数。

http://www.cndba.cn/dave/article/121043

MOT命令的语法与基于磁盘的表的语法相同,并支持大多数标准,如PostgreSQL SQL、DDL和DML命令和功能,如存储过程。只有MOT的创建和删除表语句与openGauss中基于磁盘的表的语句不同。

MOT在高性能(查询和事务延迟)、高可扩展性(吞吐量和并发量)以及高资源利用率(某些程度上节约成本)方面拥有显著优势。

  1. 低延迟(Low Latency):提供快速的查询和事务响应时间。
  2. 高吞吐量(High Throughput):支持峰值和持续高用户并发。
  3. 高资源利用率(High Resource Utilization):充分利用硬件。

使用了MOT的应用程序可以达到普通表2.5到4倍的吞吐量。

http://www.cndba.cn/dave/article/121043

所有MOT数据和索引都驻留在内存中,因此内存容量必须能够支撑数据容量,并且还有进一步增长的空间。

MOT是一个持久的数据库,使用永久性存储设备(磁盘/SSD/NVMe驱动器)进行事务日志操作和存储定期检查点。

推荐采用低延迟的存储设备,如配置RAID-1的SSD、NVMe或者任何企业级存储系统。当使用适当的硬件时,数据库事务处理和竞争将成为瓶颈,而非IO。

http://www.cndba.cn/dave/article/121043

1.1 内存配置

openGauss数据库和标准Postgres类似,其内存上限是由max_process_memory设置的,该上限在postgresql.conf文件中定义。MOT及其所有组件和线程,都驻留在openGauss进程中。因此,分配给MOT的内存也是在整个openGauss数据库进程的max_process_memory定义的上限内分配。

MOT为自己保留的内存是maxprocess_memory的一部分。可以通过百分比或通过小于max_process_memory的绝对值定义。这个部分在mot.conf配置文件中由 _mot _memory配置项定义。

max_process_memory中可以除了被MOT使用的部分之外,必须为Postgres(openGauss)封装留下至少2GB的可用空间。为了确保这一点,MOT在数据库启动过程中会进行如下校验:

(max_mot_global_memory + max_mot_local_memory) + 2GB < max_process_memory

http://www.cndba.cn/dave/article/121043

当总内存使用量接近所选内存限制时,MOT不再允许插入额外数据。不再允许额外数据插入的阈值即是MOT最大内存百分比(如上所述,这是一个计算值)。MOT最大内存百分比默认值为90,即90%。尝试添加超过此阈值的额外数据时,会向用户返回错误,并且也会注册到数据库日志文件中。

1.2 全局和本地

MOT使用的内存由两部分组成:

  1. 全局内存:全局内存是一个长期内存池,包含MOT的数据和索引。它平均分布在NUMA节点,由所有CPU核共享。
  2. 本地内存:本地内存是用于短期对象的内存池。它的主要使用者是处理事务的会话。这些会话将数据更改存储在专门用于相关特定事务的内存部分(称为事务专用内存)。在提交阶段,数据更改将被移动到全局内存中。内存对象分配以NUMA-local方式执行,以实现尽可能低的延迟。

被释放的对象被放回相关的内存池中。在事务期间尽量少使用操作系统内存分配(malloc)函数,避免不必要的锁和锁存。

这两个内存的分配由专用的min/max_mot_global_memory和min/max_mot_local_memory设置控制。如果MOT全局内存使用量太接近最大值,则MOT会保护自身,不接受新数据。超出此限制的内存分配尝试将被拒绝,并向用户报告错误。

在典型的OLTP工作负载中,平均读写比例为80:20,每个表的MOT内存使用率比基于磁盘的表高60%(包括数据和索引)。

如下统计查询可以确定customer表的数据大小和customer_pkey索引大小:

数据大小:pg_relation_size(’customer’);
索引:pg_relation_size(’customer_pkey’);http://www.cndba.cn/dave/article/121043

2. MOT使用

2.1 授予用户权限

以授予数据库用户对MOT存储引擎的访问权限为例。每个数据库用户仅执行一次,通常在初始配置阶段完成。

要使特定用户能够创建和访问MOT(DDL、DML、SELECT),以下语句只执行一次:

openGauss=# GRANT USAGE ON FOREIGN SERVER mot_server TO omm;
GRANT
openGauss=#

2.2 创建/删除MOT

只有MOT中的创建和删除表语句与openGauss中基于磁盘的表的语句不同。SELECT、DML和DDL的所有其他命令的语法对于MOT表和openGauss基于磁盘的表是一样的。

创建MOT:

openGauss=# create FOREIGN table mot(id int) server mot_server;
ERROR:  Cannot create MOT tables while incremental checkpoint is enabled.
openGauss=#

以上语句中:

  1. 始终使用FOREIGN关键字引用MOT。
  2. 在创建MOT表时,[server mot_server]部分是可选的,因为MOT是一个集成的引擎,而不是一个独立的服务器。
  3. openGauss默认开启了增量检查点,无法创建MOT。需要先将enable_incremental_checkpoint设置为off。
[omm@oracle2 ~]$ gs_guc set -N all -I all -c "enable_incremental_checkpoint=off"
The gs_guc run with the following arguments: [gs_guc -N all -I all -c enable_incremental_checkpoint=off set ].
Begin to perform the total nodes: 3.
Popen count is 3, Popen success count is 3, Popen failure count is 0.
Begin to perform gs_guc for datanodes.
Command count is 3, Command success count is 3, Command failure count is 0.

Total instances: 3. Failed instances: 0.
ALL: Success to perform gs_guc!
[omm@oracle2 ~]$ gs_om -t restart

openGauss=# create FOREIGN table mot(id int) server mot_server;
CREATE FOREIGN TABLE

openGauss=# /d mot
         Foreign table "public.mot"
 Column |  Type   | Modifiers | FDW Options 
--------+---------+-----------+-------------
 id     | integer |           | 
Server: mot_server
FDW permition: read/write

删除MOT表:

openGauss=# drop FOREIGN table mot;
DROP FOREIGN TABLE

ALTER TABLE:http://www.cndba.cn/dave/article/121043

支持添加列、删除列和重命名列。

2.3 创建索引

支持标准的PostgreSQL创建和删除索引语句。

http://www.cndba.cn/dave/article/121043

openGauss=# create index mot_index1 on mot(id) ;
ERROR:  Can't create index on nullable columns
DETAIL:  Column id is nullable

这里因为id列是允许空的,所以不能创建索引,创建一个非空列:

openGauss=# create FOREIGN table mot2(id int not null);
CREATE FOREIGN TABLE
openGauss=# create index mot_index1 on mot2(id);
CREATE INDEX

创建一个用于TPC-C的ORDER表,并创建索引:

openGauss=# create FOREIGN table bmsql_oorder ( 
  o_w_id       integer      not null, 
  o_d_id       integer      not null, 
  o_id         integer      not null, 
  o_c_id       integer not null, 
  o_carrier_id integer,          
  o_ol_cnt     integer, 
  o_all_local  integer, 
  o_entry_d    timestamp, 
  primary key (o_w_id, o_d_id, o_id) 
); 

openGauss=# create index  bmsql_oorder_index1 on bmsql_oorder(o_w_id, o_d_id, o_c_id, o_id) ;
CREATE INDEX

2.4 将磁盘表转换为MOT

2.4.1 操作说明

目前openGauss不支持直接将磁盘表转换为MOT,可以使用gs_dump工具导出数据,然后再利用gs_restore工具导入MOT表。http://www.cndba.cn/dave/article/121043

在转换之前还需要先检查磁盘表的列实际都满足MOT,MOT表有很多列类型不支持,具体不支持的列可以参考官方手册:

MOT SQL覆盖和限制
https://docs.opengauss.org/zh/docs/5.0.0/docs/DatabaseAdministrationGuide/MOT-SQL%E8%A6%86%E7%9B%96%E5%92%8C%E9%99%90%E5%88%B6.html

如果有不支持特定列,需要先对原磁盘表进行修改,使其仅包含MOT支持的类。

转换过程如下:

  1. 暂停应用程序活动。
  2. 使用gs_dump工具将表数据转储到磁盘的物理文件中。请确保使用data only。
  3. 重命名原始基于磁盘的表。
  4. 创建同名同模式的MOT。请确保使用创建FOREIGN关键字指定该表为MOT。
  5. 使用gs_restore将磁盘文件的数据加载/恢复到数据库表中。
  6. 浏览或手动验证所有原始数据是否正确导入到新的MOT中。
  7. 恢复应用程序活动。

2.4.2 操作示例

查看原表结构和数据:

openGauss=# /d+ cndba
                                 Table "public.cndba"
 Column  |          Type          | Modifiers | Storage  | Stats target | Description 
---------+------------------------+-----------+----------+--------------+-------------
 id      | integer                |           | plain    |              | 
 website | character varying(100) |           | extended |              | 
Indexes:
    "idx_cndba_id" btree (id) TABLESPACE pg_default
Has OIDs: no
Options: orientation=row, compression=no

openGauss=# select * from cndba limit 5;
 id |       website        
----+----------------------
  1 | https://www.cndba.cn
  1 | https://www.cndba.cn
  2 | https://www.cndba.cn
  3 | https://www.cndba.cn
  4 | https://www.cndba.cn
(5 rows)

使用gs_dump转储表数据:

[omm@oracle2 ~]$ gs_dump -Fc postgres -a --table cndba -f cndba.dump -p 15500 -U omm -W omm@123456 
gs_dump[port='15500'][postgres][2023-05-31 15:24:56]: dump database postgres successfully
gs_dump[port='15500'][postgres][2023-05-31 15:24:56]: total time: 3716  ms
[omm@oracle2 ~]$ ll cndba.dump 
-rw------- 1 omm dbgrp 1042 5月  31 15:24 cndba.dump
[omm@oracle2 ~]$

openGauss 逻辑备份与恢复 操作示例
https://www.cndba.cn/dave/article/116549

重命名源表:

openGauss=# alter table cndba rename to cndba2;
ALTER TABLE

创建与源表完全相同的MOT:http://www.cndba.cn/dave/article/121043


openGauss=# create foreign table cndba(id int, website  varchar(100)); 
CREATE FOREIGN TABLE

将源转储数据导入到新MOT中:

[omm@oracle2 ~]$ gs_restore -C -d postgres cndba.dump -p 15500 -U omm -W omm@123456 
start restore operation ...
table cndba complete data imported !
Finish reading 3 SQL statements!
end restore operation ...
restore operation successful
total time: 27  ms
[omm@oracle2 ~]$

验证:

openGauss=# /d+ cndba
                                    Foreign table "public.cndba"
 Column  |          Type          | Modifiers | FDW Options | Storage  | Stats target | Description 
---------+------------------------+-----------+-------------+----------+--------------+-------------
 id      | integer                |           |             | plain    |              | 
 website | character varying(100) | collate C |             | extended |              | 
Server: mot_server
FDW permition: read/write
Has OIDs: no

openGauss=# select * from cndba limit 5;
 id |       website        
----+----------------------
  1 | https://www.cndba.cn
  1 | https://www.cndba.cn
  2 | https://www.cndba.cn
  3 | https://www.cndba.cn
  4 | https://www.cndba.cn
(5 rows)

2.5 监控MOT

查看表和索引大小:

openGauss=# select pg_relation_size('cndba');
 pg_relation_size 
------------------
            40960
(1 row)

openGauss=#

检查MOT全局内存大小,主要是数据和索引:

openGauss=# select * from mot_global_memory_detail();
 numa_node | reserved_size | used_size 
-----------+---------------+-----------
        -1 |      25165824 |  25165824
         0 |      25165824 |  25165824
(2 rows)


其中,
1.-1为总内存。
2.0之后的正整数表示NUMA内存节点。

检查MOT本地内存大小,包括会话内存:http://www.cndba.cn/dave/article/121043

openGauss=# select * from mot_local_memory_detail();
 numa_node | reserved_size | used_size 
-----------+---------------+-----------
        -1 |      20971520 |  20971520
         0 |      20971520 |  20971520
(2 rows)

会话管理的内存从MOT本地内存中获取。所有活动会话(连接)的内存使用量可以通过以下查询:

openGauss=# select * from mot_session_memory_detail();
           sessid           | total_size | free_size | used_size 
----------------------------+------------+-----------+-----------
 0.0                        |    6291456 |   3640374 |   2651082
 0.0                        |    6291456 |   3640374 |   2651082
 0.0                        |    6291456 |   3640374 |   2651082
 1685517610.139921462327040 |    2097152 |    492598 |   1604554
(4 rows)

openGauss=# 

其中:
total_size:分配给会话的内存。
free_size:未使用的内存。
used_size:使用中的内存。

DBA可以通过以下查询确定当前会话使用的本地内存状态:

openGauss=# select * from mot_session_memory_detail() where sessid =pg_current_sessionid();
           sessid           | total_size | free_size | used_size 
----------------------------+------------+-----------+-----------
 1685517610.139921462327040 |    2097152 |    492598 |   1604554
(1 row)

版权声明:本文为博主原创文章,未经博主允许不得转载。

用户评论
* 以下用户言论只代表其个人观点,不代表CNDBA社区的观点或立场
dave

dave

关注

人的一生应该是这样度过的:当他回首往事的时候,他不会因为虚度年华而悔恨,也不会因为碌碌无为而羞耻;这样,在临死的时候,他就能够说:“我的整个生命和全部精力,都已经献给世界上最壮丽的事业....."

  • 2239
    原创
  • 3
    翻译
  • 546
    转载
  • 186
    评论
  • 访问:6601462次
  • 积分:4248
  • 等级:核心会员
  • 排名:第1名
精华文章
    最新问题
    查看更多+
    热门文章
      热门用户
      推荐用户
        Copyright © 2016 All Rights Reserved. Powered by CNDBA · 皖ICP备2022006297号-1·

        QQ交流群

        注册联系QQ