有两种方法,要么从metastore中获取统计信息,这需要事先运行ANALYZE
(扫描数据),要么使用InMemoryFileIndex
来估算统计信息(实际上只有SizeInBytes),不需要扫描数据,但使用Hadoop api Spark会收集每个文件的大小。
将使用哪种方法取决于更多设置。例如,如果SizeInBytes
在metastore中可用,并且通过配置设置启用了CBO(基于成本的优化)
spark.cbo.enabled
,Spark将从元存储中获取它。如果CBO关闭(Spark 2.4中的默认值),Spark将使用InMemoryFileIndex
。如果metastore中没有SizeInBytes
,Spark仍然可以使用CatalogFileIndex
或InMemoryFileIndex
。例如,如果您的表已分区,将使用CatalogFileIndex
,更具体地说,如果满足此条件(直接从Spark源代码获取):
val useCatalogFileIndex = sparkSession.sqlContext.conf.manageFilesourcePartitions && catalogTable.isDefined && catalogTable.get.tracksPartitionsInCatalog && catalogTable.get.partitionColumnNames.nonEmpty
在这种情况下,如果统计信息不在metastore中,Spark将通过配置设置使用defaultSizeInBytes
:
spark.sql.defaultSizeInBytes
,默认情况下为Long.MaxValue
,因此大小将被高估到最大值。我猜这是最糟糕的情况,统计信息不在metastore中,但是Spark正在使用CatalogFileIndex在那里寻找它们,找不到它,因此使用了非常大的不切实际的值。
本文链接:https://www.f2er.com/3148324.html