spark写大表慢
通过sparksql往一个42万个分区的大表写入数据,报超时,报错信息如下所示:
MetaStoreClient lost connection. Attempting to reconnect(1 of 3) after 1s.
org.apache.thrift.transport.TTransportException: java.net.SocketTimeoutException: Read timed out
从spark-sql提交sql,到Executor真正开始执行,中间间隔了18分钟,也就是说基本是任务执行之前的耗时。
根据sparksql任务提交过程以及上述堆栈信息,我们找到了对应的超时点,就是在HiveClient.getPartitons。
根本原因是:HiveMetastore在getPartitons处理上,会先获取所有的partition name列表,然后遍历每个分区,生成对应的org.apache.hadoop.hive.metastore.api.Partition实例,这个Partition实例会涉及一些其他信息需要从mysql中获取。如果分区数多,那么getPartitons就会很慢。
进一步发现,impala中调用的是getPartitionsByNames获取Hive分区信息,大概是2分钟左右,而spark中使用的getPartitions则需要18分钟,8倍的差距。
所以解决方案也是通过getPartitionsByNames替代getPartitions方法。