W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
許多觸發(fā)器可以干的事情同樣也可以用PostgreSQL規(guī)則系統(tǒng)來(lái)實(shí)現(xiàn)。目前不能用規(guī)則來(lái)實(shí)現(xiàn)的東西之一是某些約束,特別是外鍵。 可以放置一個(gè)合格的規(guī)則在一列上,這個(gè)規(guī)則在列的值沒(méi)有出現(xiàn)在另一個(gè)表中時(shí)把命令重寫(xiě)成NOTHING
。但是這樣做數(shù)據(jù)就會(huì)被不聲不響地丟棄,因此也不是一個(gè)好主意。如果要求檢查值的有效性,并且在出現(xiàn)無(wú)效值的情況下應(yīng)該生成一個(gè)錯(cuò)誤消息,這種需求就必須要用觸發(fā)器來(lái)完成。
在本章中,我們關(guān)注于使用規(guī)則來(lái)更新視圖。本章中所有的更新規(guī)則的例子都可以使用視圖上的INSTEAD OF
觸發(fā)器來(lái)實(shí)現(xiàn)。編寫(xiě)這類觸發(fā)器通常比編寫(xiě)規(guī)則要容易,特別是在要求使用復(fù)雜邏輯來(lái)執(zhí)行更新的情況下。
對(duì)于兩者都可實(shí)現(xiàn)的情況,哪個(gè)更好取決于對(duì)數(shù)據(jù)庫(kù)的使用。觸發(fā)器為每一個(gè)受影響的行都執(zhí)行一次。規(guī)則修改查詢樹(shù)或生成一個(gè)額外的查詢。所以如果在一個(gè)語(yǔ)句中影響到很多行, 一個(gè)發(fā)出額外查詢的規(guī)則通常可能會(huì)比一個(gè)觸發(fā)器快,因?yàn)橛|發(fā)器對(duì)每一個(gè)行都要被調(diào)用,并且每次被調(diào)用時(shí)都需要重新判斷要做什么樣的操作。不過(guò),觸發(fā)器方法從概念上要遠(yuǎn)比規(guī)則方法簡(jiǎn)單,并且很容易讓新人上手。
下面我們展示一個(gè)例子,該例子說(shuō)明了在同種情況下兩種選擇的比較。這里有兩個(gè)表:
CREATE TABLE computer (
hostname text, -- 被索引
manufacturer text -- 被索引
);
CREATE TABLE software (
software text, -- 被索引
hostname text -- 被索引
);
兩個(gè)表都有數(shù)千行,并且在hostname
上的索引是唯一的。規(guī)則或觸發(fā)器應(yīng)該實(shí)現(xiàn)一個(gè)約束,該約束從software
中刪除引用已刪除計(jì)算機(jī)的行。 觸發(fā)器可以用下面這條命令:
DELETE FROM software WHERE hostname = $1;
因?yàn)橛|發(fā)器會(huì)為每一個(gè)從computer
中刪除的獨(dú)立行調(diào)用一次, 那么它可以準(zhǔn)備并且保存這個(gè)命令的規(guī)劃,把hostname
作為參數(shù)傳入。規(guī)則應(yīng)該被寫(xiě)為:
CREATE RULE computer_del AS ON DELETE TO computer
DO DELETE FROM software WHERE hostname = OLD.hostname;
現(xiàn)在看看不同類型的刪除。在這種情況:
DELETE FROM computer WHERE hostname = 'mypc.local.net';
表computer
被使用索引(快速)掃描,并且由觸發(fā)器發(fā)出的命令也將使用一個(gè)索引掃描(同樣快速)。來(lái)自規(guī)則的額外查詢應(yīng)該是:
DELETE FROM software WHERE computer.hostname = 'mypc.local.net'
AND software.hostname = computer.hostname;
由于已經(jīng)建立了合適的索引,規(guī)劃器將創(chuàng)建一個(gè)規(guī)劃
Nestloop
-> Index Scan using comp_hostidx on computer
-> Index Scan using soft_hostidx on software
所以在觸發(fā)器和規(guī)則的實(shí)現(xiàn)之間沒(méi)有太多的速度差別。
在接下來(lái)的刪除中,我們想要去掉所有 2000 個(gè)hostname
以old
開(kāi)頭的計(jì)算機(jī)。有兩個(gè)命令可以來(lái)做這件事。一個(gè)是:
DELETE FROM computer WHERE hostname >= 'old'
AND hostname < 'ole'
被規(guī)則增加的命令將是:
DELETE FROM software WHERE computer.hostname >= 'old' AND computer.hostname < 'ole'
AND software.hostname = computer.hostname;
計(jì)劃是:
Hash Join
-> Seq Scan on software
-> Hash
-> Index Scan using comp_hostidx on computer
另一個(gè)可能的命令是:
DELETE FROM computer WHERE hostname ~ '^old';
它會(huì)為規(guī)劃增加的命令產(chǎn)生下面的執(zhí)行計(jì)劃:
Nestloop
-> Index Scan using comp_hostidx on computer
-> Index Scan using soft_hostidx on software
這表明,當(dāng)有多個(gè)條件表達(dá)式被使用AND
組合在一起時(shí),規(guī)劃器不能認(rèn)識(shí)到表computer
中hostname
上的條件也可以被用于一個(gè)software
上的索引掃描, 而在該命令的正則表達(dá)式版本中正是這樣做的。觸發(fā)器將為要被刪除的 2000 個(gè)舊計(jì)算機(jī)中的每一個(gè)調(diào)用,并且會(huì)導(dǎo)致在
computer
上的一次索引掃描和software
上的 2000 次索引掃描。采用規(guī)則的實(shí)現(xiàn)將會(huì)使用兩個(gè)使用索引的命令來(lái)完成。 并且在順序掃描情況下規(guī)則是否仍將更快是取決于software
表的總體大小的。即使所有的索引塊都將很快地進(jìn)入高速緩存,通過(guò) SPI 管理器執(zhí)行來(lái)自觸發(fā)器的 2000 個(gè)命令也要花不少時(shí)間。
我們要看的最后一個(gè)命令是:
DELETE FROM computer WHERE manufacturer = 'bim';
同樣,這也會(huì)導(dǎo)致很多行被從computer
中刪除。所以觸發(fā)器同樣會(huì)通過(guò)執(zhí)行器運(yùn)行很多命令。規(guī)則生成的命令將會(huì)是:
DELETE FROM software WHERE computer.manufacturer = 'bim'
AND software.hostname = computer.hostname;
這個(gè)命令的計(jì)劃又將是在兩個(gè)索引掃描上的嵌套循環(huán),只不過(guò)使用了computer
上的另一個(gè)索引:
Nestloop
-> Index Scan using comp_manufidx on computer
-> Index Scan using soft_hostidx on software
在任何這些情況之一,來(lái)自規(guī)則系統(tǒng)的額外命令都或多或少與命令中影響的行數(shù)無(wú)關(guān)。
概括來(lái)說(shuō),規(guī)則只有在其動(dòng)作導(dǎo)致了大而且糟糕的條件連接時(shí)才會(huì)明顯地慢于觸發(fā)器,這種情況下規(guī)劃器將沒(méi)有什么辦法。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: