34.6. ÐаÑегоÑии изменÑивоÑÑи ÑÑнкÑий
ÐÐ»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑнкÑии опÑеделÑеÑÑÑ Ñ
аÑакÑеÑиÑÑика изменÑивоÑÑи, Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ñми ваÑианÑами: VOLATILE, STABLE и IMMUTABLE. ÐÑли ÑÑа Ñ
аÑакÑеÑиÑÑика не задаÑÑÑÑ Ñвно в команде CREATE FUNCTION, по ÑмолÑÐ°Ð½Ð¸Ñ Ð¿Ð¾Ð´ÑазÑмеваеÑÑÑ VOLATILE. ÐаÑегоÑÐ¸Ñ Ð¸Ð·Ð¼ÐµÐ½ÑивоÑÑи пÑедÑÑавлÑÐµÑ Ñобой обеÑание некоÑоÑого Ð¿Ð¾Ð²ÐµÐ´ÐµÐ½Ð¸Ñ ÑÑнкÑии Ð´Ð»Ñ Ð¾Ð¿ÑимизаÑоÑа:
ÐзменÑÐ¸Ð²Ð°Ñ ÑÑнкÑÐ¸Ñ (
VOLATILE) Ð¼Ð¾Ð¶ÐµÑ Ð´ÐµÐ»Ð°ÑÑ Ð²ÑÑ, ÑÑо Ñгодно, в Ñом ÑиÑле, модиÑиÑиÑоваÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ . Ðна Ð¼Ð¾Ð¶ÐµÑ Ð²Ð¾Ð·Ð²ÑаÑаÑÑ ÑазлиÑнÑе ÑезÑлÑÑаÑÑ Ð¿Ñи неÑколÑÐºÐ¸Ñ Ð²ÑÐ·Ð¾Ð²Ð°Ñ Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñми аÑгÑменÑами. ÐпÑимизаÑÐ¾Ñ Ð½Ðµ Ð´ÐµÐ»Ð°ÐµÑ Ð½Ð¸ÐºÐ°ÐºÐ¸Ñ Ð¿Ñедположений о поведении ÑÐ°ÐºÐ¸Ñ ÑÑнкÑий. РзапÑоÑе, иÑполÑзÑÑÑем изменÑивÑÑ ÑÑнкÑиÑ, она бÑÐ´ÐµÑ Ð²ÑÑиÑлÑÑÑÑÑ Ð·Ð°Ð½Ð¾Ð²Ð¾ Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки, когда поÑÑебÑеÑÑÑ ÐµÑ ÑезÑлÑÑаÑ.СÑабилÑÐ½Ð°Ñ ÑÑнкÑÐ¸Ñ (
STABLE) не Ð¼Ð¾Ð¶ÐµÑ Ð¼Ð¾Ð´Ð¸ÑиÑиÑоваÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ Ð¸ гаÑанÑиÑованно возвÑаÑÐ°ÐµÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñй ÑезÑлÑÑаÑ, полÑÑÐ°Ñ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñе аÑгÑменÑÑ, Ð´Ð»Ñ Ð²ÑÐµÑ ÑÑÑок в одном опеÑаÑоÑе. ÐÑа Ñ Ð°ÑакÑеÑиÑÑика позволÑÐµÑ Ð¾Ð¿ÑимизаÑоÑÑ Ð·Ð°Ð¼ÐµÐ½Ð¸ÑÑ Ð¼Ð½Ð¾Ð¶ÐµÑÑво вÑзовов ÑÑой ÑÑнкÑии одним. Ð ÑаÑÑноÑÑи, вÑÑажение, ÑодеÑжаÑее ÑакÑÑ ÑÑнкÑиÑ, можно безопаÑно иÑполÑзоваÑÑ Ð² ÑÑловии поиÑка по индекÑÑ. (Так как пÑи поиÑке по индекÑÑ Ñелевое знаÑение вÑÑиÑлÑеÑÑÑ ÑолÑко один Ñаз, а не Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки, иÑполÑзоваÑÑ ÑÑнкÑÐ¸Ñ Ñ Ñ Ð°ÑакÑеÑиÑÑикойVOLATILEв ÑÑловии поиÑка по индекÑÑ Ð½ÐµÐ»ÑзÑ.)ÐоÑÑоÑÐ½Ð½Ð°Ñ ÑÑнкÑÐ¸Ñ (
IMMUTABLE) не Ð¼Ð¾Ð¶ÐµÑ Ð¼Ð¾Ð´Ð¸ÑиÑиÑоваÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ Ð¸ гаÑанÑиÑованно вÑегда возвÑаÑÐ°ÐµÑ Ð¾Ð´Ð¸Ð½Ð°ÐºÐ¾Ð²Ñе ÑезÑлÑÑаÑÑ Ð´Ð»Ñ Ð¾Ð´Ð½Ð¸Ñ Ð¸ ÑÐµÑ Ð¶Ðµ аÑгÑменÑов. ÐÑа Ñ Ð°ÑакÑеÑиÑÑика позволÑÐµÑ Ð¾Ð¿ÑимизаÑоÑÑ Ð¿ÑедваÑиÑелÑно вÑÑиÑлиÑÑ ÑÑнкÑиÑ, когда она вÑзÑваеÑÑÑ Ð² запÑоÑе Ñ Ð¿Ð¾ÑÑоÑннÑми аÑгÑменÑами. ÐапÑимеÑ, запÑÐ¾Ñ Ð²Ð¸Ð´Ð°SELECT ... WHERE x = 2 + 2можно ÑпÑоÑÑиÑÑ Ð´Ð¾SELECT ... WHERE x = 4, Ñак как нижележаÑÐ°Ñ ÑÑнкÑÐ¸Ñ Ð¾Ð¿ÐµÑаÑоÑа ÑÐ»Ð¾Ð¶ÐµÐ½Ð¸Ñ Ð¿Ð¾Ð¼ÐµÑена какIMMUTABLE.
ÐÐ»Ñ Ð½Ð°Ð¸Ð»ÑÑÑÐ¸Ñ ÑезÑлÑÑаÑов опÑимизаÑии, ÑÑнкÑии ÑледÑÐµÑ Ð½Ð°Ð·Ð½Ð°ÑаÑÑ ÑамÑÑ ÑÑÑогÑÑ Ñ Ð°ÑакÑеÑиÑÑÐ¸ÐºÑ Ð¸Ð·Ð¼ÐµÐ½ÑивоÑÑи, коÑоÑой она ÑооÑвеÑÑÑвÑеÑ.
ÐÑÐ±Ð°Ñ ÑÑнкÑÐ¸Ñ Ñ Ð¿Ð¾Ð±Ð¾ÑнÑми ÑÑÑекÑами должна бÑÑÑ Ð¿Ð¾Ð¼ÐµÑена как VOLATILE, ÑÑÐ¾Ð±Ñ Ð¾Ð±ÑаÑÐµÐ½Ð¸Ñ Ðº ней не иÑклÑÑалиÑÑ Ð¿Ñи опÑимизаÑии. Ðаже еÑли ÑÑнкÑÐ¸Ñ Ð½Ðµ Ð¸Ð¼ÐµÐµÑ Ð¿Ð¾Ð±Ð¾ÑнÑÑ
ÑÑÑекÑов, ÐµÑ Ð½Ñжно помеÑиÑÑ ÐºÐ°Ðº VOLATILE, еÑли ÐµÑ Ð·Ð½Ð°Ñение Ð¼Ð¾Ð¶ÐµÑ Ð¼ÐµÐ½ÑÑÑÑÑ Ð¿Ñи вÑполнении одного запÑоÑа; ÑÐ°ÐºÐ¾Ð²Ñ ÑÑнкÑии random(), currval() и timeofday().
ÐÑÑгой важнÑй пÑÐ¸Ð¼ÐµÑ Ð¿ÑедÑÑавлÑÐµÑ ÑемейÑÑво ÑÑнкÑий current_timestamp, коÑоÑÑе имеÑÑ Ñ
аÑакÑеÑиÑÑÐ¸ÐºÑ STABLE, поÑÐ¾Ð¼Ñ ÑÑо иÑ
знаÑÐµÐ½Ð¸Ñ Ð½Ðµ менÑÑÑÑÑ Ð² ÑамкаÑ
одной ÑÑанзакÑии.
ХаÑакÑеÑиÑÑики STABLE и IMMUTABLE мало ÑазлиÑаÑÑÑÑ, когда ÑеÑÑ Ð¸Ð´ÑÑ Ð¾ пÑоÑÑÑÑ
инÑеÑакÑивнÑÑ
запÑоÑаÑ
, коÑоÑÑе планиÑÑÑÑÑÑ Ð¸ ÑÑÐ°Ð·Ñ Ð¶Ðµ вÑполнÑÑÑÑÑ; не Ð¸Ð¼ÐµÐµÑ Ð±Ð¾Ð»ÑÑого знаÑениÑ, бÑÐ´ÐµÑ Ð»Ð¸ ÑÑнкÑÐ¸Ñ Ð²Ñполнена однокÑаÑно на ÑÑапе планиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð»Ð¸ в наÑале вÑполнениÑ. СÑÑеÑÑвенное ÑазлиÑие пÑоÑвлÑеÑÑÑ, когда план ÑоÑ
ÑанÑеÑÑÑ Ð¸ многокÑаÑно иÑполÑзÑеÑÑÑ Ð¿Ð¾Ð·Ð¶Ðµ. ÐÑли ÑÑнкÑÐ¸Ñ Ð¿Ð¾Ð¼ÐµÑена как IMMUTABLE, Ñогда как на Ñамом деле она не ÑвлÑеÑÑÑ Ð¿Ð¾ÑÑоÑнной, она Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ñведена к конÑÑанÑе во вÑÐµÐ¼Ñ Ð¿Ð»Ð°Ð½Ð¸ÑованиÑ, Ñак ÑÑо пÑи поÑледÑÑÑиÑ
вÑполнениÑÑ
плана вмеÑÑо Ð½ÐµÑ Ð±ÑÐ´ÐµÑ Ð¸ÑполÑзоваÑÑÑÑ Ð½ÐµÐ°ÐºÑÑалÑное знаÑение. ÐÑо опаÑно пÑи иÑполÑзовании подгоÑовленнÑÑ
опеÑаÑоÑов или ÑзÑков ÑÑнкÑий, кеÑиÑÑÑÑиÑ
Ð¿Ð»Ð°Ð½Ñ (напÑимеÑ, PL/pgSQL).
У ÑÑнкÑий, напиÑаннÑÑ
на SQL или на лÑбом дÑÑгом ÑÑандаÑÑном пÑоÑедÑÑном ÑзÑке, еÑÑÑ ÐµÑÑ Ð¾Ð´Ð½Ð¾ важное ÑвойÑÑво, опÑеделÑемое Ñ
аÑакÑеÑиÑÑикой изменÑивоÑÑи, а именно видимоÑÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹, пÑоизведÑннÑÑ
командой SQL, коÑоÑÐ°Ñ Ð²ÑзÑÐ²Ð°ÐµÑ ÑÑÑ ÑÑнкÑиÑ. ФÑнкÑÐ¸Ñ VOLATILE бÑÐ´ÐµÑ Ð²Ð¸Ð´ÐµÑÑ Ñакие изменениÑ, Ñогда как STABLE и IMMUTABLE â неÑ. ÐÑо поведение ÑеализÑеÑÑÑ Ð¿Ð¾ÑÑедÑÑвом Ñнимков в MVCC (Ñм. ÐлавÑ 13): STABLE и IMMUTABLE иÑполÑзÑÑÑ Ñнимок, полÑÑеннÑй в наÑале вÑзÑваÑÑего запÑоÑа, Ñогда как ÑÑнкÑии VOLATILE полÑÑаÑÑ Ñвежий Ñнимок в наÑале каждого запÑоÑа, коÑоÑÑй они вÑполнÑÑÑ.
ÐÑимеÑание
ФÑнкÑии, напиÑаннÑе на C, могÑÑ ÑабоÑаÑÑ Ñо Ñнимками как Ñгодно, но обÑÑно лÑÑÑе ÑделаÑÑ Ñак, ÑÑÐ¾Ð±Ñ Ð¾Ð½Ð¸ дейÑÑвовали аналогиÑно.
ÐÑледÑÑвие Ñакой оÑганизаÑии ÑабоÑÑ Ñо Ñнимками, ÑÑнкÑиÑ, ÑодеÑжаÑÑÑ ÑолÑко ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SELECT, можно безопаÑно помеÑиÑÑ ÐºÐ°Ðº STABLE, даже еÑли она вÑбиÑÐ°ÐµÑ Ð´Ð°Ð½Ð½Ñе из ÑаблиÑ, коÑоÑÑе могÑÑ Ð±ÑÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ñ Ð¿Ð°ÑаллелÑнÑми запÑоÑами. Postgres Pro вÑÐ¿Ð¾Ð»Ð½Ð¸Ñ Ð²Ñе ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ Ð² ÑÑнкÑии STABLE Ñо Ñнимком, полÑÑеннÑм Ð´Ð»Ñ Ð²ÑзÑваÑÑего запÑоÑа, Ñак ÑÑо они бÑдÑÑ Ð²Ð¸Ð´ÐµÑÑ Ð¾Ð´Ð½Ð¾ пÑедÑÑавление Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
на пÑоÑÑжении вÑего запÑоÑа.
То же Ñамое поведение Ñо Ñнимками ÑаÑпÑоÑÑÑанÑеÑÑÑ Ð½Ð° ÐºÐ¾Ð¼Ð°Ð½Ð´Ñ SELECT в ÑÑнкÑиÑÑ
IMMUTABLE. ÐообÑе в ÑÑнкÑиÑÑ
IMMUTABLE обÑÑно неÑазÑмно вÑбиÑаÑÑ Ð´Ð°Ð½Ð½Ñе из ÑаблиÑ, Ñак как «поÑÑоÑнÑÑво» ÑÑнкÑии бÑÐ´ÐµÑ Ð½Ð°ÑÑÑено, еÑли ÑодеÑжимое ÑÐ°Ð±Ð»Ð¸Ñ Ð¸Ð·Ð¼ÐµÐ½Ð¸ÑÑÑ. Ðднако Postgres Pro не пÑинÑÐ¶Ð´Ð°ÐµÑ Ð²Ð°Ñ Ñвно оÑказаÑÑÑÑ Ð¾Ñ ÑÑого.
Ðдна из ÑаÑпÑоÑÑÑанÑннÑÑ
оÑибок â помеÑаÑÑ ÑÑнкÑÐ¸Ñ ÐºÐ°Ðº IMMUTABLE, пÑи Ñом, ÑÑо ÐµÑ ÑезÑлÑÑаÑÑ Ð·Ð°Ð²Ð¸ÑÑÑ Ð¾Ñ Ð¿Ð°ÑамеÑÑа конÑигÑÑаÑии. ÐапÑимеÑ, ÑÑнкÑиÑ, ÑабоÑаÑÑÐ°Ñ Ñ Ð²Ñеменем, Ð¼Ð¾Ð¶ÐµÑ Ð²ÑдаваÑÑ ÑезÑлÑÑаÑÑ, завиÑÑÑие Ð¾Ñ Ð¿Ð°ÑамеÑÑа TimeZone. ÐÐ»Ñ Ð½Ð°Ð´ÑжноÑÑи Ñакие ÑÑнкÑии ÑледÑÐµÑ Ð¿Ð¾Ð¼ÐµÑаÑÑ ÐºÐ°Ðº STABLE.
ÐÑимеÑание
Postgres Pro ÑÑебÑеÑ, ÑÑÐ¾Ð±Ñ ÑÑнкÑии STABLE и IMMUTABLE не ÑодеÑжали SQL-команд, кÑоме SELECT, Ð´Ð»Ñ Ð¿ÑедоÑвÑаÑÐµÐ½Ð¸Ñ Ð¼Ð¾Ð´Ð¸ÑикаÑии даннÑÑ
. (ÐÑо не ÑовÑем непÑобиваемое огÑаниÑение, Ñак как ÑÑи ÑÑнкÑии вÑÑ Ð¶Ðµ могÑÑ Ð²ÑзÑваÑÑ ÑÑнкÑии VOLATILE, ÑпоÑобнÑе модиÑиÑиÑоваÑÑ Ð±Ð°Ð·Ñ Ð´Ð°Ð½Ð½ÑÑ
. ÐÑли Ð²Ñ ÑеализÑеÑе ÑакÑÑ ÑÑ
емÑ, Ð²Ñ ÑвидиÑе, ÑÑо ÑÑнкÑÐ¸Ñ STABLE и IMMUTABLE не замеÑÐ°ÐµÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ð¹ в базе даннÑÑ
, пÑоизведÑннÑÑ
вÑзванной ÑÑнкÑией, Ñак как они не пÑоÑвлÑÑÑÑÑ Ð² ÐµÑ Ñнимке даннÑÑ
.)