56.1. ÐÐ°Ð·Ð¾Ð²Ð°Ñ ÑÑÑÑкÑÑÑа API Ð´Ð»Ñ Ð¸Ð½Ð´ÐµÐºÑов
ÐаждÑй индекÑнÑй меÑод доÑÑÑпа опиÑÑваеÑÑÑ ÑÑÑокой в ÑиÑÑемном каÑалоге pg_am. РзапиÑи pg_am ÑказÑваеÑÑÑ Ð¸Ð¼Ñ Ð¸ ÑÑнкÑиÑ-обÑабоÑÑик Ð´Ð»Ñ Ð¼ÐµÑода доÑÑÑпа. ÐÑи запиÑи могÑÑ ÑоздаваÑÑÑÑ Ð¸ ÑдалÑÑÑÑÑ ÐºÐ¾Ð¼Ð°Ð½Ð´Ð°Ð¼Ð¸ SQL CREATE ACCESS METHOD и DROP ACCESS METHOD.
ФÑнкÑиÑ-обÑабоÑÑик индекÑного меÑода доÑÑÑпа должна обÑÑвлÑÑÑÑÑ ÐºÐ°Ðº пÑинимаÑÑÐ°Ñ Ð¾Ð´Ð¸Ð½ аÑгÑÐ¼ÐµÐ½Ñ Ñипа internal и возвÑаÑаÑÑÐ°Ñ Ð¿ÑевдоÑип index_am_handler. ÐÑгÑÐ¼ÐµÐ½Ñ Ð² данном ÑлÑÑае ÑикÑивнÑй, и нÑжен ÑолÑко Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ ÑÑÑ ÑÑнкÑÐ¸Ñ Ð½ÐµÐ»ÑÐ·Ñ Ð±Ñло вÑзÑваÑÑ Ð½ÐµÐ¿Ð¾ÑÑедÑÑвенно из команд SQL. ÐозвÑаÑаÑÑ ÑÑа ÑÑнкÑÐ¸Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° ÑÑÑÑкÑÑÑÑ Ñипа IndexAmRoutine (в памÑÑи palloc), ÑодеÑжаÑÑÑ Ð²ÑÑ, ÑÑо нÑжно знаÑÑ ÐºÐ¾Ð´Ñ ÑдÑа, ÑÑÐ¾Ð±Ñ Ð¸ÑполÑзоваÑÑ ÑÑÐ¾Ñ Ð¼ÐµÑод доÑÑÑпа. СÑÑÑкÑÑÑа IndexAmRoutine, Ñакже назÑÐ²Ð°ÐµÐ¼Ð°Ñ ÑÑÑÑкÑÑÑой API меÑода доÑÑÑпа, ÑодеÑÐ¶Ð¸Ñ Ð¿Ð¾Ð»Ñ, задаÑÑие ÑазнообÑазнÑе пÑедопÑеделÑннÑе ÑвойÑÑва меÑода доÑÑÑпа, напÑимеÑ, поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð»Ð¸ он ÑоÑÑавнÑе индекÑÑ. ЧÑо более важно, она ÑодеÑÐ¶Ð¸Ñ ÑказаÑели на опоÑнÑе ÑÑнкÑии Ð´Ð»Ñ Ð¼ÐµÑода доÑÑÑпа. ÐÑо обÑÑнÑе ÑÑнкÑии на C и они не Ð²Ð¸Ð´Ð½Ñ Ð¸ не могÑÑ Ð±ÑÑÑ Ð²ÑÐ·Ð²Ð°Ð½Ñ Ð½Ð° ÑÑовне SQL. ÐпоÑнÑе ÑÑнкÑии опиÑÐ°Ð½Ñ Ð² Разделе 56.2.
СÑÑÑкÑÑÑа IndexAmRoutine опÑеделÑеÑÑÑ Ñак:
typedef struct IndexAmRoutine
{
NodeTag type;
/*
* ÐбÑее ÑиÑло ÑÑÑаÑегий (опеÑаÑоÑов), Ñ ÐºÐ¾ÑоÑÑми возможен поиÑк/пÑименение
* ÑÑого меÑода доÑÑÑпа (ÐÐ). ÐолÑ, еÑли Ñ ÑÑого ÐÐ Ð½ÐµÑ ÑикÑиÑованного набоÑа
* назнаÑеннÑÑ
ÑÑÑаÑегий.
*/
uint16 amstrategies;
/* обÑее ÑиÑло опоÑнÑÑ
ÑÑнкÑий, иÑполÑзÑемÑÑ
ÑÑим ÐÐ */
uint16 amsupport;
/* поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð»Ð¸ ÐÐ ÑпоÑÑдоÑивание (ORDER BY) знаÑений индекÑиÑованного ÑÑолбÑа? */
bool amcanorder;
/* поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð»Ð¸ ÐÐ ÑпоÑÑдоÑивание (ORDER BY) ÑезÑлÑÑаÑа опеÑаÑоÑа Ñ Ð¸Ð½Ð´ÐµÐºÑиÑованнÑм ÑÑолбÑом? */
bool amcanorderbyop;
/* поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð»Ð¸ ÐÐ ÑканиÑование в обÑаÑном напÑавлении? */
bool amcanbackward;
/* поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð»Ð¸ ÐÐ ÑникалÑнÑе индекÑÑ (UNIQUE)? */
bool amcanunique;
/* поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð»Ð¸ ÐРиндекÑÑ Ñ Ð½ÐµÑколÑкими ÑÑолбÑами? */
bool amcanmulticol;
/* ÑÑебÑеÑÑÑ Ð»Ð¸ Ð´Ð»Ñ ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ñ ÐРогÑаниÑение пеÑвого ÑÑолбÑа индекÑа? */
bool amoptionalkey;
/* воÑпÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð»Ð¸ ÐÐ ÑÑÐ»Ð¾Ð²Ð¸Ñ ScalarArrayOpExpr? */
bool amsearcharray;
/* воÑпÑÐ¸Ð½Ð¸Ð¼Ð°ÐµÑ Ð»Ð¸ ÐÐ ÑÑÐ»Ð¾Ð²Ð¸Ñ IS NULL/IS NOT NULL? */
bool amsearchnulls;
/* Ð¼Ð¾Ð¶ÐµÑ Ð»Ð¸ Ñип, Ñ
ÑанÑÑийÑÑ Ð² индекÑе, оÑлиÑаÑÑÑÑ Ð¾Ñ Ñипа ÑÑолбÑа? */
bool amstorage;
/* возможна ли клаÑÑеÑизаÑÐ¸Ñ Ð¿Ð¾ индекÑÑ ÑÑого Ñипа? */
bool amclusterable;
/* ÐРобÑабаÑÑÐ²Ð°ÐµÑ Ð¿ÑедикаÑнÑе блокиÑовки? */
bool ampredlocks;
/* поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð»Ð¸ ÐРпаÑаллелÑное ÑканиÑование? */
bool amcanparallel;
/* Ñип даннÑÑ
, Ñ
ÑанÑÑиÑ
ÑÑ Ð² индекÑе, либо InvalidOid, еÑли он пеÑеменнÑй */
Oid amkeytype;
/* поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð»Ð¸ ÐРвклÑÑÑннÑе ÑÑолбÑÑ, задаваемÑе в INCLUDE? */
bool amcaninclude;
/* инÑеÑÑейÑнÑе ÑÑнкÑии */
ambuild_function ambuild;
ambuildempty_function ambuildempty;
aminsert_function aminsert;
ambulkdelete_function ambulkdelete;
amvacuumcleanup_function amvacuumcleanup;
amcanreturn_function amcanreturn; /* Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ NULL */
amcostestimate_function amcostestimate;
amoptions_function amoptions;
amproperty_function amproperty; /* Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ NULL */
amvalidate_function amvalidate;
ambeginscan_function ambeginscan;
amrescan_function amrescan;
amgettuple_function amgettuple; /* Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ NULL */
amgetbitmap_function amgetbitmap; /* Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ NULL */
amendscan_function amendscan;
ammarkpos_function ammarkpos; /* Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ NULL */
amrestrpos_function amrestrpos; /* Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ NULL */
/* инÑеÑÑейÑнÑе ÑÑнкÑии Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑжки паÑаллелÑного ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ð¾ индекÑÑ */
amestimateparallelscan_function amestimateparallelscan; /* Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ NULL */
aminitparallelscan_function aminitparallelscan; /* Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ NULL */
amparallelrescan_function amparallelrescan; /* Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ NULL */
} IndexAmRoutine;ЧÑÐ¾Ð±Ñ Ð¸Ð½Ð´ÐµÐºÑнÑй меÑод доÑÑÑпа пÑименÑлÑÑ, необÑ
одимо Ñакже опÑеделиÑÑ ÑемейÑÑва опеÑаÑоÑов и клаÑÑÑ Ð¾Ð¿ÐµÑаÑоÑов в pg_opfamily, pg_opclass, pg_amop и pg_amproc. ÐÑи запиÑи позволÑÑÑ Ð¿Ð»Ð°Ð½Ð¸ÑовÑÐ¸ÐºÑ Ð¿Ð¾Ð½ÑÑÑ, Ð´Ð»Ñ ÐºÐ°ÐºÐ¸Ñ
видов ÑÑловий запÑоÑов могÑÑ Ð¿ÑименÑÑÑÑÑ Ð¸Ð½Ð´ÐµÐºÑÑ Ñ Ð´Ð°Ð½Ð½Ñми меÑодом доÑÑÑпа. СемейÑÑва и клаÑÑÑ Ð¾Ð¿ÐµÑаÑоÑов опиÑÑваÑÑÑÑ Ð² Разделе 35.14; ÑÑÐ¾Ñ Ð¼Ð°ÑеÑиал необÑ
одимо изÑÑиÑÑ, пÑежде Ñем ÑиÑаÑÑ Ð´Ð°Ð½Ð½ÑÑ Ð³Ð»Ð°Ð²Ñ.
ÐÑделÑнÑй Ð¸Ð½Ð´ÐµÐºÑ Ð¾Ð¿ÑеделÑеÑÑÑ Ð·Ð°Ð¿Ð¸ÑÑÑ Ð² pg_class, опиÑÑваÑÑей его как ÑизиÑеÑкое оÑноÑение, и запиÑÑÑ Ð² pg_index, пÑедÑÑавлÑÑÑей логиÑеÑкое ÑодеÑжание индекÑа â Ñо еÑÑÑ, Ð½Ð°Ð±Ð¾Ñ ÑÑолбÑов индекÑа и ÑеманÑиÑеÑкое знаÑение ÑÑиÑ
ÑÑолбÑов, ÑÑÑановленное ÑооÑвеÑÑÑвÑÑÑими клаÑÑами опеÑаÑоÑов. СÑолбÑами индекÑа (знаÑениÑми клÑÑа) могÑÑ Ð±ÑÑÑ Ð»Ð¸Ð±Ð¾ пÑоÑÑÑе ÑÑолбÑÑ Ð½Ð¸Ð¶ÐµÐ»ÐµÐ¶Ð°Ñей ÑаблиÑÑ, либо вÑÑажениÑ, вÑÑиÑлÑемÑе по ÑÑÑокам ÑаблиÑÑ. ÐÐ»Ñ Ð¸Ð½Ð´ÐµÐºÑного меÑода доÑÑÑпа обÑÑно не важно, оÑкÑда поÑÑÑпаÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ ÐºÐ»ÑÑа индекÑа (они вÑегда поÑÑÑпаÑÑ Ð² вÑÑиÑленном виде), но оÑÐµÐ½Ñ Ð²Ð°Ð¶Ð½Ð° инÑоÑмаÑÐ¸Ñ Ð¾ клаÑÑе опеÑаÑоÑов в каÑалоге pg_index. Ðбе ÑÑи запиÑи каÑалогов пÑедÑÑÐ°Ð²Ð»ÐµÐ½Ñ Ð² ÑоÑÑаве ÑÑÑÑкÑÑÑÑ Ð´Ð°Ð½Ð½ÑÑ
Relation, коÑоÑÐ°Ñ Ð¿ÐµÑедаÑÑÑÑ Ð²Ñем ÑÑнкÑиÑм, ÑеализÑÑÑим опеÑаÑии Ñ Ð¸Ð½Ð´ÐµÐºÑом.
С некоÑоÑÑми полÑми Ñлагов в IndexAmRoutine ÑвÑÐ·Ð°Ð½Ñ Ð½ÐµÐ¾ÑевиднÑе ÑледÑÑвиÑ. ТÑÐµÐ±Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑов Ñ amcanunique опиÑÐ°Ð½Ñ Ð² Разделе 56.5. Флаг amcanmulticol показÑваеÑ, ÑÑо меÑод доÑÑÑпа поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ ÑоÑÑавнÑе индекÑÑ, а amoptionalkey обознаÑаеÑ, ÑÑо меÑод позволÑÐµÑ Ð²ÑполниÑÑ ÑканиÑование пÑи оÑÑÑÑÑÑвии индекÑиÑÑемого огÑаниÑиваÑÑего ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð´Ð»Ñ Ð¿ÐµÑвого ÑÑолбÑа индекÑа. Ðогда amcanmulticol Ñавен false, amoptionalkey по ÑÑÑи говоÑиÑ, поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð»Ð¸ меÑод доÑÑÑпа полное ÑканиÑование по индекÑÑ Ð±ÐµÐ· огÑаниÑиваÑÑего ÑÑловиÑ. ÐеÑÐ¾Ð´Ñ Ð´Ð¾ÑÑÑпа, поддеÑживаÑÑие индекÑÑ Ð¿Ð¾ неÑколÑким ÑÑолбÑам, Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¿Ð¾Ð´Ð´ÐµÑживаÑÑ ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¿Ñи оÑÑÑÑÑÑвии огÑаниÑений лÑбÑÑ
или вÑеÑ
ÑÑолбÑов поÑле пеÑвого; однако они могÑÑ ÑÑебоваÑÑ Ð¿ÑиÑÑÑÑÑÐ²Ð¸Ñ ÐºÐ°ÐºÐ¾Ð³Ð¾-либо огÑаниÑÐµÐ½Ð¸Ñ Ð´Ð»Ñ Ð¿ÐµÑвого ÑÑолбÑа индекÑа, и ÑÑо ÑÑебование оÑмеÑаеÑÑÑ Ð·Ð½Ð°Ñением false Ñлага amoptionalkey. Ð amoptionalkey Ð´Ð»Ñ Ð¼ÐµÑода доÑÑÑпа Ð¼Ð¾Ð¶ÐµÑ ÑÑÑанавливаÑÑÑÑ false, напÑимеÑ, когда ÑÑÐ¾Ñ Ð¼ÐµÑод доÑÑÑпа не индекÑиÑÑÐµÑ Ð·Ð½Ð°ÑениÑ. Так как болÑÑинÑÑво индекÑиÑÑемÑÑ
опеÑаÑоÑов â ÑÑÑогие, и поÑÑÐ¾Ð¼Ñ Ð½Ðµ могÑÑ Ð²ÐµÑнÑÑÑ true Ð´Ð»Ñ Ð¾Ð¿ÐµÑандов NULL, на пеÑвÑй взглÑд кажеÑÑÑ Ð·Ð°Ð¼Ð°Ð½Ñивой Ð¸Ð´ÐµÑ Ð½Ðµ Ñ
ÑаниÑÑ Ð·Ð°Ð¿Ð¸Ñи индекÑа Ð´Ð»Ñ Ð·Ð½Ð°Ñений NULL: они вÑÑ Ñавно никак не могÑÑ Ð±ÑÑÑ Ð¿ÑоÑиÑÐ°Ð½Ñ Ð¿Ñи ÑканиÑовании индекÑа. Ðднако ÑÑÐ¾Ñ Ð°ÑгÑÐ¼ÐµÐ½Ñ Ð¾ÑпадаеÑ, когда пÑи ÑканиÑовании индекÑа вовÑе оÑÑÑÑÑÑвÑÐµÑ Ð¾Ð³ÑаниÑение данного ÑÑолбÑа индекÑа. Ðа пÑакÑике ÑÑо ознаÑаеÑ, ÑÑо индекÑÑ Ñ ÑÑÑановленнÑм Ñлагом amoptionalkey Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¸Ð½Ð´ÐµÐºÑиÑоваÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ NULL, Ñак как планиÑовÑик Ð¼Ð¾Ð¶ÐµÑ ÑклониÑÑÑÑ Ðº иÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ ÑÑого индекÑа вообÑе без клÑÑей. С ÑÑим ÑвÑзано еÑÑ Ð¾Ð´Ð½Ð¾ огÑаниÑение â индекÑнÑй меÑод доÑÑÑпа, поддеÑживаÑÑий ÑоÑÑавнÑе индекÑÑ, должен поддеÑживаÑÑ Ð¸Ð½Ð´ÐµÐºÑиÑование знаÑений NULL в ÑÑолбÑаÑ
поÑле пеÑвого, Ñак как планиÑовÑик бÑÐ´ÐµÑ Ð¿Ð¾Ð»Ð°Ð³Ð°ÑÑ, ÑÑо Ð¸Ð½Ð´ÐµÐºÑ Ð¼Ð¾Ð¶Ð½Ð¾ пÑименÑÑÑ Ð´Ð»Ñ Ð·Ð°Ð¿ÑоÑов, в коÑоÑÑÑ
ÑÑи ÑÑолбÑÑ Ð½Ðµ огÑаниÑиваÑÑÑÑ. ÐапÑимеÑ, ÑаÑÑмоÑÑим Ð¸Ð½Ð´ÐµÐºÑ Ð¿Ð¾ (a,b) и запÑÐ¾Ñ Ñ Ð¾Ð³ÑаниÑением WHERE a = 4. СиÑÑема бÑÐ´ÐµÑ Ð¿Ð¾Ð»Ð°Ð³Ð°ÑÑ, ÑÑо по ÑÑÐ¾Ð¼Ñ Ð¸Ð½Ð´ÐµÐºÑÑ Ð¼Ð¾Ð¶Ð½Ð¾ пÑоÑканиÑоваÑÑ ÑÑÑоки Ñ a = 4, но ÑÑо бÑÐ´ÐµÑ Ð½ÐµÐ²ÐµÑно, еÑли Ð¸Ð½Ð´ÐµÐºÑ Ð¸ÑклÑÑÐ¸Ñ ÑÑÑоки, в коÑоÑÑÑ
b â NULL. Ðднако ÑÑÐ¾Ñ Ð¸Ð½Ð´ÐµÐºÑ Ð²Ð¿Ð¾Ð»Ð½Ðµ Ð¼Ð¾Ð¶ÐµÑ Ð¸ÑклÑÑиÑÑ ÑÑÑоки, в коÑоÑÑÑ
пеÑвÑй ÑÑÐ¾Ð»Ð±ÐµÑ ÑодеÑÐ¶Ð¸Ñ NULL. ÐеÑод индекÑа, коÑоÑÑй индекÑиÑÑÐµÑ Ð·Ð½Ð°ÑÐµÐ½Ð¸Ñ NULL, Ð¼Ð¾Ð¶ÐµÑ Ñакже ÑÑÑановиÑÑ Ñлаг amsearchnulls, оÑмеÑив Ñем ÑамÑм, ÑÑо он поддеÑÐ¶Ð¸Ð²Ð°ÐµÑ Ð² каÑеÑÑве ÑÑловий поиÑка IS NULL и IS NOT NULL.