你今天高效率了嗎 ? 高效思考 聰明使用 SAS – SAS Sort Information

前言

以 SAS 排序資料我們會想到 SORT procedure 或者 SQL procedureORDER BY,但是很少人會想到如果是「排序過的資料」又該如何處理。以下介紹 SAS 隱藏的技巧,對大量數據排序極為有用的 Sort Information


什麼是排序資訊 (Sort Information) ?

SAS 在以 Sort procedure 或 SQL procedure with ORDER BY 執行排序之後,會生成排序資訊 (Sort Information),這個資訊告訴我們資料的排序依據 (Sortedby) 以及排序是否已驗證 (Validated)

這個隱藏資訊可利用 Contents procedure 呼叫出來,例如:

proc sort data=sashelp.cars out=cars;
by Make EngineSize;
run;

proc contents data=cars; run;

image-20200627180606151

說明:
1. proc sort → 排序
2. proc contents → 請 SAS 提供排序資訊 (Sort Information)

↑↑↑ 由 Contents procedure 的結果可知,排序依據是汽車製造商 (Make) 及排氣量 (EngineSize) 排序,且由 SAS 所驗證。


為何需要排序資訊 ?

SAS 在排序資料時,可粗略分為三個步驟:

  1. 讀取資料
  2. 產生中繼檔案 (暫存資料) 以排序資料
  3. 輸出排序好的資料

這裡注意到 SAS 需額外的空間來暫存資料,以經驗法則來說,排序一個資料大約需要原本資料大小的四倍空間,因此我們常說排序快慢與系統的硬碟空間、記憶體大小有密切關係。然而,當資料量很大時,如何減少排序所需要耗費的資源就很重要,尤其是避免不必要的排序,例如一組數據已經排序過了。


排序資訊如何幫助我們提高效率 ?

對 SAS 來說,任何「需要排序資料才可以執行」的程序,SAS 都會檢查排序資訊。經由排序資訊所提供的資訊,確認某個變項確實已排序,SAS 就會跳過排序的步驟,大幅節省系統資源 (CUP time 及 I/O)、提高工作效率。

我們以虛擬資料,比較三種常見的情況,實際測試看看排序資訊如何發揮高效率。

假如今天有一億筆的門診資料,在外部或 input data 時已排序過 (然而 SAS 並不知道),以 id 為合併鍵值時:

狀況一:不使用 Sort (SAS 認為資料未排序)

data outpatient;
do id=1 to 100000000;
output;
end;
run;

proc sql;
create table nosort as
select a.*
from outpatient a, outpatient b
where a.id=b.id;
quit;

NOTE: 已建立表格 WORK.NOSORT,該表格包含 100000000 列和 1 欄。
NOTE: 已使用 SQL Statement (總處理時間):
實際時間 54.14 秒
CPU 時間 53:25 秒

proc contents data=outpatient; run;

image-20200627230801072

↑↑↑在沒有使用排序的情況下,儘管資料本身已排序過,對 SAS 來說資料仍然是末排序的。因此已排序的部分顯示為「NO」。

已排序 → NO
已驗證 → NO

以 SQL procedure 執行合併耗時: 54.14 秒

狀況二:使用 SORTEDBY= option (告訴 SAS 資料已排序)

data outpatient2 (sortedby= id);
do id=1 to 100000000;
output;
end;
run;

proc sql;
create table sortedby as
select a.*
from outpatient a, outpatient b
where a.id=b.id;
quit;

NOTE: 已建立表格 WORK.SORTEDBY,該表格包含 100000000 列和 1 欄。NOTE: 已使用 SQL Statement (總處理時間):
實際時間 34.89 秒
CPU 時間 33.51 秒

proc contents data=outpatient2; run;

image-20200627221013582

說明:
sortedby=id → 在建立資料或匯入資料時,告訴 SAS 變項 ID 已經排序過了

↑↑↑Contents 程序顯示資料已排序,且排序的依據為 id。這裡要注意的是,雖然經由 SORTEDBY= option,已排序的資訊由「NO」轉為「YES」,然而已驗證的部分仍然為「NO」,這是因為 SAS 尚未確認資料是否真的已排序。

已排序 → YES
已驗證 → NO

以 SQL procedure 執行合併耗時: 34.89 秒

狀況三:使用 SORTEDBY= option & PRESORTED option (告訴 SAS 資料已排序、已驗證)

data outpatient3 (sortedby= id);
do id=1 to 100000000;
output;
end;
run;

proc sort data=outpatient3 presorted out=outpatient3;
by id;
run;

proc sql;
create table sortedby as
select a.*
from outpatient3 a, outpatient3 b
where a.id=b.id;
quit;

NOTE: 已建立表格 WORK.SORTEDBY,該表格包含 100000000 列和 1 欄。NOTE: 已使用 SQL Statement (總處理時間):
實際時間 29.36 秒
CPU 時間 29.17 秒

proc contents data=outpatient3; run;

image-20200627221740888
image-20200627221759095

說明:
1. sortedby=id → 在建立資料或匯入資料時,告訴 SAS 變項 ID 已經排序過了
2. presorted → 告訴 SAS 變項 id 是排序過的資料且已驗證 (此 option 會抑制 Sort procedure 排序)

為了讓 SAS 知道資料已排序,且驗證資料已排序,可以利用 SORTEDBY= option 加上 PRESORTED option。如此一來,SAS 便不需再執行檢查資料是否真的排序過 (已驗證為 YES),可再節省執行程序的時間。

已排序 → YES
已驗證 → NO
以 SQL procedure 執行合併耗時: 29.36 秒


要點總結

  1. 任何需要執行排序的 SAS 程序都需要檢查排序資訊 (Sort Information)
  2. 如果可以確定某個變項事已事先排序過,在匯入資料時可利用 SORTEDBY option 告訴 SAS 資料已經排序過 (已排序由 NO 轉為 YES),即可跳過排序
  3. 加強 SAS 的效率,可結合 Sort procedure 的 PRESORTED option,告訴 SAS 資料確實已排序過,不需要再驗證

延伸閱讀

SAS 9.4 Language Reference: Sorted Data Sets, Sixth Edition
https://amadeus.co.uk/tips/using-the-presorted-option-with-proc-sort-in-sas-92/

2 Replies to “你今天高效率了嗎 ? 高效思考 聰明使用 SAS – SAS Sort Information”

如有任何問題和意見歡迎提出