簡體   English   中英

用sqlcontext觸發並行查詢

[英]parallel query to spark with sqlcontext

我們正在嘗試在EMR中運行ETL。 S3中有大約2000億個事件,即gzip json行。 它們總共約有30個文件。 我正在使用pyspark。

這是代碼,

def value_to_list(columns):
    def value_map(values):
        data = []
        for val in values:
            d = val.asDict()
            data.append([d[column] for column in columns])
        return data

    return value_map


def main():
    sc = SparkContext()
    sql_context = SQLContenxt(sc)

    all_events = SQLContenxt(sc).read.json("s3n://...", schema=StructType(fields), timestampFormat="yyyy-MM-dd HH:mm:ss")
    all_events.registerTempTable('allevents')

    for event_type in event_types:
        process_event(sc, event_type, "allevents")


def process_event(sparkcontext, etype, tablename):
    query = "select app_id, source, type, {time_cols}, count(*) as total " \
            "from {table} where  type = '{event_type}' " \
            "group by app_id, source, type, {time_cols}"
    time_cols_spec = [('hour', 'day', 'month', 'year'),
                      ('day', 'month', 'year'),
                      ('month', 'year'),
                      ('year')]

    for time_cols in time_cols_spec:
        final_query = query.format(time_cols=", ".join(time_cols),
                                   table=tablename,
                                   event_type=etype)
        dataframe = sql_context.sql(final_query)

        dataframe.rdd.groupBy(lambda r: r['app_id'])\
            .mapValues(value_to_list(['source'] + time_cols))\
            .saveAsTextFile("s3n://...")

因此,我們大約有30種類型的事件,對於每個事件,我將按小時,日,月和年的4種組合進行匯總。 因此,每個查詢4個。 我們總共有大約2000M個事件。

我正在繼續運行

  • AWS EMR(5.0.3)
  • Apache Spark 2.0.1
  • 1個主人,2個工人
  • 每台機器是m3.2xlarge
  • 總內存為90GB

問題是,最后的保存要花很長時間。 上次我查詢時花了14個小時進行了2次組合和一個事件:(

我知道我不會並行進行。 循環是順序的。 並且有2個循環。 但是我希望rdd,groupBymapValues能夠並行運行。 當我看到事件時間軸時,我看到它的saveAsTextFile占用了99%的時間。 可能是因為火花延遲執行。

我需要使此過程並行且快速。 我怎樣才能做到這一點?

您可以應用4種主要的優化方法:

  1. 您正在對未針對查詢進行優化的純json文件執行聚合。 將它們重寫為鑲木地板,按事件類型重新分區並存儲在S3上-它們將占用更少的空間,並且您的應用程序將獲得不錯的速度提升。

  2. 增加並行度。 在這種功能強大的VM上不需要驅動程序(主機),而是生成一個較小的實例(例如m3.medium ),並使用所有3個大型實例供工作者使用。

  3. 用Dataframe替換RDD API調用: .rdd.groupBy().mapValues()可以替換為.groupBy(dataframe.app_id).agg(collect_list())然后進行一些映射。

  4. 您可以對(小時,日,月,年)數據集的原始數據執行查詢,然后使用此聚合對給定事件進行所有剩余查詢的查詢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM