SparkSQL操作insert overwrite table到hive慢

2021-03-02 我的小樹枝

在印象中spark的速度和hive on mr模式比特別快,但實際上SparkSQL操作insert overwrite table到hive特別慢。針對此情況,說下自己收集和使用的方案:

解決方案如下:

1. 將dataframe重新分區,dataFreame.repartition(1),重新分區為1,原來是 job 花了大量的時間在寫文檔上。

來源連結:https://www.dazhuanlan.com/2019/08/21/5d5d11a2893ea/

monthDF.repartition(1).createOrReplaceTempView("tempMonth")

val insertMonthSQL =
"""
| INSERT OVERWRITE TABLE app.table_name PARTITION (dt)
| SELECT
| id,
| name,
| class,
| dt
| FROM tempMonth
""".stripMargin

sparkSession.sql(insertMonthSQL)

2. 在使用spark寫hive過程中,發現最耗時的部分是將產生的結果寫入hive,舉個例子,對3g*1G表的join來講,將結果使用以下方式直接寫入hive表需要超過半小時的時間:

dataframe.registerTempTable("result")

sql(s"""INSERT OVERWRITE Table $outputTable PARTITION (dt ='$outputDate') select * from result""")

而整個結果數據的產生只需要4分鐘左右的時間,比如以下方式:將結果以textfile存入hdfs:

result.rdd.saveAsTextFile(output_tmp_dir)

由此可見,對hive的寫入操作耗用了大量的時間。

對此現象的優化可以是,將文件存為符合hive table文件的格式,然後使用hive load將產生的結果文件直接move到指定目錄下。代碼如下:

result.rdd.map { r => r.mkString("\001") }.repartition(partitions).saveAsTextFile(output_tmp_dir)

sql(s"""load data inpath '$output_tmp_dir' overwrite into table $output partition (dt='$dt')""")

詳解:

hive column默認分隔符在scala/java中的表示為「/001」,r.mkString("/001")既是將column以分隔符/001進行分割,hive在導入時會自動識別。
repartition(partitions)是為了防止hdfs中產生大量小文件。partitions的設定與最終結果大小有關,一般是result_size/hdfs_block_size。

此處使用hive load data命令,將hdfs文件load到hive表中。後臺操作為直接將目錄下的文件移到hive table所在目錄,所以只是hdfs move數據的過程,執行非常快。

sql(s"""load data inpath '$output_tmp_dir' overwrite into table $tmp_table partition (dt='$dt')""")
sql(s"""INSERT OVERWRITE Table $outputTable PARTITION (dt ='$outputDate') select * from $tmp_table where dt='$dt'""")

在資源配置為--num-executors 20 --executor-cores 4,結果數據為1.8g的情況下,需要額外耗時50s。好處是結果數據使用列式、壓縮方式存儲,壓縮比12.7左右。
使用優化後的方式,原有test case的耗時從半小時降到4分鐘,效率提升明顯。

總結,我在實際工作中採用了第一種,因為改動成本最低,堅持先解決問題,在優化解決方案的態度。第二種,我沒有實際操作驗證,因為權限限制,且改動成本大。

相關焦點

  • Hive insert overwrite 問題
    內容目錄1 測試的版本2 insert overwrite使用說明3 示例4 建議的操作5 參考連結1 測試的版本Apache hive 1.1.0/2.3.1/3.1.02 insert overwrite 使用說明表類型使用場景hive操作邏輯非分區表insert overwrite table t select
  • insert into與insert overwrite有什麼區別?
    用法1、insert into 語句hive> insert into table user1
  • hive sql 優化心得
    下面為大家介紹一下hive的優化器以及一些常見的sql技巧。常見的優化器如果你想查看hive的優化器,可以從github上面拉一份hive的源碼,在org.apache.hadoop.hive.ql.optimizer目錄下可以看到hive裡面有哪些邏輯優化器。
  • Hadoop數據分析之Hive
    delimited fields terminated by '\t';load data local inpath '/user_bucket.txt' overwrite into table user_demo; load data local inpath '/user_bucket.txt' into table user_demo;insert into table
  • 代碼 | Spark讀取mongoDB數據寫入Hive普通表和分區表
    ;import org.apache.spark.api.java.function.Function;import org.apache.spark.sql.Dataset;import org.apache.spark.sql.Row;import org.apache.spark.sql.RowFactory;import org.apache.spark.sql.SparkSession
  • 大數據分析工程師入門9-Spark SQL
    早期Spark的切入點是SparkContext,通過它來創建和操作數據集,對於不同的API需要不同的context。比如:使用sql-需要sqlContext,使用hive-需要hiveContext,使用streaming-需要StreamingContext。
  • Hudi 新特性 Insert Overwrite API 解讀
    我們希望提供類似hive的 "insert overwrite "API,以忽略現有數據,只用提供的新數據創建一個提交。這些API也可以用於某些操作任務,如修復指定的問題分區。我們可以用源文件中的記錄對該分區進行'插入覆蓋'。對於某些數據源來說,這比還原和重放要快得多。
  • spark結構化數據處理:Spark SQL、DataFrame和Dataset
    通過SQLContext.createDataFrame()將模式信息應用到第1步創建的RDD上。import org.apache.spark.sql.Rowimport org.apache.spark.sql.types.
  • Hive SQL基本使用詳解
    Hive 查詢操作過程嚴格遵守Hadoop MapReduce 的作業執行模型,Hive 將用戶的Hive SQL 語句通過解釋器轉換為MapReduce 作業提交到Hadoop 集群上,Hadoop 監控作業執行過程,然後返回作業執行結果給用戶。Hive 並非為聯機事務處理而設計,Hive 並不提供實時的查詢和基於行級的數據更新操作。
  • Spark 2.0系列之SparkSession詳解
    這裡使用了生成器模式,只有此「spark」對象不存在時才會創建一個新對象。// Create a SparkSession.一樣使用Spark SQL的全部功能。// Now create an SQL table and issue SQL queries against it without// using the sqlContext but through the SparkSession object.// Creates a temporary view of the DataFramezipsDF.createOrReplaceTempView
  • 2小時入門SparkSQL編程
    數據表生成DataFramespark.sql("CREATE TABLE IF NOT EXISTS src (key INT, value STRING) USING hive")spark.sql("LOAD DATA LOCAL INPATH 'data/kv1.txt' INTO TABLE src")df = spark.sql("SELECT key,
  • Hive整合HBase完整筆記(親測)
    (1)測試數據文件創建測試文件course.csv第一列為課程名稱,第二列為課程分數(2)數據加載到HDFS在hdfs文件系統中創建hive-hbase目錄,並加載測試數據。查看hdfs文件目錄create external table if notexists course.testcourse(cname string,score int) row format delimited fieldsterminated by '\t' stored as textfile location '/hive-hbase/course';
  • Spark SQL重點知識總結
    3、Hive的繼承,Spark SQL通過內嵌的hive或者連接外部已經部署好的hive案例,實現了對hive語法的繼承和操作。2、需要將core-site.xml和hdfs-site.xml 拷貝到spark的conf目錄下。如果Spark路徑下發現metastore_db,需要刪除【僅第一次啟動的時候】。
  • Hive數據倉庫實戰
    語句的結果集合導出到另外一張表,用insert overwrite table這是更新數據表的常用方式,通過insert overwrite table可以把指定的查詢結果集合插入到這個表,插入前先把表清空。
  • 訪問Hive數據的幾種騷姿勢
    hiveserver2:hive服務端。提供hive服務。客戶端可以通過beeline,jdbc(即用java代碼連結)等多種方式連結到hive。beeline:hive客戶端連結到hive的一個工具。可以理解成mysql的客戶端。如:navite cat 等。hive-cli是一個遺留工具,它有兩個主要的使用場景。
  • 數據分析工具篇——HQL的DML操作
    說明:1.1)Load 操作只是單純的複製/移動操作,將數據文件移動到 Hive 表對應的位置。account_tmp;2.2)覆蓋數據:覆蓋原有的內容;insert overwrite table account1 select * from account_tmp;2.3)多插入模式:
  • 手把手教你在 Windows 平臺搭建本地 Hive 訪問環境
    如果有一種方法讓數據分析師能夠在不搭建linux集群的情況下就能把spark,hive在本地跑起來直接使用,那或許會非常方便。我為了讓需要使用大數據組件的朋友很方便的在本地使用hive和spark,已經多次測試了從零到1在windows平臺下搭建hadoop、hive和spark,並且直接跑起來。
  • 問題排查 | Spark OrcFileFormat inferSchema執行巨慢問題分析
    (這一點也通過遠程debug的方式得到了驗證)2.3 從日誌判斷慢的地方利用jstack命令,查看二次開發功能執行到哪裡了?<init>(ReaderImpl.java:316) at org.apache.hadoop.hive.ql.io.orc.OrcFile.createReader(OrcFile.java:187) at org.apache.spark.sql.hive.orc.OrcFileOperator$$anonfun$getFileReader$2.apply(OrcFileOperator.scala
  • HiveSQL優化方法與實踐(推薦收藏)
    很多聚合操作可以現在map端進行,最後在Reduce端完成結果輸出:Set hive.map.aggr = true;# 是否在Map端進行聚合,默認為true;Set hive.groupby.mapaggr.checkinterval = 1000000;# 在Map端進行聚合操作的條目數目;當使用Group