61.6. ФÑнкÑии оÑенки ÑÑоимоÑÑи индекÑа #
ФÑнкÑии amcostestimate даÑÑÑÑ Ð¸Ð½ÑоÑмаÑиÑ, опиÑÑваÑÑÐ°Ñ Ð²Ð¾Ð·Ð¼Ð¾Ð¶Ð½Ð¾Ðµ ÑканиÑование индекÑа, вклÑÑÐ°Ñ ÑпиÑки пÑедложений WHERE и ORDER BY, коÑоÑÑе бÑли вÑбÑÐ°Ð½Ñ ÐºÐ°Ðº пÑименимÑе Ñ Ð´Ð°Ð½Ð½Ñм индекÑом. Ðна должна веÑнÑÑÑ Ð¾Ñенки ÑÑоимоÑÑи обÑаÑÐµÐ½Ð¸Ñ Ðº индекÑÑ Ð¸ избиÑаÑелÑноÑÑÑ Ð¿Ñедложений WHERE (Ñо еÑÑÑ, пÑоÑÐµÐ½Ñ ÑÑÑок оÑновной ÑаблиÑÑ, коÑоÑÑй бÑÐ´ÐµÑ Ð¿Ð¾Ð»ÑÑен в Ñ
оде ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа). ÐÐ»Ñ Ð¿ÑоÑÑÑÑ
ÑлÑÑаев поÑÑи вÑÑ ÑабоÑÑ Ð¾ÑенÑика ÑÑоимоÑÑи можно пÑоизвеÑÑи, вÑзÑÐ²Ð°Ñ ÑÑандаÑÑнÑе пÑоÑедÑÑÑ Ð¾Ð¿ÑимизаÑоÑа; ÑмÑÑл ÑÑÑеÑÑÐ²Ð¾Ð²Ð°Ð½Ð¸Ñ ÑÑнкÑии amcostestimate в Ñом, ÑÑÐ¾Ð±Ñ Ð¸Ð½Ð´ÐµÐºÑнÑе меÑÐ¾Ð´Ñ Ð´Ð¾ÑÑÑпа могли поделиÑÑÑÑ Ð·Ð½Ð°Ð½Ð¸Ñми, ÑпеÑиÑиÑнÑми Ð´Ð»Ñ Ñипа индекÑа, когда ÑÑо Ð¼Ð¾Ð¶ÐµÑ Ð¿Ð¾Ð¼Ð¾ÑÑ ÑлÑÑÑиÑÑ ÑÑандаÑÑнÑе оÑенки.
ÐÐ°Ð¶Ð´Ð°Ñ ÑÑнкÑÐ¸Ñ amcostestimate должна имеÑÑ ÑакÑÑ ÑигнаÑÑÑÑ:
void
amcostestimate (PlannerInfo *root,
IndexPath *path,
double loop_count,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity,
double *indexCorrelation,
double *indexPages);ÐеÑвÑе ÑÑи паÑамеÑÑа пеÑедаÑÑ Ð²Ñ Ð¾Ð´Ð½Ñе знаÑениÑ:
rootÐнÑоÑмаÑÐ¸Ñ Ð¿Ð»Ð°Ð½Ð¸ÑовÑика о вÑполнÑемом запÑоÑе.
pathРаÑÑмаÑÑиваемÑй пÑÑÑ Ð´Ð¾ÑÑÑпа к индекÑÑ. РнÑм дейÑÑвиÑелÑÐ½Ñ Ð²Ñе полÑ, кÑоме знаÑений ÑÑоимоÑÑи и избиÑаÑелÑноÑÑи.
loop_countЧиÑло повÑоÑений ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа, коÑоÑое должно пÑинимаÑÑÑÑ Ð²Ð¾ внимание пÑи оÑенке ÑÑоимоÑÑи. ÐбÑÑно оно бÑÐ´ÐµÑ Ð±Ð¾Ð»ÑÑе одного, когда пÑи Ñоединении Ñо вложеннÑм Ñиклом планиÑÑеÑÑÑ Ð¿Ð°ÑамеÑÑизованное ÑканиÑование. ÐамеÑÑÑе, ÑÑо оÑенки ÑÑоимоÑÑи Ñем не менее Ð´Ð¾Ð»Ð¶Ð½Ñ ÑаÑÑÑиÑÑваÑÑÑÑ Ð´Ð»Ñ Ð²Ñего одного ÑканиÑованиÑ; болÑÑие знаÑениÑ
loop_countлиÑÑ Ð´Ð°ÑÑ Ð¾ÑÐ½Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¿ÑедположиÑÑ, ÑÑо пÑи многокÑаÑном ÑканиÑовании положиÑелÑное влиÑние Ð¼Ð¾Ð¶ÐµÑ Ð¾ÐºÐ°Ð·Ð°ÑÑ ÐºÐµÑиÑование.
ÐоÑледние пÑÑÑ Ð¿Ð°ÑамеÑÑов â ÑказаÑели на пеÑеменнÑе Ð´Ð»Ñ Ð²ÑÑ Ð¾Ð´Ð½ÑÑ Ð·Ð½Ð°Ñений:
*indexStartupCostСÑоимоÑÑÑ Ð²ÑÐ¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ Ð·Ð°Ð¿ÑÑка индекÑа
*indexTotalCostÐбÑÐ°Ñ ÑÑоимоÑÑÑ Ð¸ÑполÑÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа
*indexSelectivityÐзбиÑаÑелÑноÑÑÑ Ð¸Ð½Ð´ÐµÐºÑа
*indexCorrelationÐоÑÑÑиÑÐ¸ÐµÐ½Ñ ÐºÐ¾ÑÑелÑÑии Ð¼ÐµÐ¶Ð´Ñ Ð¿Ð¾ÑÑдком ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа и поÑÑдком запиÑей в нижележаÑей ÑаблиÑе
*indexPagesÐолиÑеÑÑво ÑÑÑÐ°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа на ÑÑовне лиÑÑÑев
ÐамеÑÑÑе, ÑÑо ÑÑнкÑии оÑенки ÑÑоимоÑÑи Ð´Ð¾Ð»Ð¶Ð½Ñ ÑазÑабаÑÑваÑÑÑÑ Ð½Ð° C, а не на SQL или дÑÑгом доÑÑÑпном пÑоÑедÑÑном ÑзÑке, Ñак как они Ð´Ð¾Ð»Ð¶Ð½Ñ Ð¾Ð±ÑаÑаÑÑÑÑ Ðº внÑÑÑенним ÑÑÑÑкÑÑÑам даннÑм планиÑовÑика/опÑимизаÑоÑа.
СÑоимоÑÑи обÑаÑÐµÐ½Ð¸Ñ Ðº индекÑÑ ÑледÑÐµÑ Ð²ÑÑиÑлÑÑÑ Ñ Ð¸ÑполÑзованием паÑамеÑÑов: поÑледоваÑелÑÐ½Ð°Ñ Ð²ÑбоÑка диÑкового блока Ð¸Ð¼ÐµÐµÑ ÑÑоимоÑÑÑ seq_page_cost, непоÑледоваÑелÑÐ½Ð°Ñ Ð²ÑбоÑка â random_page_cost, а ÑÑоимоÑÑÑ Ð¾Ð±ÑабоÑки одной ÑÑÑоки индекÑа обÑÑно пÑинимаеÑÑÑ Ñавной cpu_index_tuple_cost. ÐÑоме Ñого, за каждÑй опеÑаÑÐ¾Ñ ÑÑавнениÑ, вÑзÑваемÑй пÑи обÑабоÑке индекÑа, должна взимаÑÑÑÑ Ñена cpu_operator_cost (оÑобенно за вÑÑиÑление ÑобÑÑвенно ÑÑловий индекÑа).
«СÑоимоÑÑÑ Ð·Ð°Ð¿ÑÑка» ÑоÑÑавлÑÐµÑ ÑаÑÑÑ Ð¾Ð±Ñей ÑÑоимоÑÑи ÑканиÑованиÑ, коÑоÑÐ°Ñ Ð´Ð¾Ð»Ð¶Ð½Ð° бÑÑÑ Ð¿Ð¾ÑÑаÑена, пÑежде Ñем можно бÑÐ´ÐµÑ Ð½Ð°ÑаÑÑ ÑÑение пеÑвой ÑÑÑоки. ÐÐ»Ñ Ð±Ð¾Ð»ÑÑинÑÑва индекÑов она Ð¼Ð¾Ð¶ÐµÑ ÑÑиÑаÑÑÑÑ Ð½Ñлевой, но Ð´Ð»Ñ Ñипов индекÑов Ñ Ð²ÑÑокими заÑÑаÑами на запÑÑк она Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð±Ð¾Ð»ÑÑе нÑлÑ.
ÐнаÑение в indexSelectivity должно показÑваÑÑ, какой пÑоÑÐµÐ½Ñ ÑÑÑок оÑновной ÑаблиÑÑ Ð¾Ð¶Ð¸Ð´Ð°ÐµÑÑÑ Ð¿Ð¾Ð»ÑÑиÑÑ Ð¿Ñи ÑканиÑовании ÑаблиÑÑ. Ð ÑлÑÑае неÑоÑного запÑоÑа ÑÑо обÑÑно бÑÐ´ÐµÑ Ð±Ð¾Ð»ÑÑе пÑоÑенÑа ÑÑÑок, дейÑÑвиÑелÑно ÑдовлеÑвоÑÑÑÑиÑ
заданнÑм огÑаниÑиваÑÑим ÑÑловиÑм.
Ð indexCorrelation запиÑÑваеÑÑÑ ÐºÐ¾ÑÑелÑÑÐ¸Ñ (в диапазоне Ð¾Ñ -1.0 до 1.0) Ð¼ÐµÐ¶Ð´Ñ Ð¿Ð¾ÑÑдком запиÑей в индекÑе и в ÑаблиÑе. ÐÑо знаÑение бÑÐ´ÐµÑ ÐºÐ¾ÑÑекÑиÑоваÑÑ Ð¾ÑÐµÐ½ÐºÑ ÑÑоимоÑÑи вÑбоÑки ÑÑÑок из оÑновной ÑаблиÑÑ.
Ð indexPages запиÑÑваеÑÑÑ ÑиÑло ÑÑÑÐ°Ð½Ð¸Ñ Ð½Ð° ÑÑовне лиÑÑÑев. ÐÑо Ð¿Ð¾Ð¼Ð¾Ð³Ð°ÐµÑ Ð²ÑбÑаÑÑ ÑиÑло иÑполниÑелей Ð´Ð»Ñ Ð¿Ð°ÑаллелÑного ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа.
Ðогда loop_count болÑÑе нÑлÑ, возвÑаÑаÑÑÑÑ Ð´Ð¾Ð»Ð¶Ð½Ñ ÑÑедние знаÑениÑ, ожидаемÑе Ð´Ð»Ñ Ð¾Ð´Ð½Ð¾Ð³Ð¾ ÑканиÑÐ¾Ð²Ð°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа.
ÐÑенка ÑÑоимоÑÑи
ТипиÑÐ½Ð°Ñ Ð¿ÑоÑедÑÑа оÑенки вÑглÑÐ´Ð¸Ñ ÑледÑÑÑим обÑазом:
РаÑÑÑиÑаÑÑ Ð¸ веÑнÑÑÑ Ð¿ÑоÑÐµÐ½Ñ ÑÑÑок ÑодиÑелÑÑкой ÑаблиÑÑ, коÑоÑÑе бÑдÑÑ Ð¿Ð¾ÑеÑÐµÐ½Ñ Ð¿Ñи заданнÑÑ Ð¾Ð³ÑаниÑиваÑÑÐ¸Ñ ÑÑловиÑÑ . РоÑÑÑÑÑÑвие ÐºÐ°ÐºÐ¸Ñ -либо знаний, ÑпеÑиÑиÑнÑÑ Ð´Ð»Ñ Ñипа индекÑа, иÑполÑзоваÑÑ ÑÑандаÑÑнÑÑ ÑÑнкÑÐ¸Ñ Ð¾Ð¿ÑимизаÑоÑа
clauselist_selectivity():*indexSelectivity = clauselist_selectivity(root, path->indexquals, path->indexinfo->rel->relid, JOIN_INNER, NULL);ÐÑениÑÑ ÑиÑло ÑÑÑок индекÑа, коÑоÑÑе бÑдÑÑ Ð¿Ð¾ÑеÑÐµÐ½Ñ Ð¿Ñи ÑканиÑовании. ÐÐ»Ñ Ð¼Ð½Ð¾Ð³Ð¸Ñ Ñипов индекÑов ÑÑо бÑÐ´ÐµÑ Ð¿Ñоизведение
indexSelectivityи ÑиÑла ÑÑÑок в индекÑе, но оно Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¸ болÑÑе. (ÐамеÑÑÑе, ÑÑо ÑÐ°Ð·Ð¼ÐµÑ Ð¸Ð½Ð´ÐµÐºÑа в ÑÑÑаниÑÐ°Ñ Ð¸ ÑÑÑÐ¾ÐºÐ°Ñ Ð¼Ð¾Ð¶Ð½Ð¾ ÑзнаÑÑ Ð¸Ð· ÑÑÑÑкÑÑÑÑpath->indexinfo.)РаÑÑÑиÑаÑÑ ÑиÑло ÑÑÑÐ°Ð½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа, коÑоÑÑе бÑдÑÑ Ð¿Ð¾Ð»ÑÑÐµÐ½Ñ Ð¿Ñи ÑканиÑовании. ÐÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿ÑоÑÑо пÑоизведение
indexSelectivityи ÑазмеÑа индекÑа в ÑÑÑаниÑÐ°Ñ .ÐÑÑиÑлиÑÑ ÑÑоимоÑÑÑ Ð¾Ð±ÑаÑÐµÐ½Ð¸Ñ Ðº индекÑÑ. УнивеÑÑалÑнÑй оÑенÑик Ð¼Ð¾Ð¶ÐµÑ ÑделаÑÑ ÑледÑÑÑее:
/* * ÐообÑе пÑедполагаеÑÑÑ, ÑÑо ÑÑÑаниÑÑ Ð¸Ð½Ð´ÐµÐºÑа бÑдÑÑ ÑÑиÑÑваÑÑÑÑ Ð¿Ð¾ÑледоваÑелÑно, * Ñак ÑÑо ÑÑоимоÑÑÑ Ð¸Ñ ÑÑÐµÐ½Ð¸Ñ cost seq_page_cost, а не random_page_cost. * Также Ð¼Ñ Ð´Ð¾Ð±Ð°Ð²Ð»Ñем ÑÑоимоÑÑÑ Ð·Ð° вÑÑиÑление ÑÑÐ»Ð¾Ð²Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð¹ ÑÑÑоки. * ÐÑе ÑÑоимоÑÑи ÑÑиÑаÑÑÑÑ Ð¿ÑопоÑÑионалÑно возÑаÑÑаÑÑими пÑи ÑканиÑовании. */ cost_qual_eval(&index_qual_cost, path->indexquals, root); *indexStartupCost = index_qual_cost.startup; *indexTotalCost = seq_page_cost * numIndexPages + (cpu_index_tuple_cost + index_qual_cost.per_tuple) * numIndexTuples;Ðднако пÑи Ñаком ÑаÑÑÑÑе не ÑÑиÑÑваеÑÑÑ Ð°Ð¼Ð¾ÑÑизаÑÐ¸Ñ ÑÑÐµÐ½Ð¸Ñ Ð¸Ð½Ð´ÐµÐºÑа пÑи повÑоÑном ÑканиÑовании.
ÐÑениÑÑ ÐºÐ¾ÑÑелÑÑÐ¸Ñ Ð¸Ð½Ð´ÐµÐºÑа. ÐÐ»Ñ Ð¿ÑоÑÑого ÑпоÑÑдоÑенного индекÑа по Ð¾Ð´Ð½Ð¾Ð¼Ñ Ð¿Ð¾Ð»Ñ ÐµÑ Ð¼Ð¾Ð¶Ð½Ð¾ полÑÑиÑÑ Ð¸Ð· pg_statistic. ÐÑли коÑÑелÑÑÐ¸Ñ Ð½ÐµÐ¸Ð·Ð²ÐµÑÑна, веÑнÑÑÑ ÐºÐ¾Ð½ÑеÑваÑивнÑÑ Ð¾ÑÐµÐ½ÐºÑ â Ð½Ð¾Ð»Ñ (коÑÑелÑÑÐ¸Ñ Ð¾ÑÑÑÑÑÑвÑеÑ).