我想查询我的数据库,并且只存储按一些列排序的前100万条记录,例如column1。 我尝试了两种方法
我将镶木地板文件从HDFS加载到数据框中并对其应用SQL查询,然后将完整的数据框(1000万条记录)保存为HDFS上的文本文件。
df = sqlContext.sql("SELECT * FROM table order by column1")
df.rdd.saveAsTextFile("<path>")
然后我读取文本文件并从文本文件中获取100万条记录。
我将SQL查询限制为100万条记录。
df = sqlContext.sql("SELECT * FROM table order by column1 LIMIT 1000000")
df.rdd.saveAsTextFile("<path>")
但第二种方法要慢得多。我发现在第二种情况下,SQL查询(df)返回的数据帧只包含1个分区,因此它写在一个任务中。对数据帧进行重新分区改进了第二种情况下的性能,但它仍然比第一种情况慢。
请允许任何人建议在案例2或任何其他方法中更快地保存数据帧以实现相同任务的方法
答案 0 :(得分:0)
假设column1
是数字,一种可能的解决方案是估算分布和filter
而不是排序和limit
。假设您的数据如下所示:
from pyspark.mllib.random import RandomRDDs
df = RandomRDDs.normalRDD(sc, 1000000, 10, 323).map(lambda x: (x, )).toDF(["x"])
并且您希望获得100条最佳记录:
n = 1000 # Number of records to take, lets say 1000
您可以估算出必须采取的记录比例:
q = 100 * (1 - n / float(df.count()))
估计各自的分位数:
import numpy as np
from pyspark.sql.functions import col
threshold = np.percentile(
df.sample(False, 0.05).select("x").rdd.flatMap(lambda x: x).collect(),
[q]
)[0]
result = df.where(col("x") > threshold)
result.write.format(...).save(...)
这根本不会随机播放并保持初始记录分发,但不保证确切的记录数量,并且需要对相关网络IO执行其他操作。