?
Ce document utilise Manuel du site Web PHP chinois Libérer
系統(tǒng)給 amcostestimate
函數(shù)一個WHERE子句的列表,這個 WHERE 子
句列表是系統(tǒng)認(rèn)為可以被索引使用的東西。它必須返回訪問該索引的開銷估計(jì)值以
及 WHERE 子句的選擇性(也就是說,在索引掃描期間檢索的將被返回的數(shù)據(jù)行在父
表中所占據(jù)的比例)。對于簡單的場合,幾乎開銷估計(jì)器的所有工作都可以通過調(diào)
用優(yōu)化器里面的標(biāo)準(zhǔn)過程完成;有amcostestimate
這個函數(shù)的目的
是允許索引訪問方法提供和索引類型相關(guān)的知識,這樣也許可以改進(jìn)標(biāo)準(zhǔn)的開銷估計(jì)。
每個 amcostestimate
函數(shù)都有下面這樣的簽名:
void amcostestimate (PlannerInfo *root, IndexOptInfo *index, List *indexQuals, RelOptInfo *outer_rel, Cost *indexStartupCost, Cost *indexTotalCost, Selectivity *indexSelectivity, double *indexCorrelation);
頭四個參數(shù)是輸入:
規(guī)劃器的有關(guān)正在被處理的查詢的信息。
在考慮使用的索引。
索引條件子句的列表(隱含是AND的);如果是NIL列表 (空列表)就表示沒有可用的條件。請注意這個列表包含表達(dá)式樹,而不是 ScanKey(掃描鍵字)。
如果該索引可能要用于連接內(nèi)部掃描,那么這個將是規(guī)劃器關(guān)于連接 的外側(cè)信息,否則為NULL。當(dāng)不為NULL時(shí), 一些qual字句將會連接使用帶有這個rel的字句而不是簡單的約束字句。 同樣,開銷評估應(yīng)當(dāng)考慮到索引掃描將會為rel的每一行執(zhí)行一次。
后面四個參數(shù)是傳遞引用的輸出:
設(shè)置為索引啟動處理的開銷
設(shè)置為索引處理的總開銷
設(shè)置為索引的選擇型
設(shè)置為索引掃描順序和下層的表的順序之間的相關(guān)有效性
請注意開銷估計(jì)函數(shù)必須用C寫,而不能用SQL或者任何可用的存儲過程 語言,因?yàn)樗鼈儽仨氃L問規(guī)劃器/優(yōu)化器的內(nèi)部數(shù)據(jù)結(jié)構(gòu)。
索引訪問開銷應(yīng)該以 src/backend/optimizer/path/costsize.c:使用的單位進(jìn)行計(jì)算:一個順序磁盤塊抓取開銷是1.0 , 一個非順序抓取開銷是seq_page_cost ,而處理一個索引行的 開銷通常應(yīng)該是random_page_cost,而處理一個索引行的開銷 通常應(yīng)該是cpu_index_tuple_cost。另外,在任何索引處理期 間調(diào)用的比較操作符,都應(yīng)該增加一個數(shù)量為cpu_operator_cost倍數(shù)的開銷(特別是計(jì)算索引條件 indexQuals自己的時(shí)候)。
訪問開銷應(yīng)該包括所有與掃描索引本身相關(guān)的磁盤和CPU開銷,但是不包括檢 索或者處理索引標(biāo)識出來的父表的行的開銷。
"啟動開銷""start-up cost"是總掃描開銷中的這樣一部分: 在開始抓取第一行之前,必須花掉的開銷。對于大多數(shù)索引,這個可以是零,但 是那些啟動開銷很大的索引類型可能不能把它設(shè)置為零。
indexSelectivity 應(yīng)該設(shè)置成在索引掃描期間,父表中的行被 選出出來的部分的百分比。在索引比較松散的情況下,這個值通常比實(shí)際通過 給出的查詢條件之行所占的百分比要高。
indexCorrelation應(yīng)該設(shè)置成索引順序和表順序之間的相關(guān)性 (范圍在 -1.0 到 1.0 之間)。這個數(shù)值用于調(diào)整從父表中抓取行的開銷估計(jì)。
在連接情況下,返回的數(shù)值應(yīng)當(dāng)在每一次索引掃描之間平均。
開銷估計(jì)
一個典型的開銷估計(jì)器會像下面這樣進(jìn)行處理:
1.基于給出的查詢條件,估計(jì)并返回父表中將被訪問的行的百分比。如果缺
乏索引類型相關(guān)得知識,那么使用標(biāo)準(zhǔn)的優(yōu)化器函數(shù) clauselist_selectivity()
:
*indexSelectivity = clauselist_selectivity(root, indexQuals, index->rel->relid, JOIN_INNER, NULL);
2.估計(jì)在掃描過程中將被訪問的索引行數(shù)。對于許多索引類型,這個等于 indexSelectivity乘以索引中的行數(shù),但是可能更多。 請注意,頁面中的索引尺寸和行數(shù)可以從IndexOptInfo 結(jié)構(gòu)中獲得。
3.估計(jì)在掃描中將檢索的索引頁面數(shù)量。這個可能就是 indexSelectivity乘以索引的總頁面數(shù)。
4.計(jì)算索引訪問開銷。一個通用的估計(jì)器可以這么干:
/* * Our generic assumption is that the index pages will be read * sequentially, so they cost seq_page_cost each, not random_page_cost. * Also, we charge for evaluation of the indexquals at each index row. * All the costs are assumed to be paid incrementally during the scan. */ cost_qual_eval(&index_qual_cost, indexQuals, root); *indexStartupCost = index_qual_cost.startup; *indexTotalCost = seq_page_cost * numIndexPages + (cpu_index_tuple_cost + index_qual_cost.per_tuple) * numIndexTuples;
不過,上面沒有考慮在連接情況下的多次索引掃描中分期(amortization)開銷。
Estimate the index correlation. For a simple ordered index on a single field, this can be retrieved from pg_statistic. If the correlation is not known, the conservative estimate is zero (no correlation).
5.估計(jì)索引的相關(guān)性。對于簡單的在單個字段上的有序索引,這個值可以從 pg_statistic中檢索。如果相關(guān)性是未知,那么保守的估計(jì)是零(沒有相關(guān)性)。
開銷估計(jì)器函數(shù)的例子可以在src/backend/utils/adt/ selfuncs.c 里面找到。