从Spark在Hive表上运行的ANALYZE TABLE命令不能提供与从Hive发出的同一命令相同的性能改进。
例如,我已将一个数据框插入到一个空的Hive表中:-
output.write.insertInto(“XXXXXXXX”)
,然后运行分析表命令:-
spark.sql("ANALYZE TABLE XXXXXXXX COMPUTE STATISTICS")
当我在Hive中进行记录计数时,它非常慢:-
select count(*) from XXXXXXXX;
+-----------+
| _c0 |
+-----------+
| 12345678 |
+-----------+
1 row selected (36.038 seconds)
但是,如果我直接在Hive中运行同一分析表命令,性能会提高:-
select count(*) from XXXXXXXX;
+-----------+
| _c0 |
+-----------+
| 12345678 |
+-----------+
1 row selected (0.096 seconds)
谁能解释为什么会出现这种差异? 有解决方法吗?
答案 0 :(得分:0)
这是因为火花很愚蠢。 Spark的ANALYZE TABLE命令仅以Spark兼容格式将计算出的统计信息写入Hive不知道的表属性中。编写时,Spark会完全忽略标准的Hive表统计信息。
如果您进行
show create table XXXXXXXX
在Hive中,在查询中执行spark.sql(“ ANALYZE ..”)步骤之后,您将在tbl_properties部分中看到以下内容:
TBLPROPERTIES (
'numFiles'='1',
'numRows'='-1',
'rawDataSize'='-1',
'spark.sql.statistics.numRows'='12345678',
'spark.sql.statistics.totalSize'='12345678',
'totalSize'='12345678',
仅在配置单元中执行相同的命令后,您才会获得正确的信息:
TBLPROPERTIES (
'numFiles'='1',
'numRows'='12345678',
'rawDataSize'='12345678',
'spark.sql.statistics.numRows'='12345678',
'spark.sql.statistics.totalSize'='12345678',
'totalSize'='12345678',
在计算统计信息时,Spark可以正确填充numRows和rawDataSize字段吗?大概。为什么不这样做?不知道。 :(可能是spark开发人员在上面对像Hive这样的低端系统进行了优化(即使Apache Impala之类的其他框架也可以从此处的正确统计信息中受益-因为Impala正确使用了它们)
唯一的解决方法是在执行Spark Statistics统计信息命令之后执行相应的配置单元任务,这非常丑陋。 :(