Apache CarbonData
是一个支持索引和物化视图的ACID数据湖,在5月初正式发布了2.0 RC2,这个版本在索引、物化视图、数据湖能力、ACID等方面均有增强。我们可以先快速浏览一下这个版本。
索引和物化视图能力:
- 详单查询:二级索引、BloomFilter索引、Lucene索引、空间索引、Segment级别MINMAX索引,实现PB级别秒级详单查询;
- 复杂查询:物化视图、时序聚合、分桶索引,实现复杂查询秒级响应;
- 海量索引管理:分布式内存索引缓存、并支持索引内存预加载;
数据湖能力:
- 历史数据无缝迁移:支持对Parquet、ORC、CarbonData数据进行统一元数据管理,PB级别Parquet、ORC数据秒级迁移CarbonData;
- 历史数据加速:为Parquet、ORC、CarbonData构建统一物化视图;
- 异构计算融合:对接Flink、Hive、Presto、PyTorch、TensorFlow,实现“一份数据到处访问”;
ACID能力:
- Insert、Update和Delete性能增强,支持Merge语法
下面我们首先介绍CarbonData的愿景,其次通过示例介绍CarbonData的索引、物化视图、数据湖能力和ACID能力。
前言
如下表所示,业界在EB级别存储的数据库可选方案主要包含Nosql数据、Hadoop生态数据仓库等,但都有其明显的不足。
可选方案 | 优势 | 不足 |
---|---|---|
HBase、ES、Kudu、MPP等 | 快 | 贵 |
Spark、Hive等 | 成本低 | 慢 |
首先,以HBase服务、MongoDB服务或者ElasticSearch服务为代表的Nosql数据库,虽然也可以支持快速的复杂SQL查询,但是这些服务均不支持存储与计算分离,为了满足PB/EB级别存储的需求,往往我们需要启动更多的计算节点,消耗更多的CPU和存储成本,同时还要付出更多的运维成本,计算和存储的紧密耦合也意味着更低的计算和存储利用率。例如HBase服务,单台RegionServer可维护不超过10TB的数据,面对10PB的数据存储时,需要1000台计算节点部署RegionServer,其所面对的金钱成本和运维成本都十分高昂。
其次,以Spark on Parquet、Hive on ORC为代表的Hadoop生态数据仓库解决方案,支持将数据放在对象存储服务上,但是没有对数据构建高效的索引,使得明细数据查询或者复杂查询都很慢。假设如下几种场景:1)查询过去一年某用户的行为轨迹,当没有针对用户构建索引时,只能暴力扫描过去一整年的数据,测试中需要7天才能完成,2)Join类的复杂查询同样如此,无索引情况下,只能对数据暴力扫描,极大限制了查询速度。
由上可见,Nosql数据库虽然具有较好的数据索引机制,但是“太贵”,传统的Hadoop生态数据仓库将数据放在对象存储上,但是“太慢”,这两者各自的局限性,使得我们进行EB级别数据仓库选型时,面临着这一个鱼与熊掌不可兼得的选择题。
为了能够像关系型数据库一样可以高效执行复杂SQL查询,又可以像NoSQL数据库一样,构建高效索引,最后,可以和Spark/Hive一样,享受高度可扩展性的数据并行处理、利用近乎无限的低成本的对象存储资源,满足这种“又方便又快又便宜”的任性就是CarbonData的使命。
接下来的内容,我们将重点介绍如何体验CarbonData 2.0 RC2中的索引、物化视图、ACID能力。
一、快速安装CarbonData
-
准备1台Linux弹性云服务器
-
下载快速安装脚本
curl -k -O http://carbondata-publish.obs.myhuaweicloud.com/quick_start_carbondata.sh
- 启动sparksql和carbondata
source quick_start_carbondata.sh
二、CarbonData索引和物化视图
CarbonData 2.0 提供了丰富的索引能力,笔者总结了CarbonData提供的不同索引能力和适用场景。如下表所示。
索引类型 | 适用场景 | 效果 |
---|---|---|
排序索引 | 带有排序键过滤的查询 | 秒级主键精确查询 |
二级索引 | 带有二级索引键过滤的查询 | 秒级非主键精确查询 |
物化视图 | Join、GroupBy、OrderBy等复杂查询 | 复杂查询秒级响应 |
时序索引 | 时序聚合 | 秒级时序聚合 |
空间索引 | 空间检索 | 秒级空间精确过滤 |
BloomFilter索引 | 带有高基数列过滤的查询 | 高基数列快速过滤 |
Lucene索引 | 多维检索 | 秒级多维索引 |
下面我们给出在CarbonData中构建索引的语法示例。
- 构建排序键索引,语法举例如下:
CREATE TABLE person(id STRING, age INT, country STRING, timestamp timestamp, address STRING, skill STRING)
STORED AS carbondata
TBLPROPERTIES('sort_scope'='GLOBAL_SORT','sort_columns'='id, age');
- 构建二级索引,语法举例如下:
CREATE INDEX person_si_country_age on table person(country, age) AS 'carbondata';
- 构建物化视图,基于复杂查询构建物化视图的语法举例如下:
CREATE MATERIALIZED VIEW person_countid_gb_country
AS SELECT country,count(id) FROM person GROUP BY country;
- 构建时序索引,语法举例如下:
CREATE MATERIALIZED VIEW person_countid_gb_timeseries AS
SELECT timeseries(timestamp, 'minute'),count(id)
FROM person
GROUP BY timeseries(timestamp, 'minute');
- BloomFilter索引,语法举例如下:
CREATE INDEX person_bf_address
ON TABLE person (address)
AS 'bloomfilter'
PROPERTIES ('BLOOM_SIZE'='640000', 'BLOOM_FPP'='0.00001');
- Lucene索引,语法举例如下:
CREATE INDEX person_luc_skill
ON TABLE person (skill)
AS 'lucene';
- 加载数据
INSERT INTO person VALUES
('c001', '23', 'china', '2016-02-23 09:01:30','china sz','computer design'),
('c003', '23', 'japan', '2016-02-23 08:01:30','japan to','sport speech'),
('c002', '23', 'india', '2016-02-23 07:01:30','india mm','draw write');
- 查询数据
//利用排序索引查询
SELECT * FROM person WHERE id = 'c001';
//利用二级索引查询
SELECT * FROM person WHERE country = 'china' and age = 23;
//利用物化视图进行查询
SELECT country,count(id) FROM person GROUP BY country;
//利用时序索引进行查询
SELECT timeseries(timestamp, 'minute'),count(id)
FROM person
GROUP BY timeseries(timestamp, 'minute');
//利用BloomFilter索引进行查询
SELECT * FROM person WHERE address = 'china sz';
//利用Lucene索引进行查询
SELECT * FROM person WHERE TEXT_MATCH('skill:*computer*')
三、数据湖
CarbonData在体现性能优势的同时,需要回答如何将历史数据搬迁到CarbonData的问题,CarbonData 2.0交出了如下的答卷:
1)历史Parquet、ORC数据如何导入CarbonData?
支持通过"add segment"的方式,实现CarbonData对Parquet、ORC数据进行统一纳管。实现PB级别历史数据秒级迁移。
2)如何对历史Parquet、ORC数据构建索引?
支持对CarbonData、Parquet、ORC构建统一物化视图。实现PB级别数据复杂查询秒级响应。
下面主要通过示例演示以上两个功能:1.Parquet文件如何无缝导入CarbonData; 2.如何对Parquet数据构建物化视图。
- Parquet文件导入CarbonData
首先,构建一张Parquet表,并写入数据。
CREATE TABLE parquet_table(id STRING, age INT, country STRING, timestamp timestamp, address STRING, skill STRING)
STORED AS parquet;
INSERT INTO parquet_table VALUES
('c004', '23', 'kor', '2016-02-22 09:01:30','kor ab','design'),
('c005', '23', 'russia', '2016-02-21 08:01:30','russia mo','game'),
('c006', '23', 'india', '2016-02-23 07:01:30','india sc','travel');
其次,将Parquet文件元数据导入CarbonData,语法示例如下。这里path需要替换为真实parquet表路径,路径信息可以通过describe formatted parquet_table查询得到。
ALTER TABLE person ADD SEGMENT options('path'='{$parquet_table_location}','format'='parquet');
最后,查询CarbonData表。最终可以发现CarbonData表中已经可以查询到Parquet表的数据。
SELECT * FROM person;
- 为Parquet表构建物化视图
CREATE MATERIALIZED VIEW parquet_table_countid_gb_country
AS SELECT country,count(id) FROM parquet_table GROUP BY country;
利用物化视图进行查询
SELECT country,count(id) FROM parquet_table GROUP BY country;
三、ACID
CarbonData 2.0中深度优化了UPDATE、DELETE性能,并支持了Merge语法。
数据更新,语法示例如下:
UPDATE person SET age = '24' WHERE id = c001;
数据删除,语法示例如下:
DELETE FROM person WHERE id = c002;
数据Merge,支持批量查询、更新、删除。语法可参考:
https://github.com/apache/carbondata/blob/master/examples/spark/src/main/scala/org/apache/carbondata/examples/CDCExample.scala
结语
CarbonData提供了一种新的融合数据存储方案,以一份数据同时支持多种应用场景,EB级别数据规模,查询性能秒级响应。可以看出CarbonData目前的架构和想法都十分先进,在体验了CarbonData 2.0 RC2的强大功能后,笔者也更加期待5月中CarbonData 2.0的正式版本发布了,大家一起拭目以待。
欢迎大家添加微信ID:xu601450868,加入CarbonData技术交流群。