摘要:“让技术被看见 | OceanBase 布道师计划”由 OceanBase 主办,CSDN 协办,面向广大开发者的年度征文活动。
“让技术被看见 | OceanBase 布道师计划”由 OceanBase 主办,CSDN 协办,面向广大开发者的年度征文活动。
全年 4 轮,以季度为周期进行优秀文章评比,每年 1 届,以年为单位进行最佳布道师评选。
目前,首轮技术征文获奖文章已评选出炉,
本篇内容为「OceanBase 布道师计划」优秀文章之一,作者为多明戈教你玩狼人杀。
稿:https://open.oceanbase.com/blog/essay-competition。
评委有话说
屠敏(CSDN 资讯主编、《新程序员》特约专栏记者):本文深入探讨了OceanBase的列存和物化视图特性,结合实时与批处理数仓场景,展示了其技术优势。文章逻辑清晰,通过实际案例和代码示例,体现了OceanBase在提升查询性能和降低成本方面的巨大价值,为数仓领域的从业者提供了一定的实践指导。
老鱼(资深 IT 媒体人、《老鱼笔记》主理人):文章探讨了OceanBase 4.3版本中引入的列存和物化视图特性在数据仓库建设中的应用,展示了这些新特性如何显著提升查询性能和降低系统开销。文中不仅提供了详尽的技术背景、特性对比及实际操作步骤,还通过具体案例(如TPC-H测试)验证了性能增益,体现了理论与实践的紧密结合。
OceanBase在4.3开始,同时支持了行存和列存,以及可刷新物化视图。这些特性给予了这个产品更多的使用场景和可能性。作为过去一年时间里,都是在和数仓打交道的人,我在最近也做了一些基于这两个特性的测试和探索。现阶段的OceanBase,已经可以通过这些特性,来实现流和批两种场景下的数仓建设。
1.1 行存与列存我们所熟悉的几个经典数据库产品,都是基于行存的。无论是MySQL的innodb引擎,还是Oracle原生的存储引擎。在我刚入行的日子里,甚至没有想过,世界上还需要有列存引擎的数据库。然而随着数据量的提升,以及大规模报表的查询越来越复杂,这使得同一套硬件设备,数据量大了以后,数据库的查询性能不断下滑。
然而列存恰恰解决了这个问题,如果说行存是为事务而生,那么列存适合于读取部分列数据的场景,尤其是当查询只需要少数几列时,列存的优势就显现出来了。而且还有一点,就是列存的压缩比更高,在面对更大数量级的业务数据,带来的成本优势也更高。过往行存依赖的高性能存储,在列存用普通存储亦可。某种程度上来说,列存为数仓而生也不为过。
OceanBase在4.3发布的列存,并不能简单称之为列存,而是一体化的行存和列存数据存储,在同一个架构、同一个数据库上实现了列存和行存数据存储一体化,兼顾了事务处理(TP)和分析处理(AP)的查询性能。这个特性在发布会上,让我不禁眼前一亮。也让我这几个月以来,一直在思索如何应用到当下的工作和测试过程中。
1.2 物化视图与表最早使用物化视图的主流数据库是Oracle,物化视图与普通视图本质差异在于,物化视图存储了查询结果的数据副本,而且是物理层面的保存。这就使得复杂查询的结果可以快速地被访问。一直到今天的Oracle23AI,物化视图都是一直在不断迭代发展的。
而当下4.3.3的OceanBase,物化视图的功能也已经有了长足进步。那么可能就有人会问,既然有列存了,还需要有物化视图吗?或者说,物化视图和列存表,各自的优势是什么,彼此适合的场景有什么异同?
其实这个问题也是我自己好奇的。答案还是要回到存储引擎本身。LSM-Tree。
OceanBase基于LSM-Tree存储引擎的支持,列存表可以支持事务,那么就可以实现流式写入并且还能确保ACID,适合做实时数仓。分布式数据库所具备的并行查询,结合OceanBase的多副本,在执行效率上也更加优异。在数仓这种读多写少的场景下,尤其是某些大宽表,大部分时间里只会读取其中一部分列数据的场景下,列存带来的优势就很明显。
而物化视图通过自身的刷新机制,更适合做一些汇总、分发、多表连接,将一些常用查询的结果落盘。相比较列式存储,物化视图的定期刷新机制,则更适合于批量计算的场景。这种计算通常对时间要求不如流式计算那么严格,但需要高效地处理大规模数据集。有时候还承担了一些ETL的任务。
2.1 实时数仓的需求顾名思义,相较于传统的离线数仓,实时数仓最重要的特点就是实时性。以往的数仓建设,都是T+1的数据时效性。对于一些需要实时计算并且获取结果的指标来说,就显得不够灵活,而且数仓逻辑如果出了问题,往往要第二天才能发现,重新调整跑任务,都要受到时间的限制。而在一个企业里,却有着大量需要实时计算的业务指标并尽可能实时完成计算反馈给相关部门。
所以想要建立起一个实时数仓,往往需求满足如下的技术:
1. 高性能:想要做到高实时性,那么性能就是先决条件。一个能够用来做实时数仓的产品,性能都不会差。需要数据处理延迟极低,通常在毫秒级到秒级之间,确保数据处理的时效性。
2. 数据集成:数仓的上游可能是各种生产系统的数据库甚至是离线数据文件。这就对实时数仓的产品数据集成丰富度要求很高,要有丰富的数据接口,满足多样化要求。
3. 可扩展性:实时数仓,除了数据的实时要求,其实还有一个隐性需求,就是可扩展性的实时。离线数仓往往是夜间跑批,扩展性要求没那么高,但是实时数仓一旦资源出现瓶颈,不能灵活扩容,实时性也就成了空谈。
4. 安全性:实时性提升,其实对于安全要求也有了更高要求。涉及到实时计算的内容,往往也是关键数据。这其中对数据的安全性和隐私性的要求只会更高,必须要采用多种安全措施,如数据加密、访问控制等,确保数据的安全可靠。
5. 灵活的查询与分析:实时数仓的场景是多元化的,这就要求这个数据库产品要能够提供丰富的查询和分析工具,支持复杂的查询语句和数据分析模型。否则实时性就打个折甚至失去的本来的意义。
2.2 OceanBase的技术现状实时性:OceanBase 4.3 具备 T+0 的实时写入能力,支持快速的数据导入,能够有效消除数据导入延迟,满足实时分析的需求。
1. 高性能:4.3版本引入的列式存储引擎和向量化引擎,如同上面分析的,是可以显著提升查询性能的,尤其是在大宽表场景下,根据我实际测试,查询性能达到了业内主流列存大宽表数据库的水平,能够实现秒级实时分析。而且不要忘记,OceanBase是支持事务的,这带来了额外的性能开销,再这样情况下,列存仍然能够提供足够的性能。
2. 数据集成:目前为止OceanBase4.3以上的版本,集成了MySQL和Oracle的各种数据接入方式,对其他主流的开源数据库,例如PostgreSQL、Clickhosue,也可以通过flink生态的工具来实现。再加上旁路导入特性的加强,已经具备了作为实时数仓的集成能力。
3.可扩展性:云原生分布式架构,先天支持高并发的读写操作,能够根据业务需求进行水平扩展,适应不断增长的数据量和用户请求。在线扩容副本或者OBServer的能力都已经具备,而且根据我自己的实际测试,能够实现分钟级别的水平扩展。当然,随着数据量和业务量规模,这个数字是要不断下降的。
4.安全性:截止4.3.3,OceanBase在安全方面实现的特性有多租户的资源与权限隔离、数据库安全审计、数据的存储加密和传输加密、基于网络的访问控制、密码复杂度等多种手段,这些特性也让OceanBase过了等保三级。这些都是安全性的有力验证。
5.灵活查询与分析:从目前OceanBase支持的数据类型来看,涵盖了大部分常用类型,4.3.3还支持了ARRAY类型。优化器支持了RBO与CBO两种模式,加上全文索引、向量检索等功能,结合列存与物化视图,我个人认为符合了这个功能需求点。
2.3 一个实时数仓的Demo我们来做一个Demo,来演示一下列存用于实时数仓。
数据源1,MySQL 8
数据源2,PostgreSQL 14
实时数仓,OceanBase 4.3.3 社区版
数据同步,Flink CDC
a.创建MySQL表并插入数据
CREATE TABLE orders ( order_id INT AUTO_INCREMENT, order_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP, customer_name VARCHAR(100), price DECIMAL(10, 2), product_id INT, order_status BOOLEAN, PRIMARY KEY (order_id));INSERT INTO orders (customer_name, price, product_id, order_status) VALUES('Alice', 19.99, 101, TRUE),('Bob', 29.99, 102, FALSE),('Charlie', 39.99, 103, TRUE),('David', 49.99, 104, TRUE);b. 在flinkcdc创建表用于读取MySQL表
CREATE TABLE mysql_source ( order_id INT, order_date TIMESTAMP(0), customer_name STRING, price DECIMAL(10, 5), product_id INT, order_status BOOLEAN, PRIMARY KEY (order_id) NOT ENFORCED) WITH ( 'connector' = 'mysql-cdc', 'hostname' = '192.16.1.10', 'port' = '3306', 'username' = 'test', 'password' = 'password', 'database-name' = 'test', 'table-name' = 'orders' );c.创建一张PostgreSQL表,插入数据
CREATE TABLE products ( product_id INT PRIMARY KEY, product_name VARCHAR(100), product_description TEXT);INSERT INTO products (product_id, product_name, product_description) VALUES(101, 'Laptop', 'High performance laptop'),(102, 'Smartphone', 'Latest model smartphone'),(103, 'Tablet', 'Portable and lightweight tablet'),(104, 'Headphones', 'Noise-cancelling headphones');d.创建flinkcdc的pg同步表
CREATE TABLE postgres_source ( product_id INT, product_name STRING, product_description STRING, PRIMARY KEY (product_id) NOT ENFORCED) WITH ( 'connector' = 'postgres-cdc', 'hostname' = '192.168.10。11', 'port' = '5432', 'username' = 'test', 'password' = 'password', 'database-name' = 'test', 'schema-name' = 'public', 'table-name' = 'products');e.创建OceanBase的目标表,使用列存
CREATE TABLE joined_orders ( order_id INT, order_date TIMESTAMP, customer_name VARCHAR(100), price DECIMAL(10, 2), product_name VARCHAR(100), product_description TEXT, order_status BOOLEAN, PRIMARY KEY (order_id)) WITH COLUMN GROUP (each column);f.根据OceanBase目标表的字段,在flink中创建join视图
CREATE VIEW joined_orders ASSELECT o.order_id, o.order_date, o.customer_name, o.price, p.product_name, p.product_description, o.order_statusFROM mysql_source AS oJOIN postgres_source AS p ON o.product_id = p.product_id;g.配置flinkcdc的写入任务
具体步骤略
f.验证结果
如果前面的步骤都顺利完成,那么此时我们查询会有如下结果
SELECT * FROM joined_orders;++++-------++++| order_id | order_date | customer_name | price | product_name | product_description | order_status || 1 | 2024-11-19 00:00:00 | Alice | 19.99 | Laptop | High performance laptop | 1 || 2 | 2024-11-19 00:00:01 | Bob | 29.99 | smartphone | Latest model smartphone | 0 || 3 | 2024-11-19 00:00:02 | Charlie | 39.99 | Tablet | Portable and lightweight tablet | 1 || 4 | 2024-11-19 00:00:03 | David | 49.99 | Headphones | Noise-cancelling headphones | 1 |在源表插入数据
INSERT INTO orders (customer_name, price, product_id, order_status) VALUES ('Eve', 59.99, 105, TRUE);---- MySQL表INSERT INTO products (product_id, product_name, product_description) VALUES (105, 'Smartwatch', 'Advanced smartwatch with health tracking features'); ----PG表两边提交之后,实时查询OceanBase表,能够实时得到新结果:
SELECT * FROM joined_orders;++++-------++++| order_id | order_date | customer_name | price | product_name | product_description | order_status || 1 | 2024-11-19 00:00:00 | Alice | 19.99 | Laptop | High performance laptop | 1 || 2 | 2024-11-19 00:00:01 | Bob | 29.99 | Smartphone | Latest model smartphone | 0 || 3 | 2024-11-19 00:00:02 | Charlie | 39.99 | Tablet | Portable and lightweight tablet | 1 || 4 | 2024-11-19 00:00:03 | David | 49.99 | Headphones | Noise-cancelling headphones | 1 || 5 | 2024-11-19 00:00:05 | Eve | 59.99 | Smartwatch | Advanced smartwatch with health tracking features | 1 |2.4 小结Demo不算复杂,就是简单的两张表join最后吐出结果。主要的目标是为了验证实时性。而结合OceanBase列存的性能以及多副本读写分离,实际就是一个极简版的实时数仓。可以看到的是,OceanBase在flinkcdc作为工具的情况下,能够实现秒级别的实时数仓功能。
当然,我这个demo由于资源和时间所限,没有能够模拟更大数据量和更复杂的计算,只是作为一个参考,如果以后有机会,我会补充一个更详尽版的Demo。
3.1 批处理数仓的技术需求批处理数仓,其实就是我们常说的传统数仓。这种类型的数仓主要依赖于批量数据处理技术,通常在每天的特定时间运行ETL,将数据从源系统提取出来,进行转换和清洗,然后加载到数据仓库中。实时性要求不高,但是却对产品有其他的要求:
1.存储能力:批处理数仓的数据量往往更大,因为需要保存更多的历史数据。而且需要更高的数据吞吐量能力,每天晚上的批处理包含的数据量远远高于实时数仓的实时写入。而且数据量大的时候,对于数据压缩的需求也更加迫切。
2.数据处理能力:这里的处理能力比起实时数仓要求就更广泛。除了常用的对象类型和SQL支持,还需要考虑大规模数据并行计算的能力,有可能每天计算量超过百GB。在各类复杂报表中,还需要考虑索引加速等手段,来尽可能提高性能。
3.数据一致性:在多个复杂ETL过程中,往往需要事务的支持,从加载到转换再到计算落盘。而一致性往往还需要通过一些约束来辅佐,比如主键、唯一键、非空键等等,用来确保一致性和数据质量。
4.安全性、数据集成:理由基本同实时数仓。
3.2 OceanBase的现状1.存储能力:目前从各类客户案例以及我自己导入的百GB级别(再多测试资源就不够了),能够提供更高的数据吞吐量和存储能力,满足批处理数仓对大数据量存储的需求。同时,列存可以实现性能最优和最小的存储空间,对数据压缩有较好的支持,能够应对数据量大时对数据压缩的需求。
2.数据处理能力:OceanBase在4.3推出了基于Column数据格式的2.0向量化引擎,是一个能够显著提升AP场景查询性能的特性。这使得OceanBase具备大规模数据并行计算的能力,能够处理每天计算量超过百GB的需求。分配足够多资源的情况下,这些都不是问题。物化视图功能,通过预计算存储视图的查询结果提升实时查询性能,这对于提高复杂报表中的查询性能是一个大杀器。
3.数据一致性:如同之前所说的,OceanBase持事务,能够满足多个复杂ETL过程中对事务的需求。在数据加载、转换和计算落盘的过程中,能够保证数据的一致性。而主键、唯一键、非空键等约束,无论是行存还是列存,都是一视同仁支持的。也算是打消了我对数据一致性的顾虑。
4.安全性、数据集成:现状基本同实时数仓。
3.3 基于物化视图的探索我们本次对批处理数仓的探索,主要基于OceanBase的物化视图。我们模拟一个批处理数仓的场景,来验证物化视图对数据查询的加速。
测试数据:TPCH,10G/20G
测试语句:多表查询与物化视图直查
测试版本:OceanBase 4.3.3 社区版
a.创建TPCH数据表
根据TPCH要求,创建8张表,全部使用列存
CREATE TABLE NATION ( N_NATIONKEY INTEGER NOT , N_NAME VARCHAR(25) NOT , N_REGIONKEY INTEGER NOT , N_COMMENT VARCHAR(152), PRIMARY KEY (N_NATIONKEY) )WITH COLUMN GROUP (each column);CREATE TABLE REGION ( R_REGIONKEY INTEGER NOT , R_NAME VARCHAR(25) NOT , R_COMMENT VARCHAR(152), PRIMARY KEY (R_REGIONKEY) )WITH COLUMN GROUP (each column);CREATE TABLE PART ( P_PARTKEY INTEGER NOT , P_NAME VARCHAR(55) NOT , P_MFGR VARCHAR(25) NOT , P_BRAND VARCHAR(10) NOT , P_TYPE VARCHAR(25) NOT , P_SIZE INTEGER NOT , P_CONTAINER VARCHAR(10) /*CHAR(10)*/ NOT , P_RETAILPRICE DECIMAL(15,2) NOT , P_COMMENT VARCHAR(23) NOT , PRIMARY KEY (P_PARTKEY) )WITH COLUMN GROUP (each column);CREATE TABLE SUPPLIER ( S_SUPPKEY INTEGER NOT , S_NAME VARCHAR(25) NOT , S_ADDRESS VARCHAR(40) NOT , S_NATIONKEY INTEGER NOT , S_PHONE VARCHAR(15) NOT , S_ACCTBAL DECIMAL(15,2) NOT , S_COMMENT VARCHAR(101) NOT , PRIMARY KEY (S_SUPPKEY) )WITH COLUMN GROUP (each column);CREATE TABLE PARTSUPP ( PS_PARTKEY INTEGER NOT , PS_SUPPKEY INTEGER NOT , PS_AVAILQTY INTEGER NOT , PS_SUPPLYCOST DECIMAL(15,2) NOT , PS_COMMENT VARCHAR(199) NOT , PRIMARY KEY (PS_PARTKEY, PS_SUPPKEY) )WITH COLUMN GROUP (each column);CREATE TABLE CUSTOMER ( C_CUSTKEY INTEGER NOT , C_NAME VARCHAR(25) NOT , C_ADDRESS VARCHAR(40) NOT , C_NATIONKEY INTEGER NOT , C_PHONE VARCHAR(15) NOT , C_ACCTBAL DECIMAL(15,2) NOT , C_MKTSEGMENT VARCHAR(10) NOT , C_COMMENT VARCHAR(117) NOT , PRIMARY KEY (C_CUSTKEY) )WITH COLUMN GROUP (each column);CREATE TABLE ORDERS ( O_ORDERKEY BIGINT NOT , O_CUSTKEY INTEGER NOT , O_ORDERSTATUS VARCHAR(1) NOT , O_TOTALPRICE DECIMAL(15,2) NOT , O_ORDERDATE DATE NOT , O_ORDERPRIORITY VARCHAR(15) NOT , O_CLERK VARCHAR(15) NOT , O_SHIPPRIORITY INTEGER NOT , O_COMMENT VARCHAR(79) NOT , PRIMARY KEY (O_ORDERKEY) )WITH COLUMN GROUP (each column);CREATE TABLE LINEITEM ( L_ORDERKEY BIGINT NOT , L_PARTKEY INTEGER NOT , L_SUPPKEY INTEGER NOT , L_LINENUMBER INTEGER NOT , L_QUANTITY INTEGER NOT , L_EXTENDEDPRICE DECIMAL(15,2) NOT , L_DISCOUNT DECIMAL(15,2) NOT , L_TAX DECIMAL(15,2) NOT , L_RETURNFLAG VARCHAR(1) NOT , L_LINESTATUS VARCHAR(1) NOT , L_SHIPDATE DATE NOT , L_COMMITDATE DATE NOT , L_RECEIPTDATE DATE NOT , L_SHIPINSTRUCT VARCHAR(25) NOT , L_SHIPMODE VARCHAR(10) NOT , L_COMMENT VARCHAR(44) NOT , PRIMARY KEY (L_ORDERKEY, L_LINENUMBER) )WITH COLUMN GROUP (each column);b.使用数据生成工具,生成份10GB大小的数据集
./dbgen -s 10c.导入其中一份10GB数据,导入前请检查是否已经配置过secure_file_priv
SET SESSION ob_query_timeout = 1000000000000LOAD DATA INFILE '/tmp/tpch-dbgen-master/part.tbl' INTO TABLE part FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n';LOAD DATA INFILE '/tmp/tpch-dbgen-master/nation.tbl' INTO TABLE nation FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n';LOAD DATA INFILE '/tmp/tpch-dbgen-master/region.tbl' INTO TABLE region FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n';LOAD DATA INFILE '/tmp/tpch-dbgen-master/supplier.tbl' INTO TABLE supplier FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n';LOAD DATA INFILE '/tmp/tpch-dbgen-master/partsupp.tbl' INTO TABLE partsupp FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n';LOAD DATA INFILE '/tmp/tpch-dbgen-master/customer.tbl' INTO TABLE customer FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n';LOAD DATA INFILE '/tmp/tpch-dbgen-master/orders.tbl' INTO TABLE orders FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n';LOAD DATA INFILE '/tmp/tpch-dbgen-master/lineitem.tbl' INTO TABLE lineitem FIELDS TERMINATED BY '|' LINES TERMINATED BY '\n';d.随即执行一条TPCH,我选择了Q11,记录执行时间3.33秒select ps_partkey, sum(ps_supplycost * ps_availqty) as valuefrom partsupp, supplier, nationwhere ps_suppkey = s_suppkey and s_nationkey = n_nationkey and n_name = 'GERMANY'group by ps_partkey having sum(ps_supplycost * ps_availqty) > ( select sum(ps_supplycost * ps_availqty) * 0.000002 from partsupp, supplier, nation where )order by value desc;e. 根据Q11,创建物化视图
CREATE MATERIALIZED VIEW mv_q11REFRESH COMPLETE ON DEMANDASselect ps_partkey, sum(ps_supplycost * ps_availqty) as valuefrom partsupp, supplier, nationwhere ps_suppkey = s_suppkey and s_nationkey = n_nationkey and n_name = 'GERMANY'group by ps_partkey having sum(ps_supplycost * ps_availqty) > ( select sum(ps_supplycost * ps_availqty) * 0.000002 from partsupp, supplier, nation where )order by value desc;f.清理缓存后查询该物化视图,获取时间0.46秒,提升了7倍的性能
select * from mv_q11;而且随着数据量的增多,物化视图带来的性能增益将会更加明显。比如生产环境的系统,每天如果增加几十GB的数据量,采用OceanBase物化视图的增量刷新,实际效果会更好,比如这里就是6个小时刷新一次:
CREATE MATERIALIZED VIEW mv_q11REFRESH FORCESTART WITH SYSDATENEXT SYSDATE + 6/24 ASselect ps_partkey, sum(ps_supplycost * ps_availqty) as valuefrom partsupp, supplier, nationwhere ps_suppkey = s_suppkey and s_nationkey = n_nationkey and n_name = 'GERMANY'group by ps_partkey having sum(ps_supplycost * ps_availqty) > ( select sum(ps_supplycost * ps_availqty) * 0.000002 from partsupp, supplier, nation where )order by value desc;3.4 小结可以看到的是,即便是基于列存的表,查询效率比起落盘后的物化视图,仍然有着不小的时间差。而在很多数仓中,我们都会遇到一些常用且数据量很大的固定查询或者报表等等,如果能够使用物化视图,每天定期刷新,实际上可以大幅减少系统开销。
实际上,物化视图也不过是数仓最后一个层级,也就是我们平时提的比较多的数据集市层或者报表层,下面还有汇总层、基础层、ODS层等等,其实都可以通过批量ETL转换成OceanBase列存表,大大提高以往用行存的性能,而最上面的一层,则使用物化视图来实现。
行存和TP起家的OceanBase,在列存上的发力让我多少有些意外之喜,尤其是实际验证了行存列存的性能差距之后。这套的列存技术非常适用于数仓。在列存模式下,底层存储的每列数据存储为一个独立的SSTable,所有列的SSTable组合成为一个虚拟SSTable作为用户的列存基线数据。这种设计使得列存表数据可以像行存表一样进行所有事务操作,既可以提高性能,又可以提高压缩率。在未来也许还会有更多的新特性,用于增强。
而在批处理数仓中,OceanBase的物化视图可以把复杂的查询预处理后,将计算结果存储起来,从而加快查询速度。一定程度上减少了对外部ETL的依赖,而且本文没有涉及到的是,OceanBase的物化视图支持灵活的刷新策略,包括全量刷新和按需刷新,可以根据业务需求选择合适的刷新模式。使用过程中,性能也非常稳定,这一点上在国产数据的表现非常突出。我用过的所谓物化视图也有不少,但是性能和便捷性上则参差不齐。
有关从ODS到DWD再到DWS,以及最后的应用层该如何构建,其实也是足可以写一篇几千字文章的内容。这部分在新的列存引擎面前,是可以大大提高效率的,只是囿于篇幅所限,以及我本人精力的限制,只能写到这里。实际在我测试环境中,我已经将这几层的测试数据都搬到了OceanBase的列存表中,也做了很多测试。过去要用小时计算的ETL任务,在列存的加速下,性能提升可以翻倍起步。这中间很多计算逻辑并没有根据列存做过调整,认真优化的话,只会更快。
来源:CSDN