paimon,基础查询语句测试

数据湖存储解决方案之Paimon Flink 社区希望能够将 Flink 的 Streaming 实时计算能力和 Lakehouse 新架构优势进一步结合,推出新一代的 Streaming Lakehouse 技术,促进数据在数据湖上真正实时流动起来,并为用户提供实时离线一体化的开发体验。Flink 社区内部孵化了 Flink Table Store (简称 FTS )子项目,一个真正面向 Streaming 以及 Realtime的数据湖存储项目。 阅读详情

基础设置

-- 创建catalog/加载catalog,如果这个catalog已经存在就不会创建,自动加载元数据信息

CREATE CATALOG fs_paimon_catalog WITH (
'type' = 'paimon',
'warehouse' = 'hdfs://wsl01:8020/paimon/catalog'
);
-- 使用catalog
use catalog fs_paimon_catalog;

-- sqlClinet使用
-- 设置为批处理模式
SET 'execution.runtime-mode' = 'batch';
-- 设置为流处理模式
SET 'execution.runtime-mode' = 'streaming';
-- 设置查询结果显示方式,sql-clinet 特有
SET 'sql-client.execution.result-mode' = 'tableau';
-- 设置checkpoint,如果使用流模式,必须设置
SET 'execution.checkpointing.interval' = '10 s';



root@wsl01:~/soft/paimon/flink-1.17.0# cat fs_catalog.sql
CREATE CATALOG fs_catalog WITH (
    'type'='paimon',
    'warehouse'='file:/mnt/d/wsl/soft/paimon/catalog'
    -- 'warehouse' = 'hdfs://wsl01:8020/paimon/catalog'
);
use catalog fs_catalog ;
SET 'sql-client.execution.result-mode' = 'tableau';
-- 默认批处理
SET 'execution.runtime-mode' = 'batch';

-- 指定默认启动catalog
bin/sql-client.sh -i fs_catalog.sql


DDL

创建普通表

-- 普通表,没有主键

CREATE TABLE t_sample (
      user_id BIGINT,
      item_id BIGINT,
      behavior STRING,
      dt STRING,
      hh STRING
);

创建主键表

CREATE TABLE t_pk (
      user_id BIGINT,
      item_id BIGINT,
      behavior STRING,
      dt STRING,
      hh STRING,
      PRIMARY KEY (dt, hh, user_id) NOT ENFORCED
);

创建分区表

-- 分区表的分区字段必须是主键的子集

CREATE TABLE t_partition (
      user_id BIGINT,
      item_id BIGINT,
      behavior STRING,
      dt STRING,
      hh STRING,
      PRIMARY KEY (dt, hh, user_id) NOT ENFORCED
) PARTITIONED BY (dt, hh);

创建临时表

-- 如果进入paimon创建的catalog后,无法创建非paimon类型的表,如果需要借助第三方的表,需要创建临时表来使用

CREATE TEMPORARY TABLE t_temporary (
     user_id BIGINT,
     item_id BIGINT,
     behavior STRING,
     dt STRING,
     hh STRING,
     PRIMARY KEY (dt, hh, user_id) NOT ENFORCED
) WITH (
    'connector' = 'filesystem',
    'path' = 'file:///mnt/d/wsl/soft/paimon/temp_table.csv',
    'format' = 'csv'
);

复制表-AS,create table as


-- create as 创建主键表,

CREATE TABLE t_create_as_pk AS SELECT * FROM t_pk;
show create table t__pk;
show create table t_create_as_pk;


-- create as 创建分区表
show create table t_partition ;
CREATE TABLE t_create_as_partition AS SELECT * FROM t_partition;
show create table t_create_as_partition ;

上述执行结果告诉我们,create as 的表,只保留原表的字段,不保留其他属性信息


-- 通过with 重新指定,关于with的用法,参考flink
CREATE TABLE t_create_as_with with ('primary-key' = 'dt,hh','partition' = 'dt') AS SELECT * FROM t_pk  ;
show create table t_create_as_with;

上述执行结果告诉我们,create as 的表可以通过with 重新指定属性信息

复制表-LIKE,create table like

CREATE TABLE t_create_like like t_pk;
show create table t_pk;
show create table t_create_like;

上述执行结果告诉我们,create like 的表,保留全部信息

DML

常用管理语句

desc #{name}
show create table #{name}
show catalogs;
show databases;
show tables;

新增-普通表

insert into t_sample(user_id,item_id,behavior,dt,hh) values(100,100,'sing-sample','1','2');

insert into t_sample  values(101,101,'jump-sample','1','2');

insert into t_sample  select 102,102,'rap-sample','1','2';

Flink SQL> select * from t_sample;
+---------+---------+-------------+----+----+
| user_id | item_id |    behavior | dt | hh |
+---------+---------+-------------+----+----+
|     100 |     100 | sing-sample |  1 |  2 |
|     101 |     101 | jump-sample |  1 |  2 |
|     102 |     102 |  rap-sample |  1 |  2 |
+---------+---------+-------------+----+----+
3 rows in set

新增-主键表

insert into t_pk values(1,1,'sing','1','2');
insert into t_pk values(2,2,'jump','1','2');
insert into t_pk values(3,3,'rap','1','2');
Flink SQL> select * from t_pk;
+---------+---------+----------+----+----+
| user_id | item_id | behavior | dt | hh |
+---------+---------+----------+----+----+
|       1 |       1 |     sing |  1 |  2 |
|       2 |       2 |     jump |  1 |  2 |
|       3 |       3 |      rap |  1 |  2 |
+---------+---------+----------+----+----+
3 rows in set
insert into t_pk values(3,3,'basketball','1','2');
Flink SQL>  select * from t_pk;
+---------+---------+------------+----+----+
| user_id | item_id |   behavior | dt | hh |
+---------+---------+------------+----+----+
|       1 |       1 |       sing |  1 |  2 |
|       2 |       2 |       jump |  1 |  2 |
|       3 |       3 | basketball |  1 |  2 |
+---------+---------+------------+----+----+
3 rows in set

-- 我们发现,主键表,写入两条相同主键的数据,后者会覆盖前者
-- 主键表有一个默认引擎,默认是就是 'merge-engine' = 'deduplicate',因此才有这个效果

新增-分区表

insert into t_partition partition(dt='2024-10-08',hh='15')(user_id,item_id,behavior) values(1,1,'sing');
insert into t_partition partition(dt='2024-10-08',hh='15')(user_id,item_id,behavior) values(2,2,'jump');
insert into t_partition(user_id,item_id,behavior,dt,hh) values(3,3,'rap','2024-10-08','16');
insert into t_partition values(4,4,'basketball','2024-10-08','16');

Flink SQL> select * from t_partition;
+---------+---------+------------+------------+----+
| user_id | item_id |   behavior |         dt | hh |
+---------+---------+------------+------------+----+
|       1 |       1 |       sing | 2024-10-08 | 15 |
|       2 |       2 |       jump | 2024-10-08 | 15 |
|       3 |       3 |        rap | 2024-10-08 | 16 |
|       4 |       4 | basketball | 2024-10-08 | 16 |
+---------+---------+------------+------------+----+
4 rows in set


insert into t_partition as select * from t_sample;

insert into t_partition partition(dt='2099-10-08',hh='15')(user_id,item_id,behavior) select user_id,item_id,behavior from t_sample;

Flink SQL> select * from t_partition;
+---------+---------+-------------+------------+----+
| user_id | item_id |    behavior |         dt | hh |
+---------+---------+-------------+------------+----+
|       1 |       1 |        sing | 2024-10-08 | 15 |
|       2 |       2 |        jump | 2024-10-08 | 15 |
|     100 |     100 | sing-sample | 2099-10-08 | 15 |
|     101 |     101 | jump-sample | 2099-10-08 | 15 |
|     102 |     102 |  rap-sample | 2099-10-08 | 15 |
|       3 |       3 |         rap | 2024-10-08 | 16 |
|       4 |       4 |  basketball | 2024-10-08 | 16 |
|     100 |     100 | sing-sample |          1 |  2 |
|     101 |     101 | jump-sample |          1 |  2 |
|     102 |     102 |  rap-sample |          1 |  2 |
+---------+---------+-------------+------------+----+
10 rows in set

Flink SQL> insert overwrite t_partition(user_id,item_id,behavior) values(5,5,'non-partition');
[ERROR] Could not execute SQL statement. Reason:
org.apache.calcite.sql.validate.SqlValidatorException: Column 'dt' has no default value and does not allow NULLs

以上多种写入方式都支持,把分区字段当成普通字段用就行,但是分区字段不能为空

新增-覆盖写入

Flink SQL> select * from t_pk;
+---------+---------+------------+----+----+
| user_id | item_id |   behavior | dt | hh |
+---------+---------+------------+----+----+
|       1 |       1 |       sing |  1 |  2 |
|       2 |       2 |       jump |  1 |  2 |
|       3 |       3 | basketball |  1 |  2 |
+---------+---------+------------+----+----+

insert into t_pk values(10,10,'overwrite','1','2');

Flink SQL> select * from t_pk;
+---------+---------+-----------+----+----+
| user_id | item_id |  behavior | dt | hh |
+---------+---------+-----------+----+----+
|      10 |      10 | overwrite |  1 |  2 |
+---------+---------+-----------+----+----+
1 row in set

overwrite 会直接清空表,不会考虑主键


insert into t_partition partition(dt='2024-10-08',hh='15')(user_id,item_id,behavior) values(1,1,'sing');
insert into t_partition partition(dt='2024-10-08',hh='15')(user_id,item_id,behavior) values(2,2,'jump');
insert into t_partition partition(dt='2024-10-09',hh='15')(user_id,item_id,behavior) values(3,3,'rap');
Flink SQL> select * from t_partition;
+---------+---------+----------+------------+----+
| user_id | item_id | behavior |         dt | hh |
+---------+---------+----------+------------+----+
|       3 |       3 |      rap | 2024-10-09 | 15 |
|       1 |       1 |     sing | 2024-10-08 | 15 |
|       2 |       2 |     jump | 2024-10-08 | 15 |
+---------+---------+----------+------------+----+
3 rows in set

insert overwrite t_partition partition(dt='2024-10-08',hh='15')(user_id,item_id,behavior) values(4,4,'basketball');

Flink SQL> select * from t_partition;
+---------+---------+------------+------------+----+
| user_id | item_id |   behavior |         dt | hh |
+---------+---------+------------+------------+----+
|       3 |       3 |        rap | 2024-10-09 | 15 |
|       4 |       4 | basketball | 2024-10-08 | 15 |
+---------+---------+------------+------------+----+
2 rows in set

分区表只会overwrite 当前要写入分区


Flink SQL> select * from t_partition;
+---------+---------+----------+------------+----+
| user_id | item_id | behavior |         dt | hh |
+---------+---------+----------+------------+----+
|       3 |       3 |      rap | 2024-10-09 | 15 |
|       1 |       1 |     sing | 2024-10-08 | 15 |
|       2 |       2 |     jump | 2024-10-08 | 15 |
+---------+---------+----------+------------+----+
3 rows in set
-- 对指定分区写入空记录,没有效果
 INSERT OVERWRITE t_partition  PARTITION (`dt` = '2024-10-08', `hh` = '15') SELECT user_id,item_id,behavior FROM t_partition WHERE false;
 
 Flink SQL> select * from t_partition;
+---------+---------+----------+------------+----+
| user_id | item_id | behavior |         dt | hh |
+---------+---------+----------+------------+----+
|       3 |       3 |      rap | 2024-10-09 | 15 |
|       1 |       1 |     sing | 2024-10-08 | 15 |
|       2 |       2 |     jump | 2024-10-08 | 15 |
+---------+---------+----------+------------+----+
3 rows in set
 
 -- 对指定分区写入空记录,指定 /*+ OPTIONS('dynamic-partition-overwrite'='false') */,会清空指定的分区
 INSERT OVERWRITE t_partition  /*+ OPTIONS('dynamic-partition-overwrite'='false') */  PARTITION (`dt` = '2024-10-08', `hh` = '15') SELECT user_id,item_id,behavior FROM t_partition WHERE false;
Flink SQL> select * from t_partition;
+---------+---------+----------+------------+----+
| user_id | item_id | behavior |         dt | hh |
+---------+---------+----------+------------+----+
|       3 |       3 |      rap | 2024-10-09 | 15 |
+---------+---------+----------+------------+----+
1 row in set

 -- 不指定分区写入空记录,指定 /*+ OPTIONS('dynamic-partition-overwrite'='false') */,会清空所有分区,truncate
INSERT OVERWRITE t_partition /*+ OPTIONS('dynamic-partition-overwrite'='false') */ SELECT * FROM t_partition WHERE false;

Flink SQL> select * from t_partition;
Empty set

/*+ OPTIONS('dynamic-partition-overwrite'='false') */ Flink默认的覆盖模式是动态分区覆盖 (即Paimon只删除覆盖数据中出现的分区)。可以配置动态分区覆盖将其更改为静态覆盖。

paimon 没有truncate,因此我们可以借助overwite+静态覆盖,这个实现truncate

查询


修改

Important table properties setting:

  • Only primary key table supports this feature. 表必须有主键
  • MergeEngine needs to be deduplicate or partial-update to support this feature. 合并引擎必须为deduplicate,以后会支持partial-update
  • Do not support updating primary keys. 不能修改主键
  • Flink 版本1.17 及以上版本才支持
  • 必须是批处理模式
UPDATE table_identifier SET column1 = value1, column2 = value2, ... WHERE condition;

Flink SQL> select * from t_partition;
+---------+---------+-------------+----+----+
| user_id | item_id |    behavior | dt | hh |
+---------+---------+-------------+----+----+
|     100 |     100 | sing-sample |  1 |  2 |
|     101 |     101 | jump-sample |  1 |  2 |
|     102 |     102 |  rap-sample |  1 |  2 |
+---------+---------+-------------+----+----+
3 rows in set

update t_partition set behavior = 'baskteball-sample' where user_id =100;

Flink SQL> select * from t_partition;
+---------+---------+-------------------+----+----+
| user_id | item_id |          behavior | dt | hh |
+---------+---------+-------------------+----+----+
|     100 |     100 | baskteball-sample |  1 |  2 |
|     101 |     101 |       jump-sample |  1 |  2 |
|     102 |     102 |        rap-sample |  1 |  2 |
+---------+---------+-------------------+----+----+
3 rows in set

删除


常用属性

CREATE TABLE my_table (
    user_id BIGINT,
    item_id BIGINT,
    behavior STRING,
    dt STRING,
    hh STRING,
    PRIMARY KEY (dt, hh, user_id) NOT ENFORCED
) PARTITIONED BY (dt, hh);

统计数优化

paimon 会默认为每一列添加3个统计属性:最大值、最小值、null值数量

有四种配置来约束统计属性

  • full:为所有数据添加最大值、最小值、null值数量统计
  • truncate(length):截断length长度后,为所有数据添加最大值、最小值、null值数量统计,这个是默认值:默认length 16,为了避免长文本字段的统计
  • counts:只对null值数量统计
  • none:不统计

如果需要修改某个字段的统计属性

  • fields.{field_name}.stats-mode,with ( ‘fields.behavior.stats-mode’ = ‘full’ )

官网原文:https://paimon.apache.org/docs/master/flink/sql-ddl/#specify-statistics-mode
在这里插入图片描述

字段默认值

paimon表可以设置字段默认值,但是 不能 对主键字段设置默认值

如果需要修改某个字段的统计属性

  • fields.{field_name}.default-value
  • with ( ‘fields.behavior.default-value’ = ‘sing’ )

官网原文:https://paimon.apache.org/docs/master/flink/sql-ddl/#field-default-value
在这里插入图片描述

聚类写入

在批作业中配置该参数可以启用聚类写入功能,使数据在特定列上按大小范围聚集分布,从而提升该列的查询速度。只能在批处理或者append table(流处理)中使用。

多个列名请使用英文逗号(,)进行分隔,例如’col1,col2’。

  • sink.clustering.by-columns
  • with ( ‘sink.clustering.by-columns’ = ‘user_id,item_id’ )

也可以使用Hints

  • INSERT INTO my_table /*+ OPTIONS(‘sink.clustering.by-columns’ = ‘a,b’) */ SELECT * FROM source;

动态覆盖

Flink overwrite模式,在分区表中默认是动态分区覆盖,也就是说在使用overwrite时,只覆盖当前写入分区的数据,写入数据为空时,不进行覆盖,我们可以设置为静态覆盖,当写入数据为空时,也会覆盖。如果写入的分区为空则覆盖所有分区!

Hints,跟在表的后边,也就是声明本次sql的执行策略,dynamic-partition-overwrite=false > 静态覆盖,truncate的替代语法(TRUNCATE TABLE my_table 需要flink 1.18 之后才支持)
INSERT OVERWRITE my_table /*+ OPTIONS(‘dynamic-partition-overwrite’=‘false’) */

批处理时间旅行

在批处理模式下,每一个表,在发生数据变化时会保留一份快照信息,我们可以在元数据目录找到
RESET ‘execution.checkpointing.interval’;
SET ‘execution.runtime-mode’ = ‘batch’;

root@wsl01:~/soft/paimon/catalog/default.db/t_pk/snapshot# ll
total 28
drwxrwxrwx 1 root root 4096 Oct  8 17:13 ./
drwxrwxrwx 1 root root 4096 Oct  8 16:58 ../
-rwxrwxrwx 1 root root    1 Oct  8 16:58 EARLIEST*
-rwxrwxrwx 1 root root    1 Oct  8 17:13 LATEST*
-rwxrwxrwx 1 root root  621 Oct  8 16:58 snapshot-1*
-rwxrwxrwx 1 root root  621 Oct  8 16:58 snapshot-2*
-rwxrwxrwx 1 root root  621 Oct  8 16:58 snapshot-3*
-rwxrwxrwx 1 root root  621 Oct  8 16:59 snapshot-4*
-rwxrwxrwx 1 root root  621 Oct  8 17:12 snapshot-5*
-rwxrwxrwx 1 root root  623 Oct  8 17:12 snapshot-6*
-rwxrwxrwx 1 root root  625 Oct  8 17:13 snapshot-7*

我们可以指定快照版本进行查询,比如 我要查询快照1版本的数据和快照2版本的数据有什么区别

Flink SQL> select * from t_pk /*+ OPTIONS('scan.snapshot-id' = '1') */;
+---------+---------+----------+----+----+
| user_id | item_id | behavior | dt | hh |
+---------+---------+----------+----+----+
|       1 |       1 |     sing |  1 |  2 |
+---------+---------+----------+----+----+
1 row in set

Flink SQL> select * from t_pk /*+ OPTIONS('scan.snapshot-id' = '2') */;
+---------+---------+----------+----+----+
| user_id | item_id | behavior | dt | hh |
+---------+---------+----------+----+----+
|       1 |       1 |     sing |  1 |  2 |
|       2 |       2 |     jump |  1 |  2 |
+---------+---------+----------+----+----+

通过查询我们可以得知,在1版本写入了一条数据1,在2版本写入了一条数据2
每一个表都有一个快照表,我们可以从快照表中获取所有的快照信息和变化情况


Flink SQL> SELECT * FROM t_pk$snapshots;
+-------------+-----------+--------------------------------+---------------------+-------------+-------------------------+--------------------------------+--------------------------------+-------------------------+--------------------+--------------------+------------------------+----------------------+
| snapshot_id | schema_id |                    commit_user |   commit_identifier | commit_kind |             commit_time |             base_manifest_list |            delta_manifest_list | changelog_manifest_list | total_record_count | delta_record_count | changelog_record_count |            watermark |
+-------------+-----------+--------------------------------+---------------------+-------------+-------------------------+--------------------------------+--------------------------------+-------------------------+--------------------+--------------------+------------------------+----------------------+
|           1 |         0 | 1012627f-bc72-4c6f-a270-5ab... | 9223372036854775807 |      APPEND | 2024-10-08 16:58:41.049 | manifest-list-2b0d3b30-b03c... | manifest-list-2b0d3b30-b03c... |                  <NULL> |                  1 |                  1 |                      0 | -9223372036854775808 |
|           2 |         0 | 7d768bf3-2e13-4e2d-b091-130... | 9223372036854775807 |      APPEND | 2024-10-08 16:58:46.607 | manifest-list-b8a205f2-f890... | manifest-list-b8a205f2-f890... |                  <NULL> |                  2 |                  1 |                      0 | -9223372036854775808 |
|           3 |         0 | e2193b18-9491-493a-8b40-88c... | 9223372036854775807 |      APPEND | 2024-10-08 16:58:56.868 | manifest-list-045c4b86-b7f5... | manifest-list-045c4b86-b7f5... |                  <NULL> |                  3 |                  1 |                      0 | -9223372036854775808 |
|           4 |         0 | 548ab8ae-92dd-496f-a066-e57... | 9223372036854775807 |      APPEND | 2024-10-08 16:59:25.990 | manifest-list-563fe53f-e48b... | manifest-list-563fe53f-e48b... |                  <NULL> |                  4 |                  1 |                      0 | -9223372036854775808 |
|           5 |         0 | 2ead5fde-9367-4e09-95cd-aed... | 9223372036854775807 |      APPEND | 2024-10-08 17:12:47.720 | manifest-list-b87abf82-80ef... | manifest-list-b87abf82-80ef... |                  <NULL> |                  5 |                  1 |                      0 | -9223372036854775808 |
|           6 |         0 | 2ead5fde-9367-4e09-95cd-aed... | 9223372036854775807 |     COMPACT | 2024-10-08 17:12:48.638 | manifest-list-b87abf82-80ef... | manifest-list-b87abf82-80ef... |                  <NULL> |                  4 |                 -1 |                      0 | -9223372036854775808 |
|           7 |         0 | ec784398-da6c-48e9-8525-ea6... | 9223372036854775807 |   OVERWRITE | 2024-10-08 17:13:09.135 | manifest-list-f64997fa-77dc... | manifest-list-f64997fa-77dc... |                  <NULL> |                  1 |                 -3 |                      0 | -9223372036854775808 |
+-------------+-----------+--------------------------------+---------------------+-------------+-------------------------+--------------------------------+--------------------------------+-------------------------+--------------------+--------------------+------------------------+----------------------+
7 rows in set

Flink SQL> select * from t_pk /*+ OPTIONS('scan.snapshot-id' = '4') */;
+---------+---------+------------+----+----+
| user_id | item_id |   behavior | dt | hh |
+---------+---------+------------+----+----+
|       1 |       1 |       sing |  1 |  2 |
|       2 |       2 |       jump |  1 |  2 |
|       3 |       3 | basketball |  1 |  2 |
+---------+---------+------------+----+----+
3 rows in set

上述查询结果告诉我们 快照id为4的时候数据最多,有4条,但是查询结果显示只有3条,那是因为批处理模式下,不显示删除的数据,而快照数据都统计了,我们可以查询audit表查询操作明细


Flink SQL> SELECT * FROM t_pk$audit_log /*+ OPTIONS('scan.snapshot-id' = '3') */;
+---------+---------+---------+----------+----+----+
| rowkind | user_id | item_id | behavior | dt | hh |
+---------+---------+---------+----------+----+----+
|      +I |       1 |       1 |     sing |  1 |  2 |
|      +I |       2 |       2 |     jump |  1 |  2 |
|      +I |       3 |       3 |      rap |  1 |  2 |
+---------+---------+---------+----------+----+----+
3 rows in set

Flink SQL> SELECT * FROM t_pk$audit_log /*+ OPTIONS('scan.snapshot-id' = '4') */;
+---------+---------+---------+------------+----+----+
| rowkind | user_id | item_id |   behavior | dt | hh |
+---------+---------+---------+------------+----+----+
|      +I |       1 |       1 |       sing |  1 |  2 |
|      +I |       2 |       2 |       jump |  1 |  2 |
|      +I |       3 |       3 | basketball |  1 |  2 |
+---------+---------+---------+------------+----+----+
3 rows in set

我们可以看到在 快照4的时候执行了一个 +I id=3的操作,把原来的id=3覆盖掉了,被覆盖掉的那条数据依然会被统计

流处理时间旅行

在流处理模式下,默认情况下,Streaming read 在第一次启动时会生成表上的最新快照,并继续读取最新的更改。
SET ‘execution.checkpointing.interval’=‘30s’;
SET ‘execution.runtime-mode’ = ‘streaming’;

读取最新的数据

SELECT * FROM ws_t /*+ OPTIONS('scan.mode' = 'latest') */

从指定快照id开始读取变更数据

SELECT * FROM ws_t /*+ OPTIONS('scan.snapshot-id' = '1') */;

常用的元数据表

表结构审计

Flink SQL> SELECT * FROM t_pk$schemas;
+-----------+--------------------------------+----------------+-----------------------+---------+---------+-------------------------+
| schema_id |                         fields | partition_keys |          primary_keys | options | comment |             update_time |
+-----------+--------------------------------+----------------+-----------------------+---------+---------+-------------------------+
|         0 | [{"id":0,"name":"user_id","... |             [] | ["dt","hh","user_id"] |      {} |         | 2024-10-08 16:33:10.895 |
+-----------+--------------------------------+----------------+-----------------------+---------+---------+-------------------------+
1 row in set

配置审计

Flink SQL> SELECT * FROM t_pk$options;
Empty set

操作审计

Flink SQL> SELECT * FROM t_pk$audit_log;
+---------+---------+---------+-----------+----+----+
| rowkind | user_id | item_id |  behavior | dt | hh |
+---------+---------+---------+-----------+----+----+
|      +I |      10 |      10 | overwrite |  1 |  2 |
+---------+---------+---------+-----------+----+----+
1 row in set

文件元数据

Flink SQL> SELECT * FROM t_pk$files;
+-----------+--------+--------------------------------+-------------+-----------+-------+--------------+--------------------+------------+------------+--------------------------------+--------------------------------+--------------------------------+---------------------+---------------------+-------------------------+
| partition | bucket |                      file_path | file_format | schema_id | level | record_count | file_size_in_bytes |    min_key |    max_key |              null_value_counts |                min_value_stats |                max_value_stats | min_sequence_number | max_sequence_number |           creation_time |
+-----------+--------+--------------------------------+-------------+-----------+-------+--------------+--------------------+------------+------------+--------------------------------+--------------------------------+--------------------------------+---------------------+---------------------+-------------------------+
|        [] |      0 | data-15fc7fe2-b3e7-485e-b60... |         orc |         0 |     0 |            1 |                948 | [1, 2, 10] | [1, 2, 10] | {behavior=0, dt=0, hh=0, it... | {behavior=overwrite, dt=1, ... | {behavior=overwrite, dt=1, ... |                   0 |                   0 | 2024-10-08 17:13:07.749 |
+-----------+--------+--------------------------------+-------------+-----------+-------+--------------+--------------------+------------+------------+--------------------------------+--------------------------------+--------------------------------+---------------------+---------------------+-------------------------+
1 row in set

标记元数据

Flink SQL> SELECT * FROM t_pk$tags;
Empty set

Paimon LSM Trees

Paimon 采用 LSM 树(日志结构合并树)作为文件存储的数据结构。

Sorted Runs

LSM 树将文件组织成多个Sorted Run。Sorted Run由一个或多个数据文件组成,并且每个数据文件恰好属于一个Sorted Run。
数据文件中的记录按其主键排序。在Sorted Run中,数据文件的主键范围永远不会重叠。

正如您所看到的,不同的Sorted Run可能具有重叠的主键范围,甚至可能包含相同的主键。查询LSM树时,必须合并所有Sorted Run,并且必须根据用户指定的合并引擎和每条记录的时间戳来合并具有相同主键的所有记录。
写入LSM树的新记录将首先缓存在内存中。当内存缓冲区满时,内存中的所有记录将被排序并刷新到磁盘。

Compaction

当越来越多的记录写入LSM树时,Sorted Run的数量将会增加。由于查询LSM树需要将所有Sorted Run合并起来,太多Sorted Run将导致查询性能较差,甚至内存不足。
为了限制Sorted Run的数量,我们必须偶尔将多个Sorted Run合并为一个大的Sorted Run。这个过程称为Compaction。
然而,Compaction是一个资源密集型过程,会消耗一定的CPU时间和磁盘IO,因此过于频繁的Compaction可能会导致写入速度变慢。这是查询和写入性能之间的权衡。 Paimon 目前采用了类似于 Rocksdb 通用压缩的Compaction策略。
默认情况下,当Paimon将记录追加到LSM树时,它也会根据需要执行Compaction。用户还可以选择在“专用Compaction作业”中独立执行所有Compaction。

调优

写入调优

流式写入检查点间隔

  • ck检查点间隔在允许的情况下调大,ck过于频繁会导致写入性能下降
  • 或者使用批处理模式
  • 并发checkpoints改成3 (‘execution.checkpointing.max-concurrent-checkpoints’)

写入缓冲区

  • 写入缓冲区缓存大小(write-buffer-size)大小调大,默认256M,默认先放到缓冲区,缓冲区满了之后再写sorted-run
  • 开始缓冲区溢出策略(write-buffer-spillable)=true,默认不设置

并行度

  • 一个桶1g的数据量,写入并行度(sink.parallelism)要小于等于桶的数量,最好等于,默认等于上游节点并行度

合并策略

  • paimon是lsm tree架构,每一个sorted-run 就是一个小的分片,当sorted-run 数量过多时,就会触发compaction,compaction 是一个资源密集型的过程为了防止sorted-run数量无限增长,当sorted-run数量达到写入停止阈值(num.sorted-run.stop-trigger)的时候就会暂停写入,默认值为达到compaction阈值+1(num-sorted-run.compaction-trigger+1),因此提高写入停止阈值就能保证停止写入不那么频繁,但是compaction的频率就会降低,会导致查询需要更多的merge on read,会影响查询的效率
    在这里插入图片描述在这里插入图片描述

文件格式

  • avro文件类型(行存储)可以提高写入吞吐量,但会降低压缩性能
  • 缺点:查询分析会变慢,如果该表有100列,但只查询了几列,则不能忽略行存储的IO。此外,压缩效率将降低,存储成本将增加。
  • 行存储的统计信息的收集有点贵,所以我建议也关闭统计信息。
  • 如果您不想将所有文件都修改为Avro格式,至少可以考虑将前几层的文件修改为Avro格式。您可以使用 ‘file.format.per.level’ = ‘0:avro,1:avro’ 将前两层中的文件指定为Avro格式。
file.format = avro
metadata.stats-mode = none
file.format.per.level = 0:avro,1:avro

压缩比

默认情况下,Paimon 使用 1 级的 zstd,你可以修改压缩算法:
‘file.compression.zstd-level’:默认 zstd 级别为 1。对于更高的压缩率,可以配置为 9,但读写速度会明显降低。
file.compression.zstd-level = 1

压缩稳定性

如果存储桶或资源太少,完全压缩可能会导致 checkpoint 超时,这是 Flink 的默认 检查点超时为 10 分钟。
如果希望在这种情况下也能保持稳定,则可以调高检查点超时,例如:
execution.checkpointing.timeout = 60 min

内存

在 Paimon writer 中,有三个主要地方会占用内存:

  • Writer 的内存缓冲区,由单个任务的所有 writer 共享和抢占。此内存值可通过 table 属性进行调整。write-buffer-size
  • 合并多个排序运行以进行压缩时消耗的内存。可以通过选项进行调整,以更改要合并的已排序运行数。num-sorted-run.compaction-trigger
  • 如果行非常大,在进行 Compaction 时,一次读取过多的数据行会消耗大量内存。减少选项可以减轻此案例的影响。read.batch-size
  • 写入列式 ORC 文件所消耗的内存。减少该选项可以减少 ORC 格式的内存消耗。orc.write.batch-size
  • 如果文件在写入任务中自动压缩,则某些大列的字典在压缩期间可能会显著消耗内存。
  • 要禁用 Parquet 格式的所有字段的字典编码,请将 .‘parquet.enable.dictionary’= ‘false’
    要禁用 ORC 格式的所有字段的字典编码 orc.dictionary.key.threshold=‘0’,请将 .此外,设置为禁用特定列的字典编码。orc.column.encoding.direct=‘field1,field2’
  • 如果您的 Flink 作业不依赖于状态,请避免使用托管内存,您可以使用以下 Flink 参数来控制托管内存:

taskmanager.memory.managed.size=1m

  • 或者,您可以将 Flink 托管内存用于写入缓冲区以避免 OOM,请设置 table 属性:

sink.use-managed-memory-allocator=true

  • 如果写入表的数据量特别大,Committer 节点可能会占用较大的内存,这可能会导致 OOM 如果内存太小。在这种情况下,您需要增加 Committer 堆内存,但您可能不想这样做 统一增加 Flink 的 TaskManager 的内存,这可能会导致内存浪费。

  • 配置 Flink 配置 。(这是 Flink 1.18 之后的默认设置)cluster.fine-grained-resource-management.enabled: true

  • 配置 Paimon Table 选项:,例如 300 MB,具体取决于您的 。 (也支持 )sink.committer-memoryTaskManagersink.committer-cpu

最大写入吞吐量场景

  • 如果希望某种模式具有最大写入吞吐量,则可以缓慢而不是匆忙地进行Compaction。可以对表使用以下策略,适合写入过程没有过多查询请求的场景,太多Sorted Run将导致查询性能较差,甚至内存不足
    num-sorted-run.stop-trigger = 2147483647
    sort-spill-threshold = 10
    lookup-wait=false
    file.format = avro
    metadata.stats-mode = none
Hologres 实时湖仓能力增强,挑战5分钟加速分析OSS数据 5分钟快速使用Hologres实时湖仓能力,无需移动数据,直接加速读取存储于数据湖OSS上的Hudi、Delta、Paimon等格式类型的数据。 阅读详情

相关推荐

数据湖技术之Paimon

Flink社区希望能够将Flink的Streaming实时计算能力和Lakehouse新架构优势进一步结合,推出新一代Streaming Lakehouse技术,促进数据在数据湖上真正实时流动起来,并为用户提供实时离线一体化的开发体验。Apache Paimon是一个流数据湖平台,具有高速数据摄取、变更日志跟踪和高效的实时分析的能力。

奔跑的蜗牛的博客 3071

Paimon的LSM 包 和 LSM Tree的基本结构

Paimon的MergeTree包实现了核心的LSM-Tree结构,主要包含三个关键组件:写入路径、数据结构和压缩机制。MergeTreeWriter作为写入入口,将KeyValue记录缓存到WriteBuffer(如SortBufferWriteBuffer)并进行排序后刷盘生成L0层SST文件。Levels类管理LSM-Tree的多层级结构,其中L0层文件无序,L1+层文件有序不重叠。SortedRun封装一组有序且键不重叠的文件,是压缩的基本单元。

lifallen的博客 1744

数据湖paimon连接flink、mysql和hive

新晋数据湖paimon连接flink,mysql和hive

weixin_42354436的博客 1876

Paimon Compaction实现

Compact主要涉及以下几个组件。

Gefangenes的博客 1217

paimon实战 -- paimon表数据写入和查询使用指南

通过设置consumer-id参数,您可以给流作业中的Paimon源表算子赋予一个Consumer ID,其值可以是任意的字符串。Consumer ID第一次创建时,它的起始消费位点根据中的规则确定。后续只要继续使用相同的Consumer ID,即可恢复Paimon表的消费进度。例如,为Paimon源表算子设置名为test-id的Consumer ID的SQL语句示例如下。

阿华田的博客 1757

【信息科学与工程学】【数据科学】第五十一篇 数据仓库10 数据仓库的机制和特性02

将“数据仓库”作为一个工程系统而非单一产品来说明书式呈现。表中涉及的具体厂商版本为2025-2026 年公开资料中的代表性版本,落地时需以目标产品当前 Release Notes 为准。学科/知识域代表产品(厂商+版本)架构范式云原生数仓(存算分离)Snowflake(多集群共享存储);阿里云 AnalyticDB(2026-03 更新);华为云 DWS(2026-02 更新,存算一体/分离可选)存算分离 + 多 Virtual Warehouse开源 MPP / 实时 OLAPClickHouse v24

weixin_49199313的博客 45

PAIMON安装测试

参考“

wangqiaowq的博客 733

实测昇腾310P跑Qwen3有多慢?手把手带你部署vLLM并记录性能数据

本文实测了昇腾310P在vLLM框架下部署Qwen3模型的性能表现,详细记录了2.5 tokens/s的生成速度及其技术瓶颈。通过环境搭建、基准测试和深度分析,揭示了计算资源利用率不足等关键问题,并提供了实用的优化技巧与监控方案,帮助开发者更好地理解和优化昇腾平台上的大模型部署。

weixin_28724319的博客 895

Doris x Paimon湖仓一体建设技术要点

湖仓一体」这个概念大家应该都不陌生了。我们在之前的文章中提高过,关于如何实现「湖仓一体」,方案并不是统一的,和你当前的技术栈以及业务场景息息相关。其中基于Doris x Paimon(或者其他的数据湖组件例如Hudi等),是其中一个可选的方案。本文写的就是这种方案主要解决的问题和用到的能力。

atbigapp的博客 1467

vins-mono保存、重载地图、evo工具测试

下面咱们来对vins-mono的重定位vins-mono官方源码地址:https://github.com/HKUST-Aerial-Robotics/VINS-Mono https://blog.youkuaiyun.com/learning_tortosie/article/details/83182258 运行这条: roslaunch benchmark_publisher publish.launc...

追 1万+

保姆级QFIL线刷教程:从驱动安装到成功刷机的完整避坑指南(Win10/11实测)

本文提供了一份详细的QFIL线刷教程,涵盖从驱动安装到成功刷机的完整流程,特别针对Win10/11系统进行了实测。文章重点解决了EDL模式下的常见问题,如Download Fail和COM Port识别错误,并提供了实用的避坑技巧和故障排除方案,帮助用户实现零失误操作。

weixin_29245767的博客 765

构建AI原生数据湖:Paimon与Milvus协同架构实践

在AI驱动的现代应用中,高效管理和利用多源异构数据是核心挑战。传统数据基础设施通常围绕结构化查询设计,难以满足AI智能体对语义理解和实时数据访问的需求。向量数据库通过将非结构化数据转化为高维向量,并利用近似最近邻搜索等算法,实现了基于语义的快速检索,为AI应用提供了关键的“记忆”与“联想”能力。其技术价值在于弥合了数据存储与AI理解之间的鸿沟,使得智能体能够像人类一样通过自然语言描述查找信息,极大地提升了人机交互的智能化水平。这一技术广泛应用于智能问答、内容推荐、知识库构建等场景。本文聚焦于将流批一体的数据

weixin_33716154的博客 293

对称式目镜设计实例

对称式目镜设计实例

weixin_72050316的博客 1163

5 分钟使用 Hologres 实时湖仓加速分析挑战赛来袭

活动简介:5 分钟快速使用 Hologres 实时湖仓能力,加速分析数据湖 OSS 上 Hudi、Delta、Paimon、ORC 等格式数据,赢取精美礼品或点击文末【阅读全文】参与挑战2024 年 1 月 4 日-2024 年 1 月 30●挑战奖:小米充电宝 15 个,非教程代码执行 SQL,完成运行速度对比●参与奖:社区积分,每位参赛者可获得社区 100 积分。

云布道师 1028

《FPGA DDR3权威实战:从基础到高速故障录波系统》专栏导览:从不知所措到心中有数

本文是一份DDR3实战指南,作者从自身学习经历出发,分享了一套循序渐进的DDR3应用路线图。专栏包含12篇文章,从基础配置(MIG IP核、AXI总线)、仿真测试到实际项目应用(功能测试、性能测试),最后深入原生MIG接口实战,通过一个高速故障录播系统案例完整展示DDR3开发流程。文章特别强调实践性,旨在帮助读者系统掌握DDR3开发技能,避免作者当年踩过的坑。每篇都配有优快云链接,适合FPGA开发者按顺序学习参考。

FPGA_小田老师的博客 332

YOLOv11 改进 - 注意力机制 | 空间增强注意力SEAM(Spatially Enhanced Attention Module)提升遮挡场景检测鲁棒性

本文介绍了分离与增强注意力模块(SEAM)在YOLOv11中的结合应用。SEAM模块旨在增强面部特征学习能力,特别是处理面部遮挡问题。它采用多头注意力机制强调面部区域、抑制背景区域,第一部分使用深度可分离卷积减少参数并学习通道重要性,通过1x1卷积增强通道联系,利用两层全连接网络融合通道信息,经指数归一化后作为注意力权重与原始特征相乘。我们将SEAM集成到YOLOv11的检测头中,并进行相关注册和配置。实验表明,该方法有助于提升模型检测性能。

魔改工程师的博客 1667

5 Paimon数据湖之表数据查询详解

主要涉及Paimon中系统表的查询、批量读取、流式读取,以及时间旅行特性的使用。

大数据技术博客 3872

uniapp [全端兼容] - 最新详细实现拍摄视频录像并可播放预览视频,调起本机摄像头开启录像录制完毕后保存到本机临时存放,可对拍摄的视频进行压缩处理减少文件大小不损失画质,详解录制视频并读取播放!

uni-app,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,录视频,拍视频,拍摄录制视频后上传服务器,调起摄像头录视频并可预览,录视频上传,录像,uniapp录制视频并上传,录制视频并保存到本地设备,如何本地保存并播放预览,提供给用户观看MP4视频录像并上传到后端服务器完整功能源码,视频压缩,mp4文件,删除视频,录像后怎么预览,临时视频文件怎么减少压缩大小,视频压缩及上传,自己录视频并生成可播放的文件,录视频并能打开查看,视频压缩后上传,本机相册,录完怎么预

🏆 前端领域优质创作者 1万+

Paimon&Iceberg&Hudi&Delta Lake原理学习+开箱性能自测

快速了解不同的数据湖

不稳定态maj 3351

保姆级教程:ABAP 通过 HTTP POST 调用 OData 服务创建业务数据的具体例子

笔者之前的文章发布之后,有朋友在评论区留言,询问 ABAP 除了 Web Service 之外,是否也支持 HTTP 呢?ABAP 这么强大的语言,支持 HTTP 当然不在话下。网上有很多在 ABAP 系统基于 CL_HTTP_CLIENT 工具类,通过 HTTP 协议和第三方系统交互的代码例子。本文介绍笔者项目中一个实际例子,实现的是在 ABAP 系统 A 通过 HTTP 调用 OData 服务,在 ABAP 系统 B 创建业务数据的需求。下面我们按照这个套路来一步步实现。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 701

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

Paimon LSM Tree Compaction核心:堆和败者树

SortMergeReaderWithMinHeap和SortMergeReaderWithLoserTree是Paimon中实现多路归并排序的两种核心实现。两者都用于合并多个已排序的数据流,但采用不同数据结构:MinHeap使用最小堆,每次调整需要约2logK次比较;LoserTree采用败者树,优化为约logK次比较。LoserTree通过状态机(State)和firstSameKeyIndex字段高效处理主键相同的记录分组,支持快速跳转优化。两种实现都遵循"取数-调整-补充"的循环

lifallen的博客 2820

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

1 快速了解Paimon数据湖核心原理及架构

Apache Paimon的前身属于Flink的子项目:Flink Table Store。目前业内主流的数据湖存储项目都是面向批处理场景设计的,在数据更新处理时效上无法满足流式数据湖的需求,因此Flink社区在2022年的时候内部孵化了 Flink Table Store (简称 FTS )子项目,一个真正面向流以及实时的数据湖存储项目。

大数据技术博客 3646

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

基于apache paimon实时数仓全增量一体实时入湖

flink + paimon 全量 + 实时增量的数据入湖

xiaosannimei的博客 4500

Apache Doris + Paimon 快速搭建指南|Lakehouse 使用手册(二)

湖仓一体(Data Lakehouse)融合了数据仓库的高性能、实时性以及数据湖的低成本、灵活性等优势,帮助用户更加便捷地满足各种数据处理分析的需求。在过去多个版本中,持续加深与数据湖的融合,已演进出一套成熟的湖仓一体解决方案。为便于用户快速入门,我们将通过系列文章介绍 Apache Doris 与各类主流数据湖格式及存储系统的湖仓一体架构搭建指南,包括 Hudi、Iceberg、Paimon、OSS、Delta Lake、Kudu、BigQuery 等。目前,我们已经发布了。

SelectDB 1395

基于 LoserTree 的 Paimon 多路归并优化

多路归并算法主要用于外排序,主要按照排序-归并的策略进行。当需要处理的数据量非常大,内存无法全量装入时,会将这些数据先组织为多个有序的子文件,然后再对这些子文件进行归并。在 Paimon 中,每个 RecordReader 已经是有序的,因此我们只需要进行归并流程操作。下面会主要对堆排序和 LoserTree 算法进行介绍,并对两者间的性能进行分析对比。2.1 堆排序堆排序是以堆作为排序的数据结构设计的算法。堆是一棵完全二叉树,根据父节点中存储的值是否都大于或小于子节点的值,又分为大根堆和小根堆。

字节跳动云原生计算官方账号 632
上一篇: flink timer定时器
下一篇: hive session 超时
JNWsong
博客等级 码龄9年 287粉丝 204原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值