日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Delete..In.. 删除语句的优化再次探讨

發布時間:2023/12/13 综合教程 28 生活家
生活随笔 收集整理的這篇文章主要介紹了 Delete..In.. 删除语句的优化再次探讨 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

有這樣一張成績表

CREATE TABLE stu_score
(
    id int ,
    stu_id int,
    course_id int,
    score int,
    primary key(id)
)

可以這樣給它插入實驗值:

Insert into stu_score
select rownum,dbms_random.value(0,10000),dbms_random.value(1,5),dbms_random.value(0,150) from dual
connect by level<10001

然后需求來了,stu_id和course_id相同時,最高的成績保留,其余刪除。用日常話來說就是取每個學生單科的最佳成績。

第一種刪除方式:

delete from stu_score where (stu_id,course_id,score) not in (select stu_id,course_id,max(score) as score from stu_score group by stu_id,course_id);

處理結果:

SQL> delete from stu_score where (stu_id,course_id,score) not in (select stu_id,course_id,max(score) as score from stu_score group by stu_id,course_id);

已刪除1048行。

已用時間:  00: 00: 28.68

耗時約28秒,select stu_id,course_id,max(score) as score from stu_score group by stu_id,course_id的結果是8943條,這種刪除需要從一萬條里逐條取出去和8943條比對,比對次數為10000*8943次。雖說小表產生性能問題是小概率事件,但遲早會碰上。

這條刪除語句慢的原因部分在于 stu_id,course_id,score 都不是主鍵,沒有索引幫助,只能走全表查詢的路子。但是,從解釋計劃來看,cost的飆升段發生在Delete Statement,達到了八千多,和后面的查詢關系真心不大。我試了select * fromstu_score where (stu_id,course_id,score) not in (select stu_id,course_id,max(score) as score from stu_score group by stu_id,course_id) 這樣的語句,其中只是把delete替換成了select * ,執行起來就是秒出,并無delete時的阻滯。

有些書上提到過給甄別列stu_id,course_id,score 加上索引能加快刪除速度的說法,我嘗試過沒有效果。具體如下:

SQL> create index idx_stuscore_three on stu_score(stu_id,course_id,score);

索引已創建。

已用時間:  00: 00: 00.06
SQL> delete from stu_score where (stu_id,course_id,score) not in (select stu_id,course_id,max(score) as score from stu_score group by stu_id,course_id);

已刪除1011行。

已用時間:  00: 00: 29.47

第二種刪除方式:

delete from stu_score where id not in (select a.id from stu_score a,( select stu_id,course_id,max(score) as score from stu_score group by stu_id,course_id ) b
where a.stu_id=b.stu_id and a.course_id=b.course_id and a.score=b.score)

處理結果:

SQL> delete from stu_score where id not in (select a.id from stu_score a,( select stu_id,course_id,max(score) as score from stu_score group by stu_id,course_id ) b
  2  where a.stu_id=b.stu_id and a.course_id=b.course_id and a.score=b.score);

已刪除1048行。

已用時間:  00: 00: 00.06

用時不到一秒,這種方式形成了一個id臨時結果集,一萬條里逐條拿id去看在不在這個結果集里,比對次數為10000次加一次結果集查詢。由于id是主鍵,有效利用了id上的索引,這自然比全表查詢要快。從解釋計劃上看,包括delete statement部分的cost只有區區三十幾。

第三種刪除方式:

delete from stu_score where not exists (
select null from stu_score a,
(select stu_id,course_id,max(score) as score from stu_score group by stu_id,course_id) b
where a.stu_id=b.stu_id and a.course_id=b.course_id and a.score=b.score and stu_score.id=a.id)

處理結果:

SQL> delete from stu_score where not exists (
  2  select null from stu_score a,
  3                   (select stu_id,course_id,max(score) as score from stu_score group by stu_id,course_id) b
  4  where a.stu_id=b.stu_id and a.course_id=b.course_id and a.score=b.score and stu_score.id=a.id);

已刪除1048行。

已用時間:  00: 00: 00.12

用時不到一秒,這種方式取出每行id進行了一次存在性查詢,總體為一萬次存在性查詢。從解釋計劃上看,包括delete statement部分的cost也只有區區三十幾。

可以看出,雖然存在子查詢,但后兩種相當于一萬次函數調用,且函數參數只有一個,結果都是秒出;而第一種是10000*8943約九千萬次比對,比對參數還有三個,相當于九千萬次三個參數的函數調用,這自然落了下風。

由于SQL語句的度量不像程序般透徹,只能以運行時間去套函數調用的概念,目前水平也只能解釋到這個程度,大家見諒。

前作:https://www.cnblogs.com/heyang78/p/12263253.html

END

總結

以上是生活随笔為你收集整理的Delete..In.. 删除语句的优化再次探讨的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。