一次PLSQL處理LOB欄位的優化
前面一篇文章介紹了利用LOB來避免字串超長的問題。在編寫過程中,碰到了LOB處理效率比較低的問題,這裡簡單介紹了一下優化LOB處理的過程。
字串連線超長的解決(二):http://yangtingkun.itpub.net/post/468/482122
問題源自上面給出的連結。為了實現字串的聚集合並,因此用LOB來避免字串長度超過VARCHAR2型別長度的限制。
第一次PL/SQL程式碼的實現為:
SQL> CREATE OR REPLACE TYPE T_LINK_LOB AS OBJECT (
2 V_LOB CLOB,
3 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT T_LINK_LOB) RETURN NUMBER,
4 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT T_LINK_LOB, VALUE IN VARCHAR2) RETURN NUMBER,
5 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN T_LINK_LOB, RETURNVALUE OUT CLOB, FLAGS IN NUMBER) RETURN NUMBER,
6 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT T_LINK_LOB, CTX2 IN T_LINK_LOB) RETURN NUMBER
7 )
8 /
型別已建立。
SQL> CREATE OR REPLACE TYPE BODY T_LINK_LOB IS
2 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT T_LINK_LOB) RETURN NUMBER IS
3 BEGIN
4 SCTX := T_LINK_LOB(NULL);
5 DBMS_LOB.CREATETEMPORARY(SCTX.V_LOB, TRUE, DBMS_LOB.SESSION);
6 DBMS_LOB.OPEN(SCTX.V_LOB, DBMS_LOB.LOB_READWRITE);
7 RETURN ODCICONST.SUCCESS;
8 END;
9
10 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT T_LINK_LOB, VALUE IN VARCHAR2) RETURN NUMBER IS
11 BEGIN
12 DBMS_LOB.WRITEAPPEND(SELF.V_LOB, LENGTH(VALUE) + 1, VALUE || ',');
13 RETURN ODCICONST.SUCCESS;
14 END;
15
16 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN T_LINK_LOB, RETURNVALUE OUT CLOB, FLAGS IN NUMBER) RETURN NUMBER IS
17 BEGIN
18 DBMS_LOB.CREATETEMPORARY(RETURNVALUE, TRUE, DBMS_LOB.CALL);
19 DBMS_LOB.APPEND(RETURNVALUE, SELF.V_LOB);
20 DBMS_LOB.TRIM(RETURNVALUE, DBMS_LOB.GETLENGTH(RETURNVALUE) - 1);
21 RETURN ODCICONST.SUCCESS;
22 END;
23
24 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT T_LINK_LOB, CTX2 IN T_LINK_LOB) RETURN NUMBER IS
25 BEGIN
26 NULL;
27 RETURN ODCICONST.SUCCESS;
28 END;
29 END;
30 /
型別主體已建立。
SQL> CREATE OR REPLACE FUNCTION F_LINK_LOB(P_STR VARCHAR2) RETURN CLOB
2 AGGREGATE USING T_LINK_LOB;
3 /
函式已建立。
這時呼叫這個聚集函式的效率比較低:
SQL> SET TIMING ON
SQL> SET AUTOT TRACE STAT
SQL> SELECT F_LINK_LOB(SYNONYM_NAME) FROM ALL_SYNONYMS WHERE ROWNUM <= 10000;
已用時間: 00: 00: 39.67
Statistics
----------------------------------------------------------
153 recursive calls
3125947 db block gets
211709 consistent gets
43 physical reads
0 redo size
1990553 bytes sent via SQL*Net to client
1166302 bytes received via SQL*Net from client
6443 SQL*Net roundtrips to/from client
9 sorts (memory)
0 sorts (disk)
1 rows processed
檢查了一下DBMS_LOB包,發現用COPY命令可以替換APPEND和TRIM過程,這樣可以減少一次LOB物件的讀寫:
SQL> CONN TEST/TEST
已連線。
SQL> SET TIMING OFF
SQL> CREATE OR REPLACE TYPE BODY T_LINK_LOB IS
2 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT T_LINK_LOB) RETURN NUMBER IS
3 BEGIN
4 SCTX := T_LINK_LOB(NULL);
5 DBMS_LOB.CREATETEMPORARY(SCTX.V_LOB, TRUE, DBMS_LOB.SESSION);
6 DBMS_LOB.OPEN(SCTX.V_LOB, DBMS_LOB.LOB_READWRITE);
7 RETURN ODCICONST.SUCCESS;
8 END;
9
10 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT T_LINK_LOB, VALUE IN VARCHAR2) RETURN NUMBER IS
11 BEGIN
12 DBMS_LOB.WRITEAPPEND(SELF.V_LOB, LENGTH(VALUE) + 1, VALUE || ',');
13 RETURN ODCICONST.SUCCESS;
14 END;
15
16 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN T_LINK_LOB, RETURNVALUE OUT CLOB, FLAGS IN NUMBER) RETURN NUMBER IS
17 BEGIN
18 DBMS_LOB.CREATETEMPORARY(RETURNVALUE, TRUE, DBMS_LOB.CALL);
19 DBMS_LOB.COPY(RETURNVALUE, SELF.V_LOB, DBMS_LOB.GETLENGTH(SELF.V_LOB) - 1);
20 RETURN ODCICONST.SUCCESS;
21 END;
22
23 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT T_LINK_LOB, CTX2 IN T_LINK_LOB) RETURN NUMBER IS
24 BEGIN
25 NULL;
26 RETURN ODCICONST.SUCCESS;
27 END;
28 END;
29 /
型別主體已建立。
SQL> CREATE OR REPLACE FUNCTION F_LINK_LOB(P_STR VARCHAR2) RETURN CLOB
2 AGGREGATE USING T_LINK_LOB;
3 /
函式已建立。
SQL> SET TIMING ON
SQL> SET AUTOT TRACE STAT
SQL> SELECT F_LINK_LOB(SYNONYM_NAME) FROM ALL_SYNONYMS WHERE ROWNUM <= 10000;
已用時間: 00: 00: 39.46
Statistics
----------------------------------------------------------
7 recursive calls
3125933 db block gets
211660 consistent gets
0 physical reads
0 redo size
1990553 bytes sent via SQL*Net to client
1166302 bytes received via SQL*Net from client
6443 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
雖然邏輯讀和執行時間都有所減少,但是與總執行時間相比優化效果可以忽略,再次觀察PL/SQL,發現預設情況下沒有使用NOCOPY方式處理輸出引數,再次修改程式:
SQL> CONN TEST/TEST
已連線。
SQL> SET TIMING OFF
SQL> CREATE OR REPLACE TYPE T_LINK_LOB AS OBJECT (
2 V_LOB CLOB,
3 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT NOCOPY T_LINK_LOB) RETURN NUMBER,
4 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT NOCOPY T_LINK_LOB, VALUE IN VARCHAR2) RETURN NUMBER,
5 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN T_LINK_LOB, RETURNVALUE OUT NOCOPY CLOB, FLAGS IN NUMBER) RETURN NUMBER,
6 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT NOCOPY T_LINK_LOB, CTX2 IN T_LINK_LOB) RETURN NUMBER
7 )
8 /
型別已建立。
SQL> CREATE OR REPLACE TYPE BODY T_LINK_LOB IS
2 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT NOCOPY T_LINK_LOB) RETURN NUMBER IS
3 BEGIN
4 SCTX := T_LINK_LOB(NULL);
5 DBMS_LOB.CREATETEMPORARY(SCTX.V_LOB, TRUE, DBMS_LOB.SESSION);
6 DBMS_LOB.OPEN(SCTX.V_LOB, DBMS_LOB.LOB_READWRITE);
7 RETURN ODCICONST.SUCCESS;
8 END;
9
10 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT NOCOPY T_LINK_LOB, VALUE IN VARCHAR2) RETURN NUMBER IS
11 BEGIN
12 DBMS_LOB.WRITEAPPEND(SELF.V_LOB, LENGTH(VALUE) + 1, VALUE || ',');
13 RETURN ODCICONST.SUCCESS;
14 END;
15
16 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN T_LINK_LOB, RETURNVALUE OUT NOCOPY CLOB, FLAGS IN NUMBER) RETURN NUMBER IS
17 BEGIN
18 DBMS_LOB.CREATETEMPORARY(RETURNVALUE, TRUE, DBMS_LOB.CALL);
19 DBMS_LOB.COPY(RETURNVALUE, SELF.V_LOB, DBMS_LOB.GETLENGTH(SELF.V_LOB) - 1);
20 RETURN ODCICONST.SUCCESS;
21 END;
22
23 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT NOCOPY T_LINK_LOB, CTX2 IN T_LINK_LOB) RETURN NUMBER IS
24 BEGIN
25 NULL;
26 RETURN ODCICONST.SUCCESS;
27 END;
28 END;
29 /
型別主體已建立。
SQL> CREATE OR REPLACE FUNCTION F_LINK_LOB(P_STR VARCHAR2) RETURN CLOB
2 AGGREGATE USING T_LINK_LOB;
3 /
函式已建立。
SQL> SET TIMING ON
SQL> SET AUTOT TRACE STAT
SQL> SELECT F_LINK_LOB(SYNONYM_NAME) FROM ALL_SYNONYMS WHERE ROWNUM <= 10000;
已用時間: 00: 00: 35.14
Statistics
----------------------------------------------------------
7 recursive calls
3125933 db block gets
211720 consistent gets
0 physical reads
0 redo size
1990553 bytes sent via SQL*Net to client
1166302 bytes received via SQL*Net from client
6443 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
新增了NOCOPY後,執行時間提高了1/8。可以看到對於LOB欄位的處理方式對效能的影響還是很大的,如果在建立臨時LOB物件的時候不指定CACHE選項,可以看到執行時間要比CACHE的速度慢一倍以上:
SQL> CREATE OR REPLACE TYPE BODY T_LINK_LOB IS
2 STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT NOCOPY T_LINK_LOB) RETURN NUMBER IS
3 BEGIN
4 SCTX := T_LINK_LOB(NULL);
5 DBMS_LOB.CREATETEMPORARY(SCTX.V_LOB, FALSE, DBMS_LOB.CALL);
6 DBMS_LOB.OPEN(SCTX.V_LOB, DBMS_LOB.LOB_READWRITE);
7 RETURN ODCICONST.SUCCESS;
8 END;
9
10 MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT NOCOPY T_LINK_LOB, VALUE IN VARCHAR2) RETURN NUMBER IS
11 BEGIN
12 DBMS_LOB.WRITEAPPEND(SELF.V_LOB, LENGTH(VALUE) + 1, VALUE || ',');
13 RETURN ODCICONST.SUCCESS;
14 END;
15
16 MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN T_LINK_LOB, RETURNVALUE OUT NOCOPY CLOB, FLAGS IN NUMBER) RETURN NUMBER IS
17 BEGIN
18 DBMS_LOB.CREATETEMPORARY(RETURNVALUE, FALSE, DBMS_LOB.SESSION);
19 DBMS_LOB.COPY(RETURNVALUE, SELF.V_LOB, DBMS_LOB.GETLENGTH(SELF.V_LOB) - 1);
20 RETURN ODCICONST.SUCCESS;
21 END;
22
23 MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT NOCOPY T_LINK_LOB, CTX2 IN T_LINK_LOB) RETURN NUMBER IS
24 BEGIN
25 NULL;
26 RETURN ODCICONST.SUCCESS;
27 END;
28 END;
29 /
型別主體已建立。
已用時間: 00: 00: 00.07
SQL> CONN TEST/TEST
已連線。
SQL> SET AUTOT TRACE STAT
SQL> SELECT F_LINK_LOB(SYNONYM_NAME) FROM ALL_SYNONYMS WHERE ROWNUM <= 10000;
已用時間: 00: 01: 33.90
Statistics
----------------------------------------------------------
6 recursive calls
2960983 db block gets
211636 consistent gets
181384 physical reads
0 redo size
1990553 bytes sent via SQL*Net to client
1166302 bytes received via SQL*Net from client
6443 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4227/viewspace-588757/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- [20181020]lob欄位的索引段.txt索引
- ORACLE LOB大欄位維護Oracle
- [20210208]lob欄位與查詢的問題.txt
- [20181022]lob欄位的lobid來之那裡.txt
- 使用plsql 匯出欄位為json 格式SQLJSON
- [20181031]lob欄位與布隆過濾.txt
- sql 統計多個欄位的和(如果欄位中含有 null 的處理)SQLNull
- springboot~mybatis統一處理公有欄位Spring BootMyBatis
- 資料處理之欄位合併
- [重慶思莊每日技術分享]-重建LOB欄位上的IndexIndex
- 如果新增欄位是外來鍵,如何處理?
- 多型關聯自定義的型別欄位的處理多型型別
- Go 中時間型別欄位的 JSON 序列化和反序列化的處理技巧Go型別JSON
- MybatisPlus經典示例:使用Wrapper查詢指定欄位並新增欄位函式處理MyBatisAPP函式
- Mysql多欄位大表的幾種優化方法MySql優化
- 【ORA-01555】Oracle LOB欄位匯出 報錯 ORA-01555Oracle
- PLSQL Developer 提示欄位名,回車後卡頓解決SQLDeveloper
- MySql之json_extract函式處理json欄位MySqlJSON函式
- 實戰SpringCloud通用請求欄位攔截處理SpringGCCloud
- 使用 Eloquent ORM 使用 with 模型關聯查詢,如何處理select不同模型的欄位(欄位名可能相同)ORM模型
- 資料庫效能優化之冗餘欄位的作用資料庫優化
- Oracle資料庫高水位釋放——LOB欄位空間釋放Oracle資料庫
- Mysql優化系列之——優化器對子查詢的處理MySql優化
- 如何處理 Web 圖片優化?Web優化
- 前端優化之高併發處理前端優化
- 百億級資料處理優化優化
- 表單請求 統一欄位不同場景不同處理
- LOB欄位相關概念(自動建立LOB索引段和重建索引方法)索引
- SQLServer索引優化(1):對於有order by欄位的建索引策略SQLServer索引優化
- 關聯模型欄位取別名查詢不出資料的處理方法模型
- Spark儲存Parquet資料到Hive,對map、array、struct欄位型別的處理SparkHiveStruct型別
- java欄位格式化Java
- [Elasticsearch] 多欄位搜尋 (二) - 最佳欄位查詢及其調優(轉)Elasticsearch
- Windows10系統優化(批處理)Windows優化
- Oracle資料庫出現ORA-19566 LOB壞塊的處理記錄Oracle資料庫
- ORACLE 資料匯出LOB欄位報錯ORA-31693,ORA-02354,ORA-22924Oracle
- hibernate跨資料庫,json欄位處理方案,自定義擴充套件JsonStringType資料庫JSON套件
- json轉化保留null欄位JSONNull
- 【CHECKPOINT】Oracle檢查點優化與故障處理Oracle優化