本文从普通用户的角度讲述 Hive 统计信息,源代码角度请参考。
统计信息的分类
有两种统计信息,第1种为表和分区的统计信息,第2种为分区的统计信息。
表和分区的统计信息
表的统计信息
包括如下内容:
- numFiles – 文件的数量
- numRows – 记录数量
- totalSize – 总文件大小
- rawDataSize – 原始数据量(因为可以压缩后存储到文件里)
对于分区表,还包括以下内容:
- numPartitions 1824
显示表的统计信息的语句。
desc extended table_name;
或者
desc formatted table_name;
其中,用 desc formatted table_name
是格式化输出,更容易阅读,统计信息在 Table Parameters
部分,如下面的示例。
Table Parameters:
COLUMN_STATS_ACCURATE {\"BASIC_STATS\":\"true\"}
bucketing_version 2
numFiles 1826
numPartitions 1824
numRows 2160165
rawDataSize 3930709572
totalSize 122202436
transient_lastDdlTime 1646036041
分区的统计信息
分区的统计信息,内容和非分区表的统计信息一致。显示方法示例:
desc formatted web_sales partition(ws_sold_date_sk=2452642);
在 Partition Parameters:
部分可以找到分区的统计信息。
Partition Parameters:
COLUMN_STATS_ACCURATE {\"BASIC_STATS\":\"true\"}
numFiles 1
numRows 2379
rawDataSize 4329780
totalSize 127832
transient_lastDdlTime 1646036434
字段的统计信息
字段的统计信息包括字段的最大值,最小值,null 的数量,distinct 的数量等。如一个表的字段统计信息已经收集,在 desc formatted table_name
时,Table Parameters:
的 COLUMN_STATS_ACCURATE
有COLUMN_STATS,对应的字段为 true,则表示该字段的统计信息已经收集。 可以用类似以下的命令显示。
desc formatted web_site;
Table Parameters:
COLUMN_STATS_ACCURATE {\"BASIC_STATS\":\"true\",\"COLUMN_STATS\":{\"web_city\":\"true\",\"web_class\":\"true\",\"web_close_date_sk\":\"true\",\"web_company_id\":\"true\",\"web_company_name\":\"true\",\"web_country\":\"true\",\"web_county\":\"true\",\"web_gmt_offset\":\"true\",\"web_manager\":\"true\",\"web_market_manager\":\"true\",\"web_mkt_class\":\"true\",\"web_mkt_desc\":\"true\",\"web_mkt_id\":\"true\",\"web_name\":\"true\",\"web_open_date_sk\":\"true\",\"web_rec_end_date\":\"true\",\"web_rec_start_date\":\"true\",\"web_site_id\":\"true\",\"web_site_sk\":\"true\",\"web_state\":\"true\",\"web_street_name\":\"true\",\"web_street_number\":\"true\",\"web_street_type\":\"true\",\"web_suite_number\":\"true\",\"web_tax_percentage\":\"true\",\"web_zip\":\"true\"}}
bucketing_version 2
numFiles 1
numRows 32
rawDataSize 65968
totalSize 6379
transient_lastDdlTime 1646818911
查看分区的字段统计信息还是用以下命令。
desc formatted web_sales partition(ws_sold_date_sk=2452642);
显示一个字段的统计信息
非分区表字段的统计信息
DESCRIBE FORMATTED web_site web_site_sk;
OK
col_name web_site_sk
data_type bigint
min 1
max 32
num_nulls 0
distinct_count 32
avg_col_len
max_col_len
num_trues
num_falses
bitVector
comment from deserializer
COLUMN_STATS_ACCURATE {\"BASIC_STATS\":\"true\",\"COLUMN_STATS\":{\"web_city\":\"true\",\"web_class\":\"true\",\"web_close_date_sk\":\"true\",\"web_company_id\":\"true\",\"web_company_name\":\"true\",\"web_country\":\"true\",\"web_county\":\"true\",\"web_gmt_offset\":\"true\",\"web_manager\":\"true\",\"web_market_manager\":\"true\",\"web_mkt_class\":\"true\",\"web_mkt_desc\":\"true\",\"web_mkt_id\":\"true\",\"web_name\":\"true\",\"web_open_date_sk\":\"true\",\"web_rec_end_date\":\"true\",\"web_rec_start_date\":\"true\",\"web_site_id\":\"true\",\"web_site_sk\":\"true\",\"web_state\":\"true\",\"web_street_name\":\"true\",\"web_street_number\":\"true\",\"web_street_type\":\"true\",\"web_suite_number\":\"true\",\"web_tax_percentage\":\"true\",\"web_zip\":\"true\"}}
Time taken: 0.107 seconds, Fetched: 13 row(s)
一个分区字段的统计信息
DESCRIBE FORMATTED table_name field_name
可以显示一个字段的统计信息,如下所示:
DESCRIBE FORMATTED web_sales web_site_sk;
OK
col_name web_site_sk
data_type bigint
min 1
max 32
num_nulls 0
distinct_count 32
avg_col_len
max_col_len
num_trues
num_falses
bitVector
comment from deserializer
COLUMN_STATS_ACCURATE {\"BASIC_STATS\":\"true\",\"COLUMN_STATS\":{\"web_city\":\"true\",\"web_class\":\"true\",\"web_close_date_sk\":\"true\",\"web_company_id\":\"true\",\"web_company_name\":\"true\",\"web_country\":\"true\",\"web_county\":\"true\",\"web_gmt_offset\":\"true\",\"web_manager\":\"true\",\"web_market_manager\":\"true\",\"web_mkt_class\":\"true\",\"web_mkt_desc\":\"true\",\"web_mkt_id\":\"true\",\"web_name\":\"true\",\"web_open_date_sk\":\"true\",\"web_rec_end_date\":\"true\",\"web_rec_start_date\":\"true\",\"web_site_id\":\"true\",\"web_site_sk\":\"true\",\"web_state\":\"true\",\"web_street_name\":\"true\",\"web_street_number\":\"true\",\"web_street_type\":\"true\",\"web_suite_number\":\"true\",\"web_tax_percentage\":\"true\",\"web_zip\":\"true\"}}
Time taken: 0.107 seconds, Fetched: 13 row(s)
- 显示一个分区中字段的统计信息
hive> desc formatted web_sales partition(ws_sold_date_sk=2452536) ws_item_sk;
OK
col_name ws_item_sk
data_type bigint
min 49
max 35997
num_nulls 0
distinct_count 1499
avg_col_len
max_col_len
num_trues
num_falses
bitVector
comment from deserializer
统计信息的作用
查询优化
查询优化器根据统计信息,可以生成代价更低的执行计划。
查询结果
有些查询,可以从统计信息中直接获取查询的结果,不用生成作业读取文件。
配置参数如下,当为true 时,可以用统计信息的结果。
<property>
<name>hive.compute.query.using.stats</name>
<value>true</value>
<description>
When set to true Hive will answer a few queries like count(1) purely using stats
stored in metastore. For basic stats collection turn on the config hive.stats.autogather to true.
For more advanced stats collection need to run analyze table queries.
</description>
</property>
- 查询记录数
可以看到没有生成任务,直接返回结果。
hive> select count(1) from web_site;
OK
32
Time taken: 2.123 seconds, Fetched: 1 row(s)
- 查询最大值,最小值
hive> select min(ws_item_sk) from web_sales where ws_sold_date_sk=2452536;
OK
49
Time taken: 0.393 seconds, Fetched: 1 row(s)
- 查询distinct 值 会生成一个作业,这部分 Hive 还没有优化
hive> select count(distinct ws_item_sk) from web_sales where ws_sold_date_sk=2452536;
Query ID = hive_20220310161137_2da6da34-7eda-4e39-a1f5-146c19081333
Total jobs = 1
Launching Job 1 out of 1
Tez session was closed. Reopening...
Session re-established.
Session re-established.
Status: Running (Executing on YARN cluster with App id application_1646016563431_0141)
----------------------------------------------------------------------------------------------
VERTICES MODE STATUS TOTAL COMPLETED RUNNING PENDING FAILED KILLED
----------------------------------------------------------------------------------------------
Map 1 .......... container SUCCEEDED 1 1 0 0 0 0
Reducer 2 ...... container SUCCEEDED 2 2 0 0 0 0
Reducer 3 ...... container SUCCEEDED 1 1 0 0 0 0
----------------------------------------------------------------------------------------------
VERTICES: 03/03 [==========================>>] 100% ELAPSED TIME: 4.01 s
----------------------------------------------------------------------------------------------
Status: DAG finished successfully in 4.01 seconds
Query Execution Summary
----------------------------------------------------------------------------------------------
OPERATION DURATION
----------------------------------------------------------------------------------------------
Compile Query 0.23s
Prepare Plan 0.08s
Get Query Coordinator (AM) 0.00s
Submit Plan 3.65s
Start DAG 0.99s
Run DAG 4.01s
----------------------------------------------------------------------------------------------
Task Execution Summary
----------------------------------------------------------------------------------------------
VERTICES DURATION(ms) CPU_TIME(ms) GC_TIME(ms) INPUT_RECORDS OUTPUT_RECORDS
----------------------------------------------------------------------------------------------
Map 1 2031.00 4,920 68 1,526 1,497
Reducer 2 445.00 1,000 0 1,497 2
Reducer 3 0.00 280 0 2 0
----------------------------------------------------------------------------------------------
OK
1497
统计信息自动生成的配置参数
参数hive.stats.autogather
配置自动生成表和分区的统计信息。hive.stats.column.autogather
配置自动统计列的统计信息。配置之后,会多一个 Task,收集统计信息,存入 MetaStore。
<property>
<name>hive.stats.autogather</name>
<value>true</value>
<description>A flag to gather statistics (only basic) automatically during the INSERT OVERWRITE command.</description>
</property>
<property>
<name>hive.stats.column.autogather</name>
<value>true</value>
<description>A flag to gather column statistics automatically.</description>
</property>
使用命令手动生成统计信息
生成表的统计信息
以下命令用于生成表的统计信息。如果表是非分区表,则生成所有分区的统计信息。
analyze table web_sales compute statistics;
生成某个分区的统计信息
以下命令用于生成表的某些分区的统计信息。
analyze table web_sales partition(ws_sold_date_sk=2452536) compute statistics;
如果有多个分区列,如 log 表有两个分区字段(dt,hour),则以下语句生成 20220308 日所有小时分区的统计信息。
analyze table log partition(dt='20220308') compute statistics;
生成表的字段统计信息
以下命令用于生成表的所有字段统计信息。如果表是非分区表,则生成所有分区的所有字段统计信息。
analyze table web_sales compute statistics for columns;
生成表的某些字段统计信息
如果不想生成所有字段的统计信息,在后面加上需要的字段名,如下所示。
analyze table web_sales compute statistics for columns web_site_sk,ws_item_sk;
生成表的某些分区的字段统计信息
analyze table store_sales partition(ss_sold_date_sk=2452536) compute statistics for columns;
多分区字段也可以不全部指定。
生成表的某些分区,某些字段的字段统计信息
analyze table store_sales partition(ss_sold_date_sk=2452536) compute statistics for columns ss_sold_time_sk,ss_item_sk;
禁用某些表的统计信息
对于某些表的数据,不是用 hive 语句生成,而是用外部软件生成,则从统计信息中查询不正确。对于这类表,需要在创建之前设置参数 set hive.stats.autogather=false;
测试如下
创建表
创建标准表 t1,query 尽可能的利用统计信息。
set hive.stats.autogather=true;
create table t1(c1 string) stored as textfile;
查询表的存储路径和 STATS,BASIC_STATS=true
说明包含统计信息。
hive> desc formatted t1;
OK
# col_name data_type comment
c1 string
# Detailed Table Information
Database: default
OwnerType: USER
Owner: hive
CreateTime: Thu May 05 14:23:57 CST 2022
LastAccessTime: UNKNOWN
Retention: 0
Location: hdfs://bmr-cluster/warehouse/tablespace/managed/hive/t1
Table Type: MANAGED_TABLE
Table Parameters:
COLUMN_STATS_ACCURATE {\"BASIC_STATS\":\"true\",\"COLUMN_STATS\":{\"c1\":\"true\"}}
bucketing_version 2
numFiles 0
numRows 0
rawDataSize 0
totalSize 0
transient_lastDdlTime 1651731837
# Storage Information
SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
InputFormat: org.apache.hadoop.mapred.TextInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Compressed: No
Num Buckets: -1
Bucket Columns: []
Sort Columns: []
Storage Desc Params:
serialization.format 1
在创建表 t2 之前,set hive.stats.autogather=false;
。
set hive.stats.autogather=false;
create table t2(c1 string) stored as textfile;
desc 发现,t2 没有 \"BASIC_STATS\":\"true\"
的描述
hive> desc formatted t2;
OK
# col_name data_type comment
c1 string
# Detailed Table Information
Database: default
OwnerType: USER
Owner: hive
CreateTime: Thu May 05 14:25:21 CST 2022
LastAccessTime: UNKNOWN
Retention: 0
Location: hdfs://bmr-cluster/warehouse/tablespace/managed/hive/t2
Table Type: MANAGED_TABLE
Table Parameters:
bucketing_version 2
transient_lastDdlTime 1651731921
# Storage Information
SerDe Library: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe
InputFormat: org.apache.hadoop.mapred.TextInputFormat
OutputFormat: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat
Compressed: No
Num Buckets: -1
Bucket Columns: []
Sort Columns: []
Storage Desc Params:
serialization.format 1
Time taken: 0.055 seconds, Fetched: 26 row(s)
往表的所在目录直接放入文件
退出 hive,使用 shell 命令往表的所在目录直接放入文件,这是 hive 是不知道的,不会生成统计信息。
hadoop fs -put /etc/hosts hdfs://bmr-cluster/warehouse/tablespace/managed/hive/t1
hadoop fs -put /etc/hosts hdfs://bmr-cluster/warehouse/tablespace/managed/hive/t2
验证
分别从 t1 和 t2 表中查询记录数,可以看到 t1 直接返回,因为使用统计信息。t2 使用了一个作业,查询数据文件,得到记录数 6。以上示例说明
hive> select count(*) from t1;
OK
0
Time taken: 2.76 seconds, Fetched: 1 row(s)
hive> select count(*) from t2;
Query ID = hive_20220505142655_a7a965b0-fbf6-4f19-ae45-4ed49f0fac1c
Total jobs = 1
Launching Job 1 out of 1
Status: Running (Executing on YARN cluster with App id application_1651117468586_0069)
----------------------------------------------------------------------------------------------
VERTICES MODE STATUS TOTAL COMPLETED RUNNING PENDING FAILED KILLED
[=============>>-------------] 50% ELAPSED TIME: 6.10 s
Map 1 .......... container SUCCEEDED 1 1 0 0 0 0
Reducer 2 ...... container SUCCEEDED 1 1 0 0 0 0
----------------------------------------------------------------------------------------------
VERTICES: 02/02 [==========================>>] 100% ELAPSED TIME: 6.22 s
----------------------------------------------------------------------------------------------
Status: DAG finished successfully in 6.22 seconds
Query Execution Summary
----------------------------------------------------------------------------------------------
OPERATION DURATION
----------------------------------------------------------------------------------------------
Compile Query 0.31s
Prepare Plan 0.30s
Get Query Coordinator (AM) 0.02s
Submit Plan 0.36s
Start DAG 1.00s
Run DAG 6.22s
----------------------------------------------------------------------------------------------
Task Execution Summary
----------------------------------------------------------------------------------------------
VERTICES DURATION(ms) CPU_TIME(ms) GC_TIME(ms) INPUT_RECORDS OUTPUT_RECORDS
----------------------------------------------------------------------------------------------
Map 1 2527.00 3,550 69 6 1
Reducer 2 123.00 950 17 1 0
----------------------------------------------------------------------------------------------
OK
6
Time taken: 8.291 seconds, Fetched: 1 row(s)