oracle 删除主键_大数据量删除的思考 4
譯者? 湯健 · 沃趣科技數據庫技術專家
出品 ?沃趣科技
在本系列的前一期文章中,我制作了一些圖,突出顯示了按表掃描執(zhí)行大量刪除操作和按索引范圍掃描執(zhí)行大量刪除之間的主要區(qū)別。根據所涉及的數據模式,選擇正確的策略可能對隨機I/Os的數量、生成的undo的數量和排序所需的CPU數量產生顯著影響——所有這些都可能影響執(zhí)行刪除所需的時間。然而,這個簡單的演示跟生產環(huán)境當中相比,生產環(huán)境當中這個情況更為復雜。所以,如果你面臨著一項艱巨的任務,你需要仔細考慮如何對真正代表你要處理的系統的東西進行建模。實際上有兩種不同的情況,這一點很重要。*當你在處理一個非常大的一次性任務時,你需要在第一時間就把它做好,一些關鍵性的特殊情況不要發(fā)現的太遲——尤其是如果你不允許把生產系統離線來完成這個任務任務,而且你的工作期限很緊的話。*當你有一份常規(guī)的、但不經常發(fā)生的、非常大的工作時,有必要了解一下哪些看起來不相關的小操作可能對運行時產生很大影響;而且,了解下一次升級可能會出現什么問題是值得的,這樣您就可以預先解決任何問題。當然,后者的一個簡單例子是我對12c的簡短評論,以及它通過索引快速全掃描來驅動刪除的能力-這一功能在早期版本的Oracle中無法運行。在我的小示例中,一個測試將其執(zhí)行計劃從11g的索引全掃描更改為12c的索引快速全掃描,完成所需的時間是原來的兩倍。繼續(xù)想一想——當你試圖通過索引范圍掃描來刪除Oracle中的表或者索引時,您能想到多少事情,這可能會產生怎樣的影響?對于一個繁忙的系統,這個建議聽起來不錯。有時候,你會發(fā)現一個長時間運行的DML語句在運行時速度非常慢,因為事實上它涉及到數據中最近的部分,因此會受到當前變化的影響;從這一點來看,Oracle發(fā)現它必須讀取undo段來獲取undo數據,這使得創(chuàng)建與讀取一致的數據塊版本成為可能-它需要這樣做,以便它可以檢查當前和讀取一致的版本的塊同意哪些行應該刪除。我做的一個例子是通過“date_open”索引刪除數據-因此,如何強制索引進行降序范圍掃描,以便首先檢查最新的數據在它有很多(或任何)時間遭受其他DML的附帶損害之前?有一個非常快捷的方法可以檢驗這個想法的有效性。所以我們要做的就是檢查排序的行數和刪除的行數我們就能知道優(yōu)化是否發(fā)生了。我的測試數據集有1000000行和4個索引(主鍵client_ref、date_open和date_closed索引),所以在最好的情況下,我應該看到:“sort (rows)”= 4 *行被刪除。下面是我做的一個測試的總結,我想知道會發(fā)生什么:delete?/*+?index_desc(t1?t1_pk)?*/?from?t1?where?id?<=?5e65000000?rows?deleted.
Name?????????????????????????????????Value???????????????????????
----?????????????????????????????????-----
sorts?(rows)????????????????????????????29
我們刪除了500萬行并(有效地)沒有排序。當我們按降序遍歷索引時,優(yōu)化根本不適用—我確實檢查了執(zhí)行計劃是否顯示了我所指定的“索引范圍遞減掃描”。
create?index?t1_dt_open?on?t1(date_open?desc)?nologging?tablespace?test_8k_assm_2;delete?/*+?index(t1?t1_dt_open)?*/?from?t1?where?date_open?<=?add_months(sysdate,?-60);
4999999?rows?deleted.
Name?????????????????????????????????Value
----?????????????????????????????????-----
sorts?(rows)????????????????????20,003,449
在副作用很小的范圍內,“sort (rows)”= 4 *已刪除的行:所以可以使用降序索引先嘗試刪除較新的數據——這很好,作為一個通用特性來記住可能很有用。
讓我們想象一下其他可能出錯的情況。*我在這個表上定義了一個主鍵——但是你可以使約束延遲,或者您可以簡單地創(chuàng)建一個非惟一索引來保護惟一(或主鍵)約束。如果我們試圖通過主鍵索引刪除,會產生什么影響?*如果我們要考慮約束,我們可能要考慮外鍵約束的影響——我們有一個client_ref列,在生產系統中,它可能是對clients表的外鍵引用。讓我們創(chuàng)建這個表并添加外鍵約束。*當我們使事情變得更困難時——有一個眾所周知的特性將數組處理轉換為“逐行”處理——觸發(fā)器。如果我們向表中添加行級觸發(fā)器,會產生什么效果?什么類型的觸發(fā)器(在之前/之后、插入/更新/刪除)有什么區(qū)別嗎?以下是一些結果-首先,主鍵約束的非唯一索引:alter?table?t1?drop?primary?key;alter?table?t1?add?constraint?t1_pk?primary?key(id)
deferrable?initially?immediate
using?index?nologging?tablespace?test_8k_assm_2
;
delete?/*+?index(t1?t1_pk)?*/?from?t1?where?id?<=?5e6;
5000000?rows?deleted.
Name?????????????????????????????????Value
----?????????????????????????????????-----
sorts?(rows)?????????????????????15,000,004
在這個例子中,Oracle將我的主鍵索引設置為非惟一,作為約束可延遲的副作用,但是即使約束不可延遲,并且您只是將索引創(chuàng)建為非惟一,其效果也是一樣的。統計數據告訴我們,我們已經將優(yōu)化應用于四個索引中的三個——快速檢查一下v$segment_statistics,就會發(fā)現它是主鍵索引,沒有進行特殊處理,它受到了超過500萬個“db塊更改”的影響。在這一點上,有必要快速檢查一下,看看通過其他索引驅動是否會改變這種情況——但是不會,這是惟一約束與非惟一索引結合的副作用。
其次,當大表是“子表”時,引用完整性的影響:create?table?t2?(????????client_id,
????????client_name
)?as
select
????????distinct
????????????????client_ref,
????????????????rpad('x',100,'x')
from
????????t1
;
alter?table?t2?add?constraint?t2_pk?primary?key(client_id);
alter?table?t1?modify?client_ref?not?null;
alter?table?t1?add?constraint?t1_fk_t2?foreign?key?(client_ref)?references?t2(client_id);
5000000?rows?deleted.
Name?????????????????????????????????Value
----?????????????????????????????????-----
sorts?(rows)????????????????????15,002,849
我們已經排序了大約1500萬行,而通常我們需要排序2000萬行.同樣,我們可以檢查v$segment_statistics來找出哪個索引遭受了500萬的損失“db block changes”你可能不會對“外鍵”索引被逐行維護而感到驚訝-我們可能會猜測,這是某種先發(fā)制人的代碼使得Oracle必須處理“外鍵鎖定”威脅。
我們通過主鍵刪除這個特定測試的后續(xù)操作是,考慮如果我們通過外鍵索引本身刪除,或者甚至將約束修改為“on delete cascade”并刪除一些父行,將會發(fā)生什么。通過client_ref在t1上驅動delete仍然優(yōu)化了其他三個索引,但是當您試圖利用“on delete cascade”機制時,這個技巧根本沒有機會產生大規(guī)模的效果。在幕后你會發(fā)現這樣的事情:delete?from?"TEST_USER"."T1"where
?"CLIENT_REF"?=?:1
call?????count???????cpu????elapsed???????disk??????query????current????????rows
-------?------??--------?----------?----------?----------?----------??----------
Parse????????3??????0.00???????0.00??????????0??????????0??????????0???????????0
Execute???3000??????5.23??????15.37??????69349???????9238?????428052???????32510
Fetch????????0??????0.00???????0.00??????????0??????????0??????????0???????????0
-------?------??--------?----------?----------?----------?----------??----------
total?????3003??????5.23??????15.37??????69349???????9238?????428052???????32510
Rows?(1st)?Rows?(avg)?Rows?(max)??Row?Source?Operation
----------?----------?----------??---------------------------------------------------
?????0??????????0??????????0??DELETE??T1?(cr=3?pr=22?pw=0?time=9672?us)
?????7??????????8?????????11???INDEX?RANGE?SCAN?T1_CLIENT?(cr=3?pr=0?pw=0?time=125?us?cost=3?size=594?card=22)(object?id?150589)
This?output?the?consequence?of?a?bulk?delete?of?3,000?rows?from?t2?–?because?of?the?“on?delete?cascade”,?the?delete?operated?row?by?row?on?t2?and?for?each?row?Oracle?executed?a?delete?statement?against?t1.
這個輸出是t2批量刪除3000行的結果——由于“on delete cascade”,delete在t2上逐行操作,對于每一行Oracle都對t1執(zhí)行一條delete語句。
從技術上講,基于數組的優(yōu)化是有效的,由于索引范圍掃描,它給我們帶來了一點好處,但是數據的分散性是如此之大,以至于每次調用幾乎沒有給我們帶來任何好處。在某個階段,我們將不得不進一步探索這種父/子的關系。最后是觸發(fā)器。眾所周知,行級觸發(fā)器可以將數組處理轉換為單行處理——Oracle的索引維護優(yōu)化也會發(fā)生同樣的事情嗎?create?or?replace?trigger?t1_brdbefore?delete?on?t1
for?each?row
begin
????null;
end;
/
delete?/*+?index(t1?t1_pk)?*/?from?t1?where?id?<=?5e6;
5000000?rows?deleted.
Name?????????????????????????????????Value
----?????????????????????????????????-----
sorts?(rows)?????????????????????????2,639
優(yōu)化完全消失了。同樣的事情也會發(fā)生在“為每一行刪除后”觸發(fā)器上,但是如果觸發(fā)器是insert或update(行級)觸發(fā)器,則不會發(fā)生這種情況。值得一提的是,索引優(yōu)化也發(fā)生在索引列的值發(fā)生變化的更新上(請參閱本文),因此留給感興趣的讀者一個練習,看看哪些(如果有的話)觸發(fā)器類型允許優(yōu)化在數組更新后繼續(xù)存在。
| 譯者簡介
湯健·沃趣科技數據庫技術專家
沃趣科技數據庫工程師,多年Oracle數據庫從業(yè)經驗,深入理解Oracle數據庫結構體系,現主要參與公司一體機產品安裝、測試、優(yōu)化,并負責電信行業(yè)數據庫以及系統運維。
相關鏈接
MySQL 一個讓你懷疑人生的hang死現象
MySQL 執(zhí)行DDL語句 hang住了怎么辦?
MySQL行級別并行復制能并行應用多少個binlog group?
binlog server還是不可靠嗎?
MySQL binlog基于時間點恢復數據失敗是什么鬼?
開源監(jiān)控系統Prometheus的前世今生
prometheus監(jiān)控多個MySQL實例
MySQL問題兩則
Kubernetes?scheduler學習筆記
大數據量刪除的思考(三)
大數據量刪除的思考(二)
大數據量刪除的思考(一)
統計信息記錄表|全方位認識 mysql 系統庫
數據庫對象信息記錄表|全方位認識 mysql 系統庫
訪問權限控制系統|全方位認識 mysql 系統庫
權限系統表?|?全方位認識?mysql?系統庫
Oracle RAC Cache Fusion 系列十四:Oracle RAC CR Server Part One
Oracle RAC Cache Fusion 系列十三:PCM資源訪問
Oracle RAC Cache Fusion 系列十二:Oracle RAC Enqueues And Lock Part 3
Oracle RAC Cache Fusion 系列十一:Oracle RAC Enqueues And Lock Part 2
Oracle RAC Cache Fusion 系列十:Oracle RAC Enqueues And Lock Part 1
更多干貨,歡迎來撩~
總結
以上是生活随笔為你收集整理的oracle 删除主键_大数据量删除的思考 4的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DCM4CHEE 中worklist 乱
- 下一篇: java dcm4che findscu