記一次sparksql讀取oracle數據優化過程

問題描述

Sparksql提供外接關係型數據庫的接口如下,
def jdbc(
   		url: String,
    	table: String,
   	 	columnName: String,
   	 	lowerBound: Long,
   	 	upperBound: Long,
   		numPartitions: Int,
   		connectionProperties: Properties): DataFrame 

從上述接口可知,columnName列必須是整形類型,在現實使用場景中,並不一定總是存在整形列,且表中的整形列值如果不是分佈均勻的話,很容易就會出現數據傾斜現象。
如果不使用上述接口,而是使用如下

def jdbc(url: String, table: String, properties: Properties): DataFrame

便存在性能問題,即僅有一個task去讀取oracle中的數據

解決方法

Oracle存在兩個僞列:rownum、rowid。僞劣,即表中不存在的列。Rownum是邏輯存在的、整形列,且是自增的。Rowid是物理存在的,其值是一串隨機數,表徵該記錄的位置。
Rownum在select語句中,會對查詢結果集進行編號,利用這個特點,我們可以利用sparksql jdbc接口去實現分佈式多任務去讀取oracle數據,具體思路如下:

  1. select max(rownum) ,min(rownum) from 表名1,查找最大序列號、最小序列號。
  2. 預定義一個task處理多少條記錄,然後對上述的max、min區間進行等值劃分,得出並行度,即上述接口中的numPartitions變量值。
  3. dataFrame = sqlContext.read.jdbc(url, select 表名1.*, rownum from 表名1, rownum, minValue, maxValue, numPartitions, prop)
  4. 丟棄“邏輯列”drop(rownum)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章