如何讓你的 Spark SQL 查詢加速數十倍?

gentlesie 8年前發布 | 19K 次閱讀 Spark SQL SQL

先來回答標題所提的問題,這里的答案是列存儲,下面對列存儲及在列存儲加速 Spark SQL 查詢速度進行介紹

列存儲

什么是列存儲

傳統的數據庫通常以行單位做數據存儲,而列式存儲(后文均以列存儲簡稱)以列為單位做數據存儲,如下:

優勢

列存儲相比于行存儲主要有以下幾個優勢:

  • 數據即索引,查詢是可以跳過不符合條件的數據,只讀取需要的數據,降低 IO 數據量(行存儲沒有索引查詢時造成大量 IO,建立索引和物化視圖代價較大)
  • 只讀取需要的列,進一步降低 IO 數據量,加速掃描性能(行存儲會掃描所有列)
  • 由于同一列的數據類型是一樣的,可以使用高效的壓縮編碼來節約存儲空間

當然列存儲并不是在所有場景都強于行存儲,當查詢要讀取多個列時,行存儲一次就能讀取多列,而列存儲需要讀取多次。Spark 原始支持 parquet 和 orc 兩個列存儲,下文的實踐使用 parquet

使用 Parquet 加速 Spark SQL 查詢

在我的實踐中,使用的 Spark 版本是 2.0.0,測試數據集包含1.18億條數據,44G,每條數據共有17個字段,假設字段名是 f1,f2...f17。

使用 Parquet 格式的列存儲主要帶來三個好處

大大節省存儲空間

使用行存儲占用 44G,將行存儲轉成 parquet 后僅占用 5.6G,節省了 87.2% 空間,使用 Spark 將數據轉成列存儲耗時4分鐘左右(該值與使用資源相關)

只讀取指定行

Sql: select count(distinct f1) from tbInRow/tbInParquet

行存儲耗時: 119.7s

列存儲耗時: 3.4s

加速 35 倍

跳過不符合條件數據

Sql: select count(f1) from tbInRow/tbInParquet where f1 > 10000

行存儲耗時: 102.8s

列存儲耗時: 1.3s

加速 78 倍

當然,上文也提到了,列存儲在查詢需要讀取多列時并不占優勢:

Sql: select f1, f2, f3...f17 from tbInRow/tbInParquet limit 1

行存儲耗時: 1.7s

列存儲耗時: 1.9s

列存儲帶來的加速會因為不同的數據,不同的查詢,不同的資源情況而不同,也許在你的實踐中加速效果可能不如或比我這里例子的更好,這需要我們根據列存儲的特性來善用之

參考

 

來自:http://www.jianshu.com/p/d045a14930cb

 

 本文由用戶 gentlesie 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!