39.7. СÑавнение пÑавил и ÑÑиггеÑов #
Ðногие веÑи, коÑоÑÑе можно ÑделаÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ ÑÑиггеÑов, можно Ñакже ÑеализоваÑÑ, иÑполÑзÑÑ ÑиÑÑÐµÐ¼Ñ Ð¿Ñавил Postgres Pro. Ðднако, иÑполÑзÑÑ Ð¿Ñавила, нелÑÐ·Ñ ÑеализоваÑÑ, напÑимеÑ, некоÑоÑÑе ÑÐ¸Ð¿Ñ Ð¾Ð³ÑаниÑений, в ÑаÑÑноÑÑи, внеÑние клÑÑи. ХоÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ опÑеделиÑÑ Ð¿Ñавило Ñ Ð¾Ð³ÑаниÑиваÑÑим ÑÑловием, коÑоÑое бÑÐ´ÐµÑ Ð¿ÑеобÑазоваÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð² NOTHING, еÑли знаÑение клÑÑа не наÑ
одиÑÑÑ Ð² дÑÑгой ÑаблиÑе, но пÑи ÑÑом неподÑ
одÑÑие даннÑе бÑдÑÑ Ð¾ÑбÑаÑÑваÑÑÑÑ Ð¼Ð¾Ð»Ñа, а ÑÑо не ÑамÑй лÑÑÑий ваÑианÑ. Также, еÑли ÑÑебÑеÑÑÑ Ð¿ÑовеÑиÑÑ Ð¿ÑавилÑноÑÑÑ Ð·Ð½Ð°Ñений и, обнаÑÑжив невеÑное знаÑение, вÑдаÑÑ Ð¾ÑибкÑ, ÑÑо нÑжно делаÑÑ Ð² ÑÑиггеÑе.
Ð ÑÑой главе Ð¼Ñ ÑазбеÑÑм иÑполÑзование пÑавил Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ñ Ð¿ÑедÑÑавлений. ÐÑе пÑавила, пÑиведÑннÑе в пÑимеÑаÑ
ÑÑой главÑ, можно Ñакже замениÑÑ ÑÑиггеÑами INSTEAD OF Ð´Ð»Ñ Ð¿ÑедÑÑавлений. ÐапиÑаÑÑ Ñакие ÑÑиггеÑÑ ÑаÑÑо бÑÐ²Ð°ÐµÑ Ð¿ÑоÑе, Ñем ÑазÑабоÑаÑÑ Ð¿Ñавила, оÑобенно еÑли Ð´Ð»Ñ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ пÑименÑеÑÑÑ ÑÐ»Ð¾Ð¶Ð½Ð°Ñ Ð»Ð¾Ð³Ð¸ÐºÐ°.
ÐÐ»Ñ ÑÐµÑ Ð·Ð°Ð´Ð°Ñ, коÑоÑÑе можно ÑеÑиÑÑ Ð¾Ð±Ð¾Ð¸Ð¼Ð¸ ÑпоÑобами, лÑÑÑий вÑбиÑаеÑÑÑ Ð² завиÑимоÑÑи Ð¾Ñ Ñ Ð°ÑакÑеÑа иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ . СледÑÐµÑ ÑÑиÑÑваÑÑ, ÑÑо ÑÑÐ¸Ð³Ð³ÐµÑ ÑÑабаÑÑÐ²Ð°ÐµÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ обÑабаÑÑваемой ÑÑÑоки, а пÑавило изменÑÐµÑ ÑÑÑеÑÑвÑÑÑий запÑÐ¾Ñ Ð¸Ð»Ð¸ ÑоздаÑÑ ÐµÑÑ Ð¾Ð´Ð¸Ð½. ÐоÑÑомÑ, еÑли один опеÑаÑÐ¾Ñ Ð¾Ð±ÑабаÑÑÐ²Ð°ÐµÑ ÑÑÐ°Ð·Ñ Ð¼Ð½Ð¾Ð³Ð¾ ÑÑÑок, пÑавило, добавлÑÑÑее дополниÑелÑнÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ, ÑкоÑее вÑего, бÑÐ´ÐµÑ ÑабоÑаÑÑ Ð±ÑÑÑÑее, Ñем ÑÑиггеÑ, коÑоÑÑй вÑзÑваеÑÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ оÑеÑедной ÑÑÑоки и должен каждÑй Ñаз опÑеделÑÑÑ, ÑÑо Ñ Ð½ÐµÐ¹ делаÑÑ. Ðднако ÑÑиггеÑÑ ÐºÐ¾Ð½ÑепÑÑалÑно гоÑаздо пÑоÑе пÑавил, и иÑполÑзоваÑÑ Ð¸Ñ Ð¿ÑавилÑно новиÑкам гоÑаздо пÑоÑе.
ÐавайÑе ÑаÑÑмоÑÑим пÑимеÑ, показÑваÑÑий, как вÑÐ±Ð¾Ñ Ð² полÑÐ·Ñ Ð¿Ñавил вмеÑÑо ÑÑиггеÑов оказÑваеÑÑÑ Ð²ÑигÑÑÑнÑм в опÑеделÑнной ÑиÑÑаÑии. ÐÑÑÑÑ Ñ Ð½Ð°Ñ ÐµÑÑÑ Ð´Ð²Ðµ ÑаблиÑÑ:
CREATE TABLE computer (
hostname text, -- индекÑиÑованное
manufacturer text -- индекÑиÑованное
);
CREATE TABLE software (
software text, -- индекÑиÑованное
hostname text -- индекÑиÑованное
); Ðбе ÑаблиÑÑ ÑодеÑÐ¶Ð°Ñ Ð½ÐµÑколÑко ÑÑÑÑÑ ÑÑÑок, а индекÑÑ Ð¿Ð¾ Ð¿Ð¾Ð»Ñ hostname ÑвлÑÑÑÑÑ ÑникалÑнÑми. ÐÑавило или ÑÑÐ¸Ð³Ð³ÐµÑ Ð´Ð¾Ð»Ð¶Ð½Ñ ÑеализоваÑÑ Ð¾Ð³ÑаниÑение, коÑоÑое ÑÐ´Ð°Ð»Ð¸Ñ ÑÑÑоки из ÑаблиÑÑ software, ÑÑÑлаÑÑиеÑÑ Ð½Ð° ÑдалÑемÑй компÑÑÑеÑ. ТÑÐ¸Ð³Ð³ÐµÑ Ð²ÑполнÑл Ð±Ñ ÑакÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ:
DELETE FROM software WHERE hostname = $1;
Так как ÑÑÐ¸Ð³Ð³ÐµÑ Ð²ÑзÑваеÑÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ оÑделÑной ÑÑÑоки, ÑдалÑемой из ÑаблиÑÑ computer, он Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð´Ð³Ð¾ÑовиÑÑ Ð¸ ÑоÑ
ÑаниÑÑ Ð¿Ð»Ð°Ð½ ÑÑой командÑ, а заÑем пеÑедаваÑÑ Ð·Ð½Ð°Ñение hostname подгоÑÐ¾Ð²Ð»ÐµÐ½Ð½Ð¾Ð¼Ñ Ð·Ð°Ð¿ÑоÑÑ Ð² паÑамеÑÑаÑ
. ÐÑавило же можно запиÑаÑÑ Ñак:
CREATE RULE computer_del AS ON DELETE TO computer
DO DELETE FROM software WHERE hostname = OLD.hostname;ТепеÑÑ Ð´Ð°Ð²Ð°Ð¹Ñе взглÑнем на ÑазнÑе ваÑианÑÑ ÑдалениÑ. Ð ÑÑом ÑлÑÑае:
DELETE FROM computer WHERE hostname = 'mypc.local.net';
ÑаблиÑа computer ÑканиÑÑеÑÑÑ Ð¿Ð¾ индекÑÑ (бÑÑÑÑо), и команда, вÑполнÑÐµÐ¼Ð°Ñ ÑÑиггеÑом, Ñак же бÑÐ´ÐµÑ Ð¿ÑименÑÑÑ ÑканиÑование по индекÑÑ (Ñоже бÑÑÑÑо). ÐополниÑелÑной командой пÑавила бÑдеÑ:
DELETE FROM software WHERE computer.hostname = 'mypc.local.net'
AND software.hostname = computer.hostname;Так как ÑÐ¾Ð·Ð´Ð°Ð½Ñ Ð²Ñе Ð½ÐµÐ¾Ð±Ñ Ð¾Ð´Ð¸Ð¼Ñе индекÑÑ, планиÑовÑик ÑоздаÑÑ Ð¿Ð»Ð°Ð½
Nestloop -> Index Scan using comp_hostidx on computer -> Index Scan using soft_hostidx on software
Таким обÑазом, болÑÑого ÑазлиÑÐ¸Ñ Ð² ÑкоÑоÑÑи Ð¼ÐµÐ¶Ð´Ñ ÑеализаÑиÑми Ñ ÑÑиггеÑом и Ñ Ð¿Ñавилом не бÑдеÑ.
ТепеÑÑ Ð¼Ñ Ñ
оÑим избавиÑÑÑÑ Ð¾Ñ 2000 компÑÑÑеÑов, Ñ ÐºÐ¾ÑоÑÑÑ
hostname наÑинаеÑÑÑ Ñ old. ÐÑо можно ÑделаÑÑ Ð´Ð²ÑÐ¼Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ð¼Ð¸. ÐеÑваÑ:
DELETE FROM computer WHERE hostname >= 'old'
AND hostname < 'ole'ÐÑавило пÑеобÑазÑÐµÑ ÐµÑ Ð²:
DELETE FROM software WHERE computer.hostname >= 'old' AND computer.hostname < 'ole'
AND software.hostname = computer.hostname;Ñ Ð¿Ð»Ð°Ð½Ð¾Ð¼:
Hash Join
-> Seq Scan on software
-> Hash
-> Index Scan using comp_hostidx on computer
С дÑÑгой возможной командой:
DELETE FROM computer WHERE hostname ~ '^old';
Ð´Ð»Ñ Ð·Ð°Ð¿ÑоÑа, пÑеобÑазованного пÑавилом, полÑÑаеÑÑÑ ÑледÑÑÑий план:
Nestloop -> Index Scan using comp_hostidx on computer -> Index Scan using soft_hostidx on software
ÐÑо показÑваеÑ, ÑÑо планиÑовÑик не понимаеÑ, ÑÑо огÑаниÑение по hostname в computer можно Ñакже иÑполÑзоваÑÑ Ð´Ð»Ñ ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ индекÑÑ Ð² software, когда неÑколÑко ÑÑловий обÑединÑÑÑÑÑ Ñ Ð¿Ð¾Ð¼Ð¾ÑÑÑ AND, ÑÑо он ÑÑпеÑно Ð´ÐµÐ»Ð°ÐµÑ Ð´Ð»Ñ Ð²Ð°ÑианÑа ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ñ ÑегÑлÑÑнÑм вÑÑажением. ТÑÐ¸Ð³Ð³ÐµÑ Ð±ÑÐ´ÐµÑ Ð²ÑзÑваÑÑÑÑ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ из 2000 ÑдалÑемÑÑ
запиÑей о ÑÑаÑÑÑ
компÑÑÑеÑаÑ
, и ÑÑо пÑиведÑÑ Ðº Ð¾Ð´Ð½Ð¾Ð¼Ñ ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа в ÑаблиÑе computer и 2000 ÑканиÑованиÑм индекÑа в ÑаблиÑе software. РеализаÑÐ¸Ñ Ñ Ð¿Ñавилом Ð´ÐµÐ»Ð°ÐµÑ ÑÑо двÑÐ¼Ñ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ð¼Ð¸, пÑименÑÑÑими индекÑÑ. ÐÑÐ´ÐµÑ Ð»Ð¸ пÑавило бÑÑÑÑее пÑи поÑледоваÑелÑном ÑканиÑовании, завиÑÐ¸Ñ Ð¾Ñ Ð¾Ð±Ñего ÑазмеÑа ÑаблиÑÑ software. С дÑÑгой ÑÑоÑонÑ, вÑполнение 2000 команд из ÑÑиггеÑа ÑеÑез Ð¼ÐµÐ½ÐµÐ´Ð¶ÐµÑ SPI вÑÑ Ñавно займÑÑ Ð²ÑемÑ, даже еÑли вÑе блоки индекÑа вÑкоÑе окажÑÑÑÑ Ð² кеÑе.
РзавеÑÑение взглÑниÑе на ÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ:
DELETE FROM computer WHERE manufacturer = 'bim';
Ðна Ñакже Ð¼Ð¾Ð¶ÐµÑ Ð¿ÑивеÑÑи к ÑÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¼Ð½Ð¾Ð¶ÐµÑÑва ÑÑÑок из ÑаблиÑÑ computer. ÐоÑÑÐ¾Ð¼Ñ ÑÑÐ¸Ð³Ð³ÐµÑ Ñнова пÑопÑÑÑÐ¸Ñ ÑеÑез иÑполниÑÐµÐ»Ñ Ñакое же множеÑÑво команд. ÐÑавило же вÑдаÑÑ ÑледÑÑÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ:
DELETE FROM software WHERE computer.manufacturer = 'bim'
AND software.hostname = computer.hostname; Ðлан Ð´Ð»Ñ ÑÑой ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ñнова бÑÐ´ÐµÑ ÑодеÑжаÑÑ Ð²Ð»Ð¾Ð¶ÐµÐ½Ð½Ñй Ñикл по двÑм ÑканиÑованиÑм индекÑа, но на ÑÑÐ¾Ñ Ñаз Ñ Ð´ÑÑгим индекÑом ÑаблиÑÑ computer:
Nestloop -> Index Scan using comp_manufidx on computer -> Index Scan using soft_hostidx on software
Ðо вÑÐµÑ ÑÑÐ¸Ñ ÑлÑÑаÑÑ Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸ÑелÑнÑе ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð±ÑдÑÑ Ð±Ð¾Ð»ÐµÐµ-менее незавиÑимÑми Ð¾Ñ ÑиÑла заÑÑагиваемÑÑ ÑÑÑок.
Таким обÑазом, пÑавила бÑдÑÑ Ð·Ð½Ð°ÑиÑелÑно медленнее ÑÑиггеÑов, ÑолÑко еÑли Ð¸Ñ Ð´ÐµÐ¹ÑÑÐ²Ð¸Ñ Ð¿ÑиводÑÑ Ðº обÑÐ°Ð·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð±Ð¾Ð»ÑÑÐ¸Ñ Ð¸ Ð¿Ð»Ð¾Ñ Ð¾ ÑвÑзаннÑÑ Ñоединений, когда планиÑовÑик оказÑваеÑÑÑ Ð±ÐµÑÑилен.