一條insert語句導致的效能問題分析(二

2021-09-22 19:16:37 字數 2982 閱讀 8057

今天對之前描述的問題

一條insert語句導致的效能問題分析(一)

進行了進一步的補充。

有一條insert語句的主要效能瓶頸在於insert子句中的查詢語句,查詢中的主要資源消耗在於對兩個表進行了多次關聯

語句主要的結構如下:

insert into ***xx   (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(+)

考慮到執行的情況和資源情況,加了乙個並行,可以在一定程度上緩解這個問題。

在本地的環境中進行了測試,發現幾分鐘就可以輕鬆搞定,做了基本的確認,就和開發進行了反饋,對線上的儲存過程內容進行了修改。

這個問題的解決也就終於告一段落。

一條Select語句導致瓶頸

情況 上週,公司一專案新上線,剛上線的第2天,在後台發現資料庫伺服器與iis伺服器的網路io出現瓶頸,1gb的網路頻寬,占用了70 100 也就是每秒傳輸資料700mb 1gb,資料庫使用記憶體高達21gb。iis伺服器cpu使用率時常爆至80 90 導致 頻頻出現連線超時。原因select fro...

使用一條INSERT語句完成多表插入

這是一條顛覆常規的插入方法,一條insert語句可以完成向多張表的插入任務。小小地展示一下這種插入方法。1.建立表t並初始化測試資料,此表作為資料來源。sec ora10g create table t x number 10 y varchar2 10 sec ora10g insert into...

一條insert語句批量插入多條記錄

常見的insert語句,向資料庫中,一條語句只能插入一條資料 一條insert只能插入一條資料 insert into person id,personcode,personname telnumber values 1,5112403 張三 1378902134 一次插入多條資料的方法 方式一 i...