一條insert語句導致的效能問題分析(二)
今天對之前描述的問題一條insert語句導致的效能問題分析(一) 進行了進一步的補充。
有一條insert語句的主要效能瓶頸在於insert子句中的查詢語句,查詢中的主要資源消耗在於對兩個表進行了多次關聯
語句主要的結構如下:
insert into xxxxx (select * from TEST_vip_new minus select * from TEST_vip_new_bak
) a left join TEST_vip_new_bak b
on a.cn=b.cn
對於這個test_vip_new和test_vip_new_bak我產生了疑問,覺得這個臨時表test_vip_new_bak有些多餘。帶著這種思路分析,看起來邏輯很簡單啊,於是就聯絡了開發的同學,一起討論一番。
但是討論完之後,還是讓我有些不知所措。
首先,語句為什麼要多次關聯,自己做了一個小的測試,感覺這種關聯方式還是有些多餘。
SQL> create table a (id number);
Table created.
SQL> create table b (id number);
Table created.
SQL> insert into a values(1);
1 row created.
SQL> insert into a values(2);
1 row created.
SQL> insert into b values(1);
1 row created.
SQL> select * from a minus select * from b;
ID
----------
2
SQL> select *from a left join b on a.id=b.id;
ID ID
---------- ----------
1 1
2
如果按照這樣的思路,仿照原來的結構輸出就是下面這樣的結果。
SQL> select *from (select * from a minus select * from b) a left join b on a.id=b.id;
ID ID
---------- ----------
2
但是和開發討論了一番,發現我的想法有些簡單了,具體的場景中資料過濾的邏輯比上面這種略微複雜一些。
透過一個兩個測試表來模擬。
create table a (id1 number,id2 number);create table game_new (id1 number,id2 number);
create table game_new_bak (id1 number,id2 number);
如果原來的資料內容為(1,1),在執行儲存過程之後,會修改為(1,2)
SQL> insert into game_new values(1,2);
1 row created.
然後儲存過程在執行過程中,會插入一些新的資料,假設為(2,2)
SQL> insert into game_new values(2,2);
1 row created.
而臨時表game_new_bak中的資料是儲存過程執行之前的資料狀態,即(1,1)
SQL> insert into game_new_bak values(1,1);
1 row created.
按照這種情況,兩個表做了minus操作之後會輸出兩行,即修改之後的資料和新增的資料。
而這個需求需要實現的是,根據id1進行匹配,把修改前的id2一併輸出。這樣就知道修改前是什麼樣的資料了,如果是新增的,那這列的值就保持為空。
SQL> select a.id1,a.id2,b.id2 from (select * from game_new minus select *from game_new_bak) a left join game_new_bak b on a.id1=b.id1
ID1 ID2 ID2
---------- ---------- ----------
1 2 1
2 2
如果是這樣的情況,就完全可以使用一次表關聯就可以改進。可以用下面的形式。
select a.id1,a.id2,b.id2 from game_new a ,game_new_bak b where a.id1=b.id1(+)
所以就建議語句從原來的形式
SELECT A.CN,A.GRADE,A.RANK,A.SCORE,DECODE(SIGN
(A.RANK-(NVL(B.RANK,-1))),1,2,-1,3,0,1),
SYSDATE,(NVL(B.RANK,-1)),B.SIGN,B.FLAG,B.TAG,B.SCORE FROM ( SELECT *
FROM GAME_VIP_NEW MINUS SELECT * FROM GAME_VIP_NEW_BAK ) A LEFT JOIN
GAME_VIP_NEW_BAK B ON A.CN=B.CN
修改為:
SELECT /*+parallel(4)*/ A.CN,A.GRADE,A.RANK,A.SCORE,DECODE(SIGN
(A.RANK-(NVL(B.RANK,-1))),1,2,-1,3,0,1),
SYSDATE,(NVL(B.RANK,-1)),B.SIGN,B.FLAG,B.TAG,B.SCORE FROM GAME_VIP_NEW a,cydba.GAME_VIP_NEW_BAK B
where A.CN=B.CN(+)
考慮到執行的情況和資源情況,加了一個並行,可以在一定程度上緩解這個問題。
在本地的環境中進行了測試,發現幾分鐘就可以輕鬆搞定,做了基本的確認,就和開發進行了反饋,對線上的儲存過程內容進行了修改。
這個問題的解決也就終於告一段落。
有一條insert語句的主要效能瓶頸在於insert子句中的查詢語句,查詢中的主要資源消耗在於對兩個表進行了多次關聯
語句主要的結構如下:
insert into xxxxx (select * from TEST_vip_new minus select * from TEST_vip_new_bak
) a left join TEST_vip_new_bak b
on a.cn=b.cn
對於這個test_vip_new和test_vip_new_bak我產生了疑問,覺得這個臨時表test_vip_new_bak有些多餘。帶著這種思路分析,看起來邏輯很簡單啊,於是就聯絡了開發的同學,一起討論一番。
但是討論完之後,還是讓我有些不知所措。
首先,語句為什麼要多次關聯,自己做了一個小的測試,感覺這種關聯方式還是有些多餘。
SQL> create table a (id number);
Table created.
SQL> create table b (id number);
Table created.
SQL> insert into a values(1);
1 row created.
SQL> insert into a values(2);
1 row created.
SQL> insert into b values(1);
1 row created.
SQL> select * from a minus select * from b;
ID
----------
2
SQL> select *from a left join b on a.id=b.id;
ID ID
---------- ----------
1 1
2
如果按照這樣的思路,仿照原來的結構輸出就是下面這樣的結果。
SQL> select *from (select * from a minus select * from b) a left join b on a.id=b.id;
ID ID
---------- ----------
2
但是和開發討論了一番,發現我的想法有些簡單了,具體的場景中資料過濾的邏輯比上面這種略微複雜一些。
透過一個兩個測試表來模擬。
create table a (id1 number,id2 number);create table game_new (id1 number,id2 number);
create table game_new_bak (id1 number,id2 number);
如果原來的資料內容為(1,1),在執行儲存過程之後,會修改為(1,2)
SQL> insert into game_new values(1,2);
1 row created.
然後儲存過程在執行過程中,會插入一些新的資料,假設為(2,2)
SQL> insert into game_new values(2,2);
1 row created.
而臨時表game_new_bak中的資料是儲存過程執行之前的資料狀態,即(1,1)
SQL> insert into game_new_bak values(1,1);
1 row created.
按照這種情況,兩個表做了minus操作之後會輸出兩行,即修改之後的資料和新增的資料。
而這個需求需要實現的是,根據id1進行匹配,把修改前的id2一併輸出。這樣就知道修改前是什麼樣的資料了,如果是新增的,那這列的值就保持為空。
SQL> select a.id1,a.id2,b.id2 from (select * from game_new minus select *from game_new_bak) a left join game_new_bak b on a.id1=b.id1
ID1 ID2 ID2
---------- ---------- ----------
1 2 1
2 2
如果是這樣的情況,就完全可以使用一次表關聯就可以改進。可以用下面的形式。
select a.id1,a.id2,b.id2 from game_new a ,game_new_bak b where a.id1=b.id1(+)
所以就建議語句從原來的形式
SELECT A.CN,A.GRADE,A.RANK,A.SCORE,DECODE(SIGN
(A.RANK-(NVL(B.RANK,-1))),1,2,-1,3,0,1),
SYSDATE,(NVL(B.RANK,-1)),B.SIGN,B.FLAG,B.TAG,B.SCORE FROM ( SELECT *
FROM GAME_VIP_NEW MINUS SELECT * FROM GAME_VIP_NEW_BAK ) A LEFT JOIN
GAME_VIP_NEW_BAK B ON A.CN=B.CN
修改為:
SELECT /*+parallel(4)*/ A.CN,A.GRADE,A.RANK,A.SCORE,DECODE(SIGN
(A.RANK-(NVL(B.RANK,-1))),1,2,-1,3,0,1),
SYSDATE,(NVL(B.RANK,-1)),B.SIGN,B.FLAG,B.TAG,B.SCORE FROM GAME_VIP_NEW a,cydba.GAME_VIP_NEW_BAK B
where A.CN=B.CN(+)
考慮到執行的情況和資源情況,加了一個並行,可以在一定程度上緩解這個問題。
在本地的環境中進行了測試,發現幾分鐘就可以輕鬆搞定,做了基本的確認,就和開發進行了反饋,對線上的儲存過程內容進行了修改。
這個問題的解決也就終於告一段落。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8494287/viewspace-2089573/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一條insert語句導致的效能問題分析(一)
- 一條sql語句導致的資料庫當機問題及分析SQL資料庫
- 一條sql語句“導致”的資料庫當機問題及分析SQL資料庫
- 由一條sql語句導致的系統IO問題SQL
- 一條簡單的sql語句導致的系統問題SQL
- 一條執行4秒的sql語句導致的系統問題SQL
- merge語句導致的效能問題緊急優化優化
- Oracle 使用一條insert語句完成多表插入Oracle
- 【SQL】使用一條INSERT語句完成多表插入SQL
- merge語句導致的ORA錯誤分析
- ANALYZE導致的阻塞問題分析
- insert導致的效能問題大排查(r11筆記第26天)筆記
- mysql insert語句錯誤問題解決MySql
- MySQL8.0 view導致的效能問題MySqlView
- SCHEDULER呼叫XDB程式導致效能問題
- 【Mysql】兩條insert 語句產生的死鎖MySql
- C 語言宣告與定義不一致導致的問題
- 執行計劃的偏差導致的效能問題
- MySQL 中 一條 order by index limit 語句的分析MySqlIndexMIT
- 一條全表掃描sql語句的分析SQL
- 一條sql語句的建議調優分析SQL
- oracle效能問題:sql語句優化OracleSQL優化
- PostgreSQL的insert語句執行過程分析SQL
- 如此大的一條sql語句在30個左右的併發訪問系統當中的效能問題?SQL
- 完美的執行計劃導致的效能問題
- Oracle資料庫導致效能問題的可能原因Oracle資料庫
- memlock過低導致的資料庫效能問題資料庫
- SQLite語句(二):INSERT DELETE UPDATE SELECTSQLitedelete
- 執行SQL語句導致mysqld的crashMySql
- [20141203]分析語句導致阻塞分析表.txt
- SQLite Insert 語句SQLite
- MySQL中insert語句沒有響應的問題分析(r11筆記第21天)MySql筆記
- 比CRUD多一點兒(二):基礎INSERT、SELECT語句
- 一個insert插入語句很慢的優化優化
- 資料庫統計資訊不更新導致的效能問題資料庫
- 優化由直方圖資訊導致的sql效能問題優化直方圖SQL
- DB Link因 driving_site導致的效能問題
- JPA 二級快取 網路多播協議導致的資料庫效能問題快取協議資料庫