本文介绍云原生多模数据库 Lindorm在不同场景下与开源HBase、开源MySQL和开源MongoDB之间压缩能力的对比结果。
背景信息
Lindorm除多模超融合、开放兼容和云原生弹性等能力外,还具备了高效的数据压缩能力。Lindorm不仅支持深度优化的ZSTD压缩算法,还在此基础上对字典采样进行了优化,进一步减少存储成本。
本文测试压缩能力所使用到的数据库版本及其说明如下:
- Lindorm:使用阿里云发行的最新版本。默认使用深度优化的ZSTD压缩算法,支持开启字典压缩。 
- 开源HBase:使用2.3.4版本。在有高版本Hadoop支撑的情况下支持ZSTD压缩算法,但不稳定且易发生进程崩溃现象(Core Dump)。绝大部分自建HBase用户使用SNAPPY压缩算法。 
- 开源MySQL:使用8.0版本。默认不开启数据压缩。MySQL虽然支持ZLIB压缩算法,但由于开启数据压缩后会对查询性能产生严重影响,因此MySQL用户基本不会开启数据压缩。 
- 开源MongoDB:使用5.0版本。默认使用SNAPPY压缩算法,同时支持将SNAPPY算法替换为ZSTD算法。 
本文选取了订单、车联网、日志和用户行为这四个在Lindorm中常见的场景,使用真实的数据集分别测试了Lindorm默认压缩、Lindorm开启字典压缩、HBase使用SNAPPY算法压缩、MySQL不开启压缩、MongoDB使用SNAPPY算法压缩和MongoDB使用ZSTD算法压缩这六种方式的压缩能力。
各场景下的测试对比结果汇总及测试结论请参见测试对比结果。
订单场景
数据准备
该场景使用TPC-H数据集进行压缩测试。TPC-H是业界常用的一套基准程序,由TPC委员会制定发布,用于评测数据库的分析型查询能力。
本测试并未完全依照<TPC benchmark name>基准测试规范,而是基于该测试规范进行了修改。本测试结果不能等同于完全遵守<TPC benchmark name>测试规范所获得的测试结果,因此不能与完全遵守该测试规范获得的测试结果进行对比。
TPC-H程序下载
生成数据
# unzip TPC-H_Tools_v3.0.0.zip
# cd TPC-H_Tools_v3.0.0/dbgen
# cp makefile.suite makefile
# vim makefile
################生成Oracle数据库的脚本和数据,主要修改以下字段
CC = gcc
DATABASE = ORACLE
MACHINE = LINUX
WORKLOAD = TPCH
################
# make  --生成dbgen
# ./dbgen -s 10  --生成10GB数据执行完成后会在当前目录下生成8个.tbl格式的文件,每一个文件对应一张表。选择ORDERS.tbl文件进行压缩测试,文件大小为1.76 GB,共有数据1500万行,对应表结构如下:
| Field | Type | 
| O_ORDERKEY | INT | 
| O_CUSTKEY | INT | 
| O_ORDERSTATUS | CHAR(1) | 
| O_TOTALPRICE | DECIMAL(15,2) | 
| O_ORDERDATE | DATE | 
| O_ORDERPRIORITY | CHAR(15) | 
| O_CLERK | CHAR(15) | 
| O_SHIPPRIORITY | INT | 
| O_COMMENT | VARCHAR(79) | 
建表
HBase
create 'ORDERS', {NAME => 'f', DATA_BLOCK_ENCODING => 'DIFF', COMPRESSION => 'SNAPPY', BLOCKSIZE => '32768}MySQL
CREATE TABLE ORDERS  ( O_ORDERKEY       INTEGER NOT NULL,
                       O_CUSTKEY        INTEGER NOT NULL,
                       O_ORDERSTATUS    CHAR(1) NOT NULL,
                       O_TOTALPRICE     DECIMAL(15,2) NOT NULL,
                       O_ORDERDATE      DATE NOT NULL,
                       O_ORDERPRIORITY  CHAR(15) NOT NULL,
                       O_CLERK          CHAR(15) NOT NULL,
                       O_SHIPPRIORITY   INTEGER NOT NULL,
                       O_COMMENT        VARCHAR(79) NOT NULL);MongoDB
db.createCollection("ORDERS")Lindorm
# lindorm-cli
CREATE TABLE ORDERS  ( O_ORDERKEY       INTEGER NOT NULL,
                      O_CUSTKEY        INTEGER NOT NULL,
                      O_ORDERSTATUS    CHAR(1) NOT NULL,
                      O_TOTALPRICE     DECIMAL(15,2) NOT NULL,
                      O_ORDERDATE      DATE NOT NULL,
                      O_ORDERPRIORITY  CHAR(15) NOT NULL,
                      O_CLERK          CHAR(15) NOT NULL,
                      O_SHIPPRIORITY   INTEGER NOT NULL,
                      O_COMMENT        VARCHAR(79) NOT NULL,
                      primary key(O_ORDERKEY));压缩效果对比

| 数据库 | Lindorm (默认压缩) | Lindorm (字典压缩) | HBase (SNAPPY) | MySQL | MongoDB (默认SNAPPY) | MongoDB (ZSTD) | 
| 表大小 | 784 MB | 639 MB | 1.23 GB | 2.10 GB | 1.63 GB | 1.32 GB | 
车联网场景
该场景使用NGSIM数据集。NGSIM(Next Generation Simulation)是由美国联邦公路局发起的一项数据采集项目,广泛应用于车辆的跟驰和换道等驾驶行为的研究、交通流分析、微观交通模型构建、车辆运动轨迹预测和自动驾驶决策规划等。所有数据来源于美国高速公路国道101上的实际运行轨迹采集。
数据准备
搜索并下载数据集文件NGSIM_Data.csv。文件大小1.54GB,共有数据1185万行,每行25列。数据结构的详细介绍及下载方式,请参见NGSIM数据集。
建表
HBase
create 'NGSIM', {NAME => 'f', DATA_BLOCK_ENCODING => 'DIFF', COMPRESSION => 'SNAPPY', BLOCKSIZE => '32768}MySQL
CREATE TABLE NGSIM ( ID								 INTEGER NOT NULL,
                     Vehicle_ID				 INTEGER NOT NULL,
                     Frame_ID					 INTEGER NOT NULL,
                     Total_Frames			 INTEGER NOT NULL,
                     Global_Time			 BIGINT NOT NULL,
                     Local_X					 DECIMAL(10,3) NOT NULL,
                     Local_Y					 DECIMAL(10,3) NOT NULL,
                     Global_X					 DECIMAL(15,3) NOT NULL,
                     Global_Y					 DECIMAL(15,3) NOT NULL,
                     v_length					 DECIMAL(10,3) NOT NULL,
                     v_Width					 DECIMAL(10,3) NOT NULL,
                     v_Class					 INTEGER NOT NULL,
                     v_Vel						 DECIMAL(10,3) NOT NULL,
                     v_Acc						 DECIMAL(10,3) NOT NULL,
                     Lane_ID					 INTEGER NOT NULL,
                     O_Zone						 CHAR(10),
                     D_Zone						 CHAR(10),
                     Int_ID						 CHAR(10),
                     Section_ID				 CHAR(10),
                     Direction				 CHAR(10),
                     Movement					 CHAR(10),
                     Preceding				 INTEGER NOT NULL,
                     Following				 INTEGER NOT NULL,
                     Space_Headway		 DECIMAL(10,3) NOT NULL,
                     Time_Headway			 DECIMAL(10,3) NOT NULL,
                     Location					 CHAR(10) NOT NULL,
                     PRIMARY KEY(ID));MongoDB
db.createCollection("NGSIM")Lindorm
# lindorm-cli
CREATE TABLE NGSIM ( ID								 INTEGER NOT NULL,
                     Vehicle_ID				 INTEGER NOT NULL,
                     Frame_ID					 INTEGER NOT NULL,
                     Total_Frames			 INTEGER NOT NULL,
                     Global_Time			 BIGINT NOT NULL,
                     Local_X					 DECIMAL(10,3) NOT NULL,
                     Local_Y					 DECIMAL(10,3) NOT NULL,
                     Global_X					 DECIMAL(15,3) NOT NULL,
                     Global_Y					 DECIMAL(15,3) NOT NULL,
                     v_length					 DECIMAL(10,3) NOT NULL,
                     v_Width					 DECIMAL(10,3) NOT NULL,
                     v_Class					 INTEGER NOT NULL,
                     v_Vel						 DECIMAL(10,3) NOT NULL,
                     v_Acc						 DECIMAL(10,3) NOT NULL,
                     Lane_ID					 INTEGER NOT NULL,
                     O_Zone						 CHAR(10),
                     D_Zone						 CHAR(10),
                     Int_ID						 CHAR(10),
                     Section_ID				 CHAR(10),
                     Direction				 CHAR(10),
                     Movement					 CHAR(10),
                     Preceding				 INTEGER NOT NULL,
                     Following				 INTEGER NOT NULL,
                     Space_Headway		 DECIMAL(10,3) NOT NULL,
                     Time_Headway			 DECIMAL(10,3) NOT NULL,
                     Location					 CHAR(10) NOT NULL,
                     PRIMARY KEY(ID)) ;压缩效果对比

| 数据库 | Lindorm (默认压缩) | Lindorm (开启字典压缩) | HBase (SNAPPY) | MySQL | MongoDB (默认SNAPPY) | MongoDB (ZSTD) | 
| 表大小 | 995 MB | 818 MB | 1.72 GB | 2.51 GB | 1.88 GB | 1.50 GB | 
日志场景
使用Web服务器访问日志数据集:Zaker, Farzin, 2019, "Online Shopping Store - Web Server Logs", https://doi.org/10.7910/DVN/3QBYB5, Harvard Dataverse, V1。
数据准备
在日志数据集网页下载日志文件access.log。文件大小为3.51GB,共有数据1036万行,日志数据格式示例如下:
54.36.149.41 - - [22/Jan/2019:03:56:14 +0330] "GET /filter/27|13%20%D9%85%DA%AF%D8%A7%D9%BE%DB%8C%DA%A9%D8%B3%D9%84,27|%DA%A9%D9%85%D8%AA%D8%B1%20%D8%A7%D8%B2%205%20%D9%85%DA%AF%D8%A7%D9%BE%DB%8C%DA%A9%D8%B3%D9%84,p53 HTTP/1.1" 200 30577 "-" "Mozilla/5.0 (compatible; AhrefsBot/6.1; +http://ahrefs.com/robot/)" "-"建表
HBase
create 'ACCESS_LOG', {NAME => 'f', DATA_BLOCK_ENCODING => 'DIFF', COMPRESSION => 'SNAPPY', BLOCKSIZE => '32768}MySQL
CREATE TABLE ACCESS_LOG  ( ID        INTEGER NOT NULL,
                           CONTENT   VARCHAR(10000),
                           PRIMARY KEY(ID));MongoDB
db.createCollection("ACCESS_LOG")Lindorm
# lindorm-cli
CREATE TABLE ACCESS_LOG  ( ID        INTEGER NOT NULL,
                           CONTENT   VARCHAR(10000),
                           PRIMARY KEY(ID));压缩效果对比

| 数据库 | Lindorm (默认压缩) | Lindorm (字典压缩) | HBase (SNAPPY) | MySQL | MongoDB (SNAPPY) | MongoDB (ZSTD) | 
| 表大小 | 646 MB | 387 MB | 737 MB | 3.99 GB | 1.17 GB | 893 MB | 
用户行为
该场景使用来自阿里云天池的数据集:Shop Info and User Behavior data from IJCAI-15。
数据准备
在用户行为数据集网页下载data_format1.zip,并选用user_log_format1.csv文件,文件大小为1.91 GB,共有数据5492万行。文件结构示例如下:
| user_id | item_id | cat_id | seller_id | brand_id | time_stamp | action_type | 
| 328862 | 323294 | 833 | 2882 | 2661 | 829 | 0 | 
| 328862 | 844400 | 1271 | 2882 | 2661 | 829 | 0 | 
| 328862 | 575153 | 1271 | 2882 | 2661 | 829 | 0 | 
建表
HBase
create 'USER_LOG', {NAME => 'f', DATA_BLOCK_ENCODING => 'DIFF', COMPRESSION => 'SNAPPY', BLOCKSIZE => '32768}MySQL
CREATE TABLE USER_LOG  ( ID            INTEGER NOT NULL,
                         USER_ID       INTEGER NOT NULL,
                         ITEM_ID       INTEGER NOT NULL,
                         CAT_ID        INTEGER NOT NULL,
                         SELLER_ID     INTEGER NOT NULL,
                         BRAND_ID      INTEGER,
                         TIME_STAMP    CHAR(4) NOT NULL,
                         ACTION_TYPE   CHAR(1) NOT NULL,
                         PRIMARY KEY(ID));MongoDB
db.createCollection("USER_LOG")Lindorm
# lindorm-cli
CREATE TABLE USER_LOG  ( ID            INTEGER NOT NULL,
                         USER_ID       INTEGER NOT NULL,
                         ITEM_ID       INTEGER NOT NULL,
                         CAT_ID        INTEGER NOT NULL,
                         SELLER_ID     INTEGER NOT NULL,
                         BRAND_ID      INTEGER,
                         TIME_STAMP    CHAR(4) NOT NULL,
                         ACTION_TYPE   CHAR(1) NOT NULL,
                         PRIMARY KEY(ID));压缩效果对比

| 数据库 | Lindorm (默认压缩) | Lindorm (字典压缩) | HBase (SNAPPY) | MySQL | MongoDB (SNAPPY) | MongoDB (ZSTD) | 
| 表大小 | 805 MB | 721 MB | 1.48 GB | 2.90 GB | 3.33 GB | 2.74 GB | 
总结
通过上述对比可以得知,在不同的场景下,面对类型不同且数据量较大的数据,即使不开启字典压缩,Lindorm的压缩比相较于其他开源数据库也有明显的优势。在开启了字典压缩之后,Lindorm的压缩效果更加突出,压缩效果几乎是开源HBase的1~2倍,开源MongoDB的2~4倍,开源MySQL的3~10倍。
各场景下的测试对比结果汇总如下:
| 数据 | 文件大小 | Lindorm (默认压缩) | Lindorm (字典压缩) | HBase (SNAPPY) | MySQL | MongoDB (SNAPPY) | MongoDB (ZSTD) | 
| 订单数据 (TPC-H) | 1.76 GB | 784 MB | 639 MB | 1.23 GB | 2.10 GB | 1.63 GB | 1.32 GB | 
| 车联网数据(NGSIM) | 1.54 GB | 995 MB | 818 MB | 1.72 GB | 2.51 GB | 1.88 GB | 1.50 GB | 
| 日志数据 (server log) | 3.51 GB | 646 MB | 387 MB | 737 MB | 3.99 GB | 1.17 GB | 893 MB | 
| 用户行为数据(IJCAI-15) | 1.91 GB | 805 MB | 721 MB | 1.48 GB | 2.90 GB | 3.33 GB | 2.74 GB |