Hadoop 如何将数据从Spark SQL导出到CSV
此命令适用于HiveQL:Hadoop 如何将数据从Spark SQL导出到CSV,hadoop,apache-spark,export-to-csv,hiveql,apache-spark-sql,Hadoop,Apache Spark,Export To Csv,Hiveql,Apache Spark Sql,此命令适用于HiveQL: insert overwrite directory '/data/home.csv' select * from testtable; 但是使用Spark SQL,我在org.apache.Spark.SQL.hive.HiveQl堆栈跟踪中遇到了一个错误: java.lang.RuntimeException: Unsupported language features in query: insert overwrite directory '/dat
insert overwrite directory '/data/home.csv' select * from testtable;
但是使用Spark SQL,我在org.apache.Spark.SQL.hive.HiveQl
堆栈跟踪中遇到了一个错误:
java.lang.RuntimeException: Unsupported language features in query:
insert overwrite directory '/data/home.csv' select * from testtable
请指导我在Spark SQL中编写导出到CSV功能。错误消息表明这不是查询语言中支持的功能。但是您可以像往常一样通过RDD接口(
df.RDD.saveAsTextFile
)以任何格式保存数据帧。或者您可以签出。您可以使用下面的语句以CSV格式写入数据帧的内容
df.write.csv(“/data/home/csv”)
如果需要将整个数据帧写入单个CSV文件,则使用
df.coalesce(1).write.csv(“/data/home/sample.csv”)
对于spark 1.x,您可以使用将结果写入CSV文件
下面的scala片段会有所帮助
import org.apache.spark.sql.hive.HiveContext
// sc - existing spark context
val sqlContext = new HiveContext(sc)
val df = sqlContext.sql("SELECT * FROM testtable")
df.write.format("com.databricks.spark.csv").save("/data/home/csv")
将内容写入单个文件
import org.apache.spark.sql.hive.HiveContext
// sc - existing spark context
val sqlContext = new HiveContext(sc)
val df = sqlContext.sql("SELECT * FROM testtable")
df.coalesce(1).write.format("com.databricks.spark.csv").save("/data/home/sample.csv")
最简单的方法是映射数据帧的RDD并使用mkString:
df.rdd.map(x=>x.mkString(","))
从Spark 1.5开始(甚至更早)
df.map(r=>r.mkString(“,”)
也会这样做
如果您想要CSV转义,可以使用ApacheCommonsLang。e、 这是我们正在使用的代码
def DfToTextFile(path: String,
df: DataFrame,
delimiter: String = ",",
csvEscape: Boolean = true,
partitions: Int = 1,
compress: Boolean = true,
header: Option[String] = None,
maxColumnLength: Option[Int] = None) = {
def trimColumnLength(c: String) = {
val col = maxColumnLength match {
case None => c
case Some(len: Int) => c.take(len)
}
if (csvEscape) StringEscapeUtils.escapeCsv(col) else col
}
def rowToString(r: Row) = {
val st = r.mkString("~-~").replaceAll("[\\p{C}|\\uFFFD]", "") //remove control characters
st.split("~-~").map(trimColumnLength).mkString(delimiter)
}
def addHeader(r: RDD[String]) = {
val rdd = for (h <- header;
if partitions == 1; //headers only supported for single partitions
tmpRdd = sc.parallelize(Array(h))) yield tmpRdd.union(r).coalesce(1)
rdd.getOrElse(r)
}
val rdd = df.map(rowToString).repartition(partitions)
val headerRdd = addHeader(rdd)
if (compress)
headerRdd.saveAsTextFile(path, classOf[GzipCodec])
else
headerRdd.saveAsTextFile(path)
}
def DfToTextFile(路径:字符串,
数据帧,
分隔符:String=“,”,
csvEscape:Boolean=true,
分区:Int=1,
compress:Boolean=true,
标题:选项[字符串]=无,
maxColumnLength:选项[Int]=无)={
def trimColumnLength(c:字符串)={
val col=maxColumnLength匹配{
案例无=>c
案例部分(len:Int)=>c.take(len)
}
if(csvEscape)StringEscapeUtils.escapeCsv(col)else col
}
def行字符串(r:行)={
val st=r.mkString(“~-~”).replaceAll(“[\\p{C}|\\uFFFD]”,“”)//删除控制字符
st.split(“~-~”).map(trimColumnLength).mkString(分隔符)
}
def addHeader(r:RDD[String])={
val rdd=for(h以上使用spark csv的答案是正确的,但存在一个问题-库基于数据帧分区创建多个文件。这不是我们通常需要的。因此,您可以将所有分区合并为一个:
df.coalesce(1).
write.
format("com.databricks.spark.csv").
option("header", "true").
save("myfile.csv")
并将lib的输出(名称为“part-00000”)重命名为所需的文件名
这篇博文提供了更多细节:因为Spark
2.X
Spark csv
集成为。因此,必要的语句简化为(windows)
或UNIX
df.write
.option("header", "true")
.csv("/var/out.csv")
注意:正如评论所说,它正在以该名称创建目录,其中包含分区,而不是分区。然而,这很可能是您想要的,因为否则您可能会导致驱动程序崩溃(内存不足),或者您可能正在使用非分布式环境。在spark csv的帮助下,我们可以写入csv文件
val dfsql = sqlContext.sql("select * from tablename")
dfsql.write.format("com.databricks.spark.csv").option("header","true").save("output.csv")`
在DATAFRAME中的此处输入代码:
val p=spark.read.format("csv").options(Map("header"->"true","delimiter"->"^")).load("filename.csv")
虽然这是最简单的答案(也是一个很好的答案),但如果您的文本中有双引号,则必须对它们进行解释。只需在为表scala>df.RDD.map(x=>x.mkString(“,”);:18:错误:值RDD不是org.apache.spark.sql.SchemaRDD df.RDD.map(x=>x.mkString(“,”)的成员);scala>df.write.format(“com.databricks.spark.csv”).save(“/data/home.csv”):18:错误:value write不是org.apache.spark.sql.SchemaRDD的成员。我是否需要再次使用databricks包构建当前jar?
DataFrame.write
是在apache spark 1.4.0中添加的。它应该是df.repartition.write而不是df.write.repartition吗?@Cedric你说得对,谢谢!首先重新分区!已编辑。还可以添加模型,如果希望继续写入现有文件。resultDF.repartition(1).write.mode(“append”).format(“com.databricks.spark.csv”).option(“header”,“true”).save(“s3:/…”)
合并(1)
需要将数据集放入一台机器的堆中,并且在处理大型数据集时很可能会导致问题datasets@DmitryPetrov当包含coalesce选项时,我们是否需要提到write.format(“com…”)选项?大家好,有没有办法替换文件,因为它在尝试重写文件时失败。当然!.mode(“overwrite”).csv(“/var/out.csv”)
在Spark 2.x中,它正在以该名称创建目录。有什么帮助吗?我猜您的分区在该目录中。但它不是标准的csv文件,它正在生成一个包含奇怪文件的文件夹(!)。请参阅,我尝试了您提到的合并方法。它在指定路径处创建一个带有部分“文件和名为”的文件\u成功"。你知道一种只获取一个文件的方法吗?不,我想没有办法。它不是本地文件,而是hdfs文件。我发现这段代码中有一个错误,与此代码生成的单个csv相比,我原来的带有分区的目录csv有一个额外的列。我知道这段代码适用于普通情况,但我的最后两列是错误的格式concat(“”,concat_ws(“,”,collect_list(某些列)),“)
在插入覆盖时效果很好,但在我选择所有列并写入此格式时效果不好,即使标题是正确的,但它错误地识别了最后第二个列值以填充这两个列,并忽略了REST。这就是我的csv部分在“USR”、0,0、“css”、“shell”、“html”、“python”、“javascript”之前的样子,“38153439601683229869156900”
这就是它们现在的样子“\'USR\”,0,0,“\'css\”,“\'shell\”
这个问题/答案并不能解决Spark 2.x的问题…真正的问题是导出到标准的CSV格式。不,它不是真正的CSV文件,结果output.CSV是一个文件夹。
val p=spark.read.format("csv").options(Map("header"->"true","delimiter"->"^")).load("filename.csv")