在Hadoop平台运维监控中,Hive表的统计信息通常是作为集群数据质量的关键依据;通常以Hive表的大小、行数、分区数等信息来衡量集群数据量的增减趋势;本文以Hive表Size大小和数据行数作为重点,对于超大表统计时避免过多的资源消耗
两种常规方式统计:
- 方式一:
size 统计:1
long size = FileSystem.getContentSummary(new Path(tablePath)).getLength();
rowCount统计:
1 | select count(*) from tableName; |
- 方式二:
size统计:
1 | hadoop fs -du -s tablePath |
rowCount统计(非Orc、Parquet):
1 | hadoop fs -text tablePath | wc -l |
常规方式在获取rowCount时都有局限性(例如OrcFile无法用hadoop fs -text),并且效率不高
ANALYZE 方式统计
ANALYZE TABLE tablename [PARTITION(partcol1[=val1], partcol2[=val2], …)] COMPUTE STATISTICS [noscan];
考虑到表的统计值通常是要通过计算后记录到某个地方,执行ANALYZE的时候才会快速显示;为此探究什么情况下导入Hive数据,ANALYZE的结果准确
下文会以TextFile、SequenceFile、OrcFile、ParquetFile,四种常见的Hive表文件格式来做测试
Hive数据导入途径:
1. Load file to hive table
2. Add partition and mv file to partition path
3. Insert into
测试数据文件
1 | // 数据文件 count = 20 |
TextFile
1 | // create table |
- Load file to table
1 | hive> LOAD DATA LOCAL INPATH '/home/hadoop/wxm/test.txt' OVERWRITE INTO TABLE analyze_text partition(part_date='2019-02-21'); |
1 | hive> ANALYZE TABLE analyze_text PARTITION(part_date='2019-02-21') COMPUTE STATISTICS noscan; |
Load 操作实际上是执行了 mv 操作,将文件移动到表目录下面;ANALYZE 只能查看到numFiles(文件数)和totalSize(分区总大小)
- Add partition and mv file to partition path
1 | // add partition |
1 | hive> ANALYZE TABLE analyze_text PARTITION(part_date='2019-02-20') COMPUTE STATISTICS noscan; |
和Load操作一样,ANALYZE 只能查看到numFiles(文件数)和totalSize(分区总大小)
- Insert into
1 | hive> insert into table analyze_text partition(part_date='2019-02-19') select `id`,`name` from analyze_text_copy where part_date='2019-02-21'; |
1 | hive> ANALYZE TABLE analyze_text PARTITION(part_date='2019-02-19') COMPUTE STATISTICS noscan; |
由于insert into 用了 MapReduce,在计算的过程中就已经将表的统计信息记录了下来,所以numRows、rawDataSize都有
SequenceFile
1 | // create table |
- Load file to table
1 | hive> LOAD DATA LOCAL INPATH '/home/hadoop/wxm/analyze_sequence_test_file' OVERWRITE INTO TABLE analyze_sequence_test partition(part_date='2019-02-21'); |
1 | hive> ANALYZE TABLE analyze_sequence_test PARTITION(part_date='2019-02-21') COMPUTE STATISTICS noscan; |
stats: [numFiles=1, numRows=0, totalSize=607, rawDataSize=0]
- Add partition and mv file to partition path
1 | // add partition |
1 | ANALYZE TABLE analyze_sequence_test PARTITION(part_date='2019-02-20') COMPUTE STATISTICS noscan; |
由于sequenceFile文件的head中没有存储row的相关信息,所以获取不到
- Insert into
1 | hive> insert into table analyze_sequence_test partition(part_date='2019-02-19') select `id`,`name` from analyze_text_copy where part_date='2019-02-21'; |
1 | hive> ANALYZE TABLE analyze_sequence_test PARTITION(part_date='2019-02-19') COMPUTE STATISTICS noscan; |
stats: [numFiles=1, numRows=20, totalSize=607, rawDataSize=260]
OrcFile
1 | // create table |
- Load file to table
1 | hive> LOAD DATA LOCAL INPATH '/home/hadoop/wxm/analyze_orc_test_file' OVERWRITE INTO TABLE analyze_orc_test partition(part_date='2019-02-21'); |
1 | hive> ANALYZE TABLE analyze_orc_test PARTITION(part_date='2019-02-21') COMPUTE STATISTICS noscan; |
stats: [numFiles=1, numRows=20, totalSize=365, rawDataSize=3600]
- Add partition and mv file to partition path
1 | // add partition |
1 | hive> ANALYZE TABLE analyze_orc_test PARTITION(part_date='2019-02-20') COMPUTE STATISTICS noscan; |
stats: [numFiles=1, numRows=20, totalSize=365, rawDataSize=3600]
- Insert into
1 | hive> insert into table analyze_orc_test partition(part_date='2019-02-19') select `id`,`name` from analyze_text_copy where part_date='2019-02-21'; |
1 | hive> ANALYZE TABLE analyze_orc_test PARTITION(part_date='2019-02-19') COMPUTE STATISTICS noscan; |
stats: [numFiles=1, numRows=20, totalSize=365, rawDataSize=3600]
Parquet
1 | // create table |
- Load file to table
1 | hive> LOAD DATA LOCAL INPATH '/home/hadoop/wxm/analyze_parquet_test_file' OVERWRITE INTO TABLE analyze_parquet_test partition(part_date='2019-02-21'); |
1 | hive> ANALYZE TABLE analyze_parquet_test PARTITION(part_date='2019-02-21') COMPUTE STATISTICS noscan; |
stats: [numFiles=1, numRows=0, totalSize=390, rawDataSize=0]
- Add partition and mv file to partition path
1 | // add partition |
1 | hive> ANALYZE TABLE analyze_parquet_test PARTITION(part_date='2019-02-20') COMPUTE STATISTICS noscan; |
stats: [numFiles=1, totalSize=390]
- Insert into
1 | hive> insert into table analyze_parquet_test partition(part_date='2019-02-19') select `id`,`name` from analyze_text_copy where part_date='2019-02-21'; |
1 | hive> ANALYZE TABLE analyze_parquet_test PARTITION(part_date='2019-02-19') COMPUTE STATISTICS noscan; |
stats: [numFiles=1, numRows=20, totalSize=390, rawDataSize=40]
Result
通过上述测试可以看出,OrcFile文件的三种数据导入方式可以直接通过ANALYZE获取完整信息,其他文件格式默认只能获取到Size,除非insert into
触发了MapReduce
时才能获取RowCount
ANALYZE耗时非常短,文件的统计数据一定是存储在某个地方不需要RunTime去计算(查询了Hive MetaStore,并没有发现表Row的统计存储)
,猜想原因在于OrcFile的自描述Header里存储了对Row的统计信息,ANALYZE会直接获取自描述文件中的统计信息,可以看下文件的Dump
Hive Orc File Dump
1 | // Orc Dump |
可以看到Dump信息里面有Rows: 20的信息,所以可以确定ANALYZE 命令是分析了file的meta
Parquet File Dump
1 | hadoop jar parquet-tools-1.5.0.jar dump hdfs://sdg/user/hive/warehouse/dw.db/analyze_parquet_test/part_date=2019-02-19/000000_0 |
虽然看到Dump文件中有TV=20,但是不像ORC File 有完整的Row信息,meta还是基于列的,所以读取不到
MapReduce 统计
我们想要获取完整的表统计信息,可以将
ANALYZE
命令的noscan
去掉执行,则会触发一个MapReduce,这个MR会对表文件做一个统计,并将结果存储到Hive MetaStore中,后续在用ANALYZE
分析就会直接得到结果
1 | hive> ANALYZE TABLE analyze_parquet_test PARTITION(part_date='2019-02-21') COMPUTE STATISTICS; |
1 | hive> ANALYZE TABLE analyze_parquet_test PARTITION(part_date='2019-02-21') COMPUTE STATISTICS noscan; |
总结
我们可以看到利用ANALYZE
命令可以快速帮助我们分析一张表的基本统计信息,但也有缺点:如果是分区表,写分区则会列出这个分区的统计,不写分区会列出所有分区的数据列表;并没有一个队整张表进行的汇总统计
,所以通常需要配合最开始提到的两种常用方法
对于OrcFile则直接可以用ANALYZE
命令分析,如果是TextFile、SequenceFile、ParquetFile,则需要确保Hive 表的数据加载方式是通过MapReduce,其他方式Load数据的则需要执行noscan 的ANALYZE(可以准备离线任务,每天对非MR Load的数据表执行一次);也可以在执行ETL的时候,将统计作为一个回调自动完成
- Size
1 | long size = FileSystem.getContentSummary(new Path(tablePath)).getLength(); |
此方法可以获取一个表路径、分区路径以及具体文件的Size大小;Size是压缩后的值
全表的统计可以将tablePath截止到tableName就可以,获取某个分区的统计,则tablePath精确到分区目录
- RowCount
1 | ANALYZE TABLE tablName [PARTITION(part)] COMPUTE STATISTICS noscan; |
此方法会列出所有表的分区统计,解析这些统计并将numRows加总就是全表的RowCount;如果是非分区表或只想获取当前分区的统计,则只解析一条记录
转载请注明出处:https://github.com/imperio-wxm