Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

使用Impala/Presto/ES/kudu/Parquet基准测试

目的

本测试报告为调研OLAP性能测试报告,目的在于总结调研的几个存储查询方案的可用性。

背景

考虑到数据量的的增多以及用户并发操作给服务器造成压力,因此对kudu、parquet、presto、Es 等进行存储及查询的性能测试,在系统配置不变的情况下,观察各计算引擎的的操作耗时表现,便于对正确的进行技术选型与评估。

 

环境准备

本次测试方案的硬件环境使用三台物理机,系统为centos7,基础配置信息如下表:

服务器 cpu核数 内存大小 磁盘空间
server1 40 192g 3.6T
server2 40 192g 3.6T
server3 40 192g 3.6T

本次测试搭建的大数据环境为CDH6.3.2,所有组件都采用分布式搭建于三台服务器。

 

impala + kudu Vs impala + parquet

 

TPC-DS 介绍

TPC-DS采用星型、雪花型等多维数据模式。它包含7张事实表,17张维度表平均每张表含有18列。其工作负载包含99个SQL查询,覆盖SQL99和2003的核心部分以及OLAP。这个测试集包含对大数据集的统计、报表生成、联机查询、数据挖掘等复杂应用,测试用的数据和值是有倾斜的,与真实数据一致。可以说TPC-DS是与真实场景非常接近的一个测试集,也是难度较大的一个测试集。

TPC-DS支持指定不同的数据大小。本次测试选择的数据大小分别为100GB、1TB。数据大小与表rows的关系如下图所示。

 

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

测试步骤

1.安装TPC-DS工具并生成测试数据dat文件和查询语句。

2.在HDFS新建目录,将测试数据dat文件上传到HDFS中。

3.将TPC-DS提供的Kudu/parquet DDL语句做语法兼容改造。

4.准备impala外部表DDL。

5.执行kudu/parquet内部表ddl,将impala外部表数据导入到kudu/parquet内部表,调用统计分析SQL

6.整理TPC-DS提供的SQL基准查询语句,由于有些语法不兼容kudu/parquet,需要进行手动调整,最后整理到单独SQL文件中,最后调整出79个可兼容sql。

7.执行手动调整过后的TPC—DS的SQL基准查询。

8.收集执行结果信息到result目录查看,具体的SQL文件执行日志在logs目录查看。

测试结果

 

首先我们比较一下1T 下impala on kudu 和impala on parquet的性能

 

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

再对比下 1T 数据的时间对比

 

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

     如图所示,单从查询来看,kudu的性能和parquet差距不是特别大,但是阅读网络上的一些对两者的性能评测的文章,很多评测性能更倾向于parquet 。 其实不难分析,创建kudu 表前提是必须对分区初始化和创建主键,而tpc-ds 的数据分布对parquet 而言,那些当作Kudu 主键的数据很难甚至不能当作parquet的分区数据,导致不能利用到impala 分区谓词下推的特性,所以由此来看,本次性能测试还是偏心的。但如果能充分利用到分区特性,parquet 恐怕会更胜一筹吧。

因为impala 查询引擎定位于olap 方向,所以在高并发上并不是很在行。不过在以上数据的基础上,还是进行了并发测试,在10个并发的情况下, 对简单条件的sql查询,时间耗时已经是原来1个并发的3-5倍了。

 

presto + orc Vs presto + parquet

由于 presto 未生成系统的时间耗时数据,这里就不放耗时数据了。相同资源相同查询条件的环境下,但是差别并不是特别大, orc 的查询速度略快于parquet格式。可能这也是两者中更推荐presto + orc 这种组合。

再对比 impala 、presto的查询方式,相同查询查询条件,presto 是impala 的查询速度的1.5倍左右。由于presto也是定位于olap 方向,由于Mpp 的查询特性,会把数据加载到内存中计算,所以方面Presto 也不会支持很高的并发,10个并发时也是下降了2-3倍。

 

ES + X

Hbase 由于rowkey 的特性,使得Hbase 在最左原则的查询方面存在天然的优势,但在多维度查询或者分析的情况下就略逊一筹了。Kudu 虽然解决了Hbase 分析慢的痛点,但是由于不能建立二级索引,也不得不遵从最左原则使得查询耗时减少,这也给它多维分析带来了致命问题。

Elasticsearch是一个基于Lucene的搜索服务器,定位很明确: 搜索。列式存储和倒排索引使得他可以多条件*组合的进行查询,倒排索引的特性在对减少索引数据耗时的优势上发挥的淋漓尽致,对一些大数据量的搜索并且小数据量的输出是一个很适合的使用场景。可是官方不并推荐Elasticsearch当作存储引擎。

取 Elasticsearch 的多条件*组合查询的优势,再结合Hbase或 Kudu存储+数据get获取的优势,将数据明细存储到Hbase 中,索引数据存储到ES 中, ES+ Kudu / ES + Hbase 可能是一个不错的选项。Hbase 或 Kudu 在单查方面有着可人的输出,ES 查询的输出的结果量并不是特别大,在大数据量的加持下,ES+ Kudu / ES + Hbase 的查询组合,瓶颈一定在 ES 查询上,所以这里仅对 ES 查询做了性能评测。

 

数据准备

导入 TPC-DS工具 生成的1T 数据中的catalog_sales 表数据,14.3亿条记录。这里使用的是spark 进行数据导入, 14.3亿条数据。其中3个shards,2个副本。 mapping结构如下:

{
  "settings": {
      "number_of_shards": 3,
      "number_of_replicas": 2
  },
  "mappings": {
          "properties": {
              "cs_sold_date_sk"   : {"type": "integer"} ,
              "cs_sold_time_sk"   : {"type": "integer"} ,
              "cs_ship_date_sk"   : {"type": "integer"} ,
              "cs_bill_customer_sk" : {"type": "integer ,
              "cs_bill_cdemo_sk" : {"type": "integer"} ,
              "cs_bill_hdemo_sk" : {"type": "integer"} ,
              "cs_bill_addr_sk"   : {"type": "integer"} ,
              "cs_ship_customer_sk" : {"type": "integer"} ,
              "cs_ship_cdemo_sk" : {"type": "integer"} ,
              "cs_ship_hdemo_sk" : {"type": "integer"} ,
              "cs_ship_addr_sk"   : {"type": "integer"} ,
              "cs_call_center_sk"   : {"type": "integer"} ,
              "cs_catalog_page_sk"   : {"type": "integer"} ,
              "cs_ship_mode_sk"   : {"type": "integer"} ,
              "cs_warehouse_sk"   : {"type": "integer"} ,
              "cs_item_sk"   : {"type": "integer"}   ,
              "cs_promo_sk" : {"type": "integer"} ,
              "cs_order_number"   : {"type": "integer"} ,
              "cs_quantity" : {"type": "integer"}
          }
      }
}

减少误差的操作

在查询之前,作出以下操作减少误差:

1、脚本会将缓存清除,查询条件以及分页参数设置为动态值,以此来减少缓存带来的误差。

curl -H \'Content-Type: application/json\' -XPOST http://xxxx:9200/_cache/clear

2、ES master 设置为3个,查询脚本中的http地址随机设置为3个地址中的一个,尽可能均衡到每台服务节点上。

3、无论range 还是 term 操作,将结果数据量控制在一个数级。

 

性能测试

场景:条件查询 (term)

curl --location --request GET 'http://xxxx:9200/catalog_sales/_doc/_search' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": {
  "bool": {
    "must": [
    {
        "term": {
          "cs_ship_hdemo_sk": "5037"
        }
      }
    ]
  }
},
"track_total_hits": true,
"from": 18,
"size": 10
}'

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试 

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

场景:条件查询 + 范围查询 (term + range)

curl --location --request GET 'http://10.135.3.203:9200/catalog_sales/_doc/_search' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": {
  "bool": {
    "must": [
    {
        "term": {
          "cs_ship_hdemo_sk": "2489"
        }
      },
      {
        "range": {
          "cs_sold_date_sk": {
            "gte": "2451510",
            "lte": "2451790"
          }
        }
      }
    ]
  }
},
"track_total_hits": true,
"from": 12,
"size": 10
}'

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试 

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

场景:条件查询 + 范围查询 + 聚合(term + range + agg)

curl --location --request GET 'http://10.135.3.203:9200/catalog_sales/_doc/_search' \
--header 'Content-Type: application/json' \
--data-raw '{
"query": {
  "bool": {
    "must": [
    {
        "term": {
          "cs_ship_hdemo_sk": "409"
        }
      },
      {
        "range": {
          "cs_sold_date_sk": {
            "gte": "2450864",
            "lte": "2452452"
          }
        }
      }
    ]
  }
},
"aggs": {
  "group_by_word_count": {
    "terms": {
      "field": "cs_ship_hdemo_sk"
    }
  }
  },
"track_total_hits": true,
"from": 12,
"size": 10
}'

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试 

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

 

场景:条件查询 + 范围查询 + 多聚合(term + range + multi agg)
 

curl --location --request GET \'http://xxxxx:9200/catalog_sales/_doc/_search\' 
--header \'Content-Type: application/json\' 
--data-raw \'{
query: {
bool: {
must: [
{
term: {
cs_ship_hdemo_sk: 6042
}
},
{
range: {
cs_sold_date_sk: {
gte: 2450989,
lte: 2451728
}
}
}
]
}
},
aggs: {
group_by_cs_sold_date_sk: {
terms: {
field: cs_sold_date_sk
}
},
group_by_cs_promo_sk: {
stats: {
field: cs_promo_sk
}
},
group_by_cs_quantity: {
stats: {
field: cs_quantity
}
}
},
track_total_hits: true,
from: 11,
size: 10
}'

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

 

Kudu拓展

Kudu目前也是apache下面的开源项目。Hadoop生态圈中的技术繁多,HDFS作为底层数据存储的地位一直很牢固。而HBase作为Google BigTable的开源产品,一直也是Hadoop生态圈中的核心组件,其数据存储的底层采用了HDFS,主要解决的是在超大数据集场景下的随机读写和更新的问题。

Kudu通过要求完整的表结构设置,主键的设定,以列式存储作为数据在磁盘上的组织方式,更新和数据分开等技巧,使得Kudu能够实现像HBase一样实现数据的随机读写之外,在HBase不太擅长的批量数据扫描(scan)具有较好的性能。而批量读数据正是olap型应用所关注的重点,Kudu的设计有参考HBase的结构,也能够实现HBase擅长的快速的随机读写、更新功能,也可以实现数据的快速分析。Kudu的定位不是取代HBase,而是以降低写的性能为代价,提高了批量读的性能,使其能够实现快速在线分析。

Kudu 物理架构

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

Kudu 存储原理

Impala/Presto/ES/kudu/Parquet TPC_DS基准测试

Kudu Vs Hbase

1、自有存储介质,非HDFS 存储,读取更快

2、完全列式存储,减少读取内容

3、限定列类型,设置合适的编码方式,实现更高的数据压缩比,进而降低数据读入时的IO压力

4、Kudu对同一行的数据更新记录的合并工作,不是在查询的时候发生的,而是在更新的时候进行

5、核心模块用的C++来实现,没有full gc的风险;

6、timestamp连续,搜索时间小

7、聚合分析不一定需要取出主键,减少IO压力

总结

这里调研了 Impala + Parquet , Impala + Kudu,Presto + Parquet , Presto + ORC , ES 。其中 Impala + Parquet , Impala + Kudu 查询性能相似,但是不可否认的是假如去除“偏心”的查询后,Impala + Parquet可能会更胜一筹,但是对于存在可删除、修改功能的 Impala + Kudu 来说,此时也并非一个不能选择的选项。 Presto + ORC 这里调研显示速度一般吧,但是Presto 也具有不可忽略的优点: 多源数据分析,这也是Presto 存在的场景。 ES 作为索引届的王者,在索引数据方面呈现出无与伦比的优势,ES + X是个不错的选项。

 

 

上一篇:深入理解TCP协议及其源代码


下一篇:Socket与系统调用深度分析