您好,登錄后才能下訂單哦!
這篇文章主要講解了“PostgreSQL物理優化中的create_index_paths->choose_bitmap_and函數分析”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“PostgreSQL物理優化中的create_index_paths->choose_bitmap_and函數分析”吧!
該函數執行Bitmap AND操作后創建位圖索引掃描訪問路徑(BitmapAndPath)節點。
下面是BitmapAnd訪問路徑的樣例:
testdb=# explain verbose select t1.* testdb-# from t_dwxx t1 testdb-# where (dwbh > '10000' and dwbh < '15000') AND (dwdz between 'DWDZ10000' and 'DWDZ15000'); QUERY PLAN ---------------------------------------------------------------------------------------------- Bitmap Heap Scan on public.t_dwxx t1 (cost=32.33..88.38 rows=33 width=20) Output: dwmc, dwbh, dwdz Recheck Cond: (((t1.dwbh)::text > '10000'::text) AND ((t1.dwbh)::text < '15000'::text) AND ((t1.dwdz)::text >= 'DWDZ10000' ::text) AND ((t1.dwdz)::text <= 'DWDZ15000'::text)) -> BitmapAnd (cost=32.33..32.33 rows=33 width=0) -->BitmapAnd -> Bitmap Index Scan on t_dwxx_pkey (cost=0.00..13.86 rows=557 width=0) Index Cond: (((t1.dwbh)::text > '10000'::text) AND ((t1.dwbh)::text < '15000'::text)) -> Bitmap Index Scan on idx_dwxx_dwdz (cost=0.00..18.21 rows=592 width=0) Index Cond: (((t1.dwdz)::text >= 'DWDZ10000'::text) AND ((t1.dwdz)::text <= 'DWDZ15000'::text)) (8 rows)
Cost相關
注意:實際使用的參數值通過系統配置文件定義,而不是這里的常量定義!
typedef double Cost; /* execution cost (in page-access units) */ /* defaults for costsize.c's Cost parameters */ /* NB: cost-estimation code should use the variables, not these constants! */ /* 注意:實際值通過系統配置文件定義,而不是這里的常量定義! */ /* If you change these, update backend/utils/misc/postgresql.sample.conf */ #define DEFAULT_SEQ_PAGE_COST 1.0 //順序掃描page的成本 #define DEFAULT_RANDOM_PAGE_COST 4.0 //隨機掃描page的成本 #define DEFAULT_CPU_TUPLE_COST 0.01 //處理一個元組的CPU成本 #define DEFAULT_CPU_INDEX_TUPLE_COST 0.005 //處理一個索引元組的CPU成本 #define DEFAULT_CPU_OPERATOR_COST 0.0025 //執行一次操作或函數的CPU成本 #define DEFAULT_PARALLEL_TUPLE_COST 0.1 //并行執行,從一個worker傳輸一個元組到另一個worker的成本 #define DEFAULT_PARALLEL_SETUP_COST 1000.0 //構建并行執行環境的成本 #define DEFAULT_EFFECTIVE_CACHE_SIZE 524288 /*先前已有介紹, measured in pages */ double seq_page_cost = DEFAULT_SEQ_PAGE_COST; double random_page_cost = DEFAULT_RANDOM_PAGE_COST; double cpu_tuple_cost = DEFAULT_CPU_TUPLE_COST; double cpu_index_tuple_cost = DEFAULT_CPU_INDEX_TUPLE_COST; double cpu_operator_cost = DEFAULT_CPU_OPERATOR_COST; double parallel_tuple_cost = DEFAULT_PARALLEL_TUPLE_COST; double parallel_setup_cost = DEFAULT_PARALLEL_SETUP_COST; int effective_cache_size = DEFAULT_EFFECTIVE_CACHE_SIZE; Cost disable_cost = 1.0e10;//1后面10個0,通過設置一個巨大的成本,讓優化器自動放棄此路徑 int max_parallel_workers_per_gather = 2;//每次gather使用的worker數
PathClauseUsage
/* Per-path data used within choose_bitmap_and() */ typedef struct { Path *path; /* 訪問路徑鏈表,IndexPath, BitmapAndPath, or BitmapOrPath */ List *quals; /* 限制條件子句鏈表,the WHERE clauses it uses */ List *preds; /* 部分索引謂詞鏈表,predicates of its partial index(es) */ Bitmapset *clauseids; /* 位圖集合,quals+preds represented as a bitmapset */ } PathClauseUsage;
choose_bitmap_and函數
create_index_paths->choose_bitmap_and函數,該函數給定非空的位圖訪問路徑鏈表,執行AND操作后合并到一條路徑中,最終得到位圖索引掃描訪問路徑節點.
/* * choose_bitmap_and * Given a nonempty list of bitmap paths, AND them into one path. * 給定非空的位圖訪問路徑鏈表,執行AND操作后合并到一條路徑中 * * This is a nontrivial decision since we can legally use any subset of the * given path set. We want to choose a good tradeoff between selectivity * and cost of computing the bitmap. * 這是一個非常重要的策略,因為這樣可以合法地使用給定路徑集的任何子集。 * * The result is either a single one of the inputs, or a BitmapAndPath * combining multiple inputs. * 輸出結果要么是輸出的其中之一,要么是融合多個輸入之后的BitmapAndPath */ static Path * choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths) { int npaths = list_length(paths); PathClauseUsage **pathinfoarray; PathClauseUsage *pathinfo; List *clauselist; List *bestpaths = NIL; Cost bestcost = 0; int i, j; ListCell *l; Assert(npaths > 0); /* else caller error */ if (npaths == 1) return (Path *) linitial(paths); /* easy case */ /* * In theory we should consider every nonempty subset of the given paths. * In practice that seems like overkill, given the crude nature of the * estimates, not to mention the possible effects of higher-level AND and * OR clauses. Moreover, it's completely impractical if there are a large * number of paths, since the work would grow as O(2^N). * 理論上,我們應該考慮給定路徑的所有非空子集。在實踐中, * 考慮到估算的不確定性和成本,以及更高級別的AND和OR約束可能產生的影響,這樣的做法并不合適. * 此外,它并不切合實際,如果有大量的路徑,這項工作的復雜度會是指數級的O(2 ^ N)。 * * As a heuristic, we first check for paths using exactly the same sets of * WHERE clauses + index predicate conditions, and reject all but the * cheapest-to-scan in any such group. This primarily gets rid of indexes * that include the interesting columns but also irrelevant columns. (In * situations where the DBA has gone overboard on creating variant * indexes, this can make for a very large reduction in the number of * paths considered further.) * 作為一種啟發式方法,首先使用完全相同的WHERE子句+索引謂詞條件集檢查路徑, * 并去掉這類條件組中除成本最低之外的所有路徑。 * 這主要是去掉了包含interesting列和不相關列的索引。 * (在DBA過度創建索引的情況下,這會大大減少進一步考慮的路徑數量。) * * We then sort the surviving paths with the cheapest-to-scan first, and * for each path, consider using that path alone as the basis for a bitmap * scan. Then we consider bitmap AND scans formed from that path plus * each subsequent (higher-cost) path, adding on a subsequent path if it * results in a reduction in the estimated total scan cost. This means we * consider about O(N^2) rather than O(2^N) path combinations, which is * quite tolerable, especially given than N is usually reasonably small * because of the prefiltering step. The cheapest of these is returned. * 然后,我們首先使用成本最低的掃描路徑對現存的路徑進行排序, * 對于每個路徑,考慮單獨使用該路徑作為位圖掃描的基礎。 * 然后我們考慮位圖和從該路徑形成的掃描加上每個后續的(更高成本的)路徑, * 如果后續路徑導致估算的總掃描成本減少,那么就添加一個后續路徑。 * 這意味著我們只需要處理O(N ^ 2),而不是O(2 ^ N)個路徑組合, * 這樣的成本完全可以接受,特別是N通常相當小時。函數返回成本最低的路徑。 * * We will only consider AND combinations in which no two indexes use the * same WHERE clause. This is a bit of a kluge: it's needed because * costsize.c and clausesel.c aren't very smart about redundant clauses. * They will usually double-count the redundant clauses, producing a * too-small selectivity that makes a redundant AND step look like it * reduces the total cost. Perhaps someday that code will be smarter and * we can remove this limitation. (But note that this also defends * against flat-out duplicate input paths, which can happen because * match_join_clauses_to_index will find the same OR join clauses that * extract_restriction_or_clauses has pulled OR restriction clauses out * of.) * 我們將只考慮沒有兩個索引同時使用相同的WHERE子句的AND組合。 * 這是一個有點蹩腳的做法:之所以這樣是因為cost.c和clausesel.c未能足夠聰明的處理多余的子句。 * 它們通常會重復計算冗余子句,從而產生很小的選擇性,使冗余子句看起來像是減少了總成本。 * 也許有一天,代碼會變得更聰明,我們可以消除這個限制。 * (但是要注意,這也可以防止完全重復的輸入路徑, * 因為match_join_clauses_to_index會找到相同的OR連接子句,而這些子句 * 已通過extract_restriction_or_clauses函數提升到外面去了.) * * For the same reason, we reject AND combinations in which an index * predicate clause duplicates another clause. Here we find it necessary * to be even stricter: we'll reject a partial index if any of its * predicate clauses are implied by the set of WHERE clauses and predicate * clauses used so far. This covers cases such as a condition "x = 42" * used with a plain index, followed by a clauseless scan of a partial * index "WHERE x >= 40 AND x < 50". The partial index has been accepted * only because "x = 42" was present, and so allowing it would partially * double-count selectivity. (We could use predicate_implied_by on * regular qual clauses too, to have a more intelligent, but much more * expensive, check for redundancy --- but in most cases simple equality * seems to suffice.) * 出于同樣的原因,我們不會組合索引謂詞子句與另一個重復的子句。 * 在這里,有必要更加嚴格 : 如果部分索引的任何謂詞子句 * 隱含在WHERE子句中,則不能使用此索引。 * 這里包括了形如使用普通索引的“x = 42”和使用部分索引“x >= 40和x < 50”的情況。 * 部分索引被接受,是因為存在“x = 42”,因此允許它部分重復計數選擇性。 * (我們也可以在普通的qual子句上使用predicate_implied_by函數, * 這樣就可以更智能但更昂貴地檢查冗余——但在大多數情況下,簡單的等式似乎就足夠了。) */ /* * Extract clause usage info and detect any paths that use exactly the * same set of clauses; keep only the cheapest-to-scan of any such groups. * The surviving paths are put into an array for qsort'ing. * 提取子句使用信息并檢測使用完全相同子句集的所有路徑; * 只保留這類路徑中成本最低的,這些路徑被放入一個數組中進行qsort'ing */ pathinfoarray = (PathClauseUsage **) palloc(npaths * sizeof(PathClauseUsage *));//數組 clauselist = NIL; npaths = 0; foreach(l, paths)//遍歷paths { Path *ipath = (Path *) lfirst(l); pathinfo = classify_index_clause_usage(ipath, &clauselist);//歸類路徑信息 for (i = 0; i < npaths; i++) { if (bms_equal(pathinfo->clauseids, pathinfoarray[i]->clauseids)) break;//只要發現子句集一樣,就繼續執行 } if (i < npaths)//發現相同的 { /* duplicate clauseids, keep the cheaper one */ //相同的約束條件,只保留成本最低的 Cost ncost; Cost ocost; Selectivity nselec; Selectivity oselec; cost_bitmap_tree_node(pathinfo->path, &ncost, &nselec);//計算成本 cost_bitmap_tree_node(pathinfoarray[i]->path, &ocost, &oselec); if (ncost < ocost) pathinfoarray[i] = pathinfo; } else//沒有發現條件一樣的,添加到數組中 { /* not duplicate clauseids, add to array */ pathinfoarray[npaths++] = pathinfo; } } /* If only one surviving path, we're done */ if (npaths == 1)//結果只有一條,則返回之 return pathinfoarray[0]->path; /* Sort the surviving paths by index access cost */ qsort(pathinfoarray, npaths, sizeof(PathClauseUsage *), path_usage_comparator);//以索引訪問成本排序現存路徑 /* * For each surviving index, consider it as an "AND group leader", and see * whether adding on any of the later indexes results in an AND path with * cheaper total cost than before. Then take the cheapest AND group. * 對于現存的索引,把它視為"AND group leader", * 并查看是否添加了以后的索引后,會得到一個總成本比以前更低的AND路徑。 * 選擇成本最低的AND組. * */ for (i = 0; i < npaths; i++)//遍歷這些路徑 { Cost costsofar; List *qualsofar; Bitmapset *clauseidsofar; ListCell *lastcell; pathinfo = pathinfoarray[i];//PathClauseUsage結構體 paths = list_make1(pathinfo->path);//路徑鏈表 costsofar = bitmap_scan_cost_est(root, rel, pathinfo->path);//當前的成本 qualsofar = list_concat(list_copy(pathinfo->quals), list_copy(pathinfo->preds)); clauseidsofar = bms_copy(pathinfo->clauseids); lastcell = list_head(paths); /* 用于快速刪除,for quick deletions */ for (j = i + 1; j < npaths; j++)//掃描后續的路徑 { Cost newcost; pathinfo = pathinfoarray[j]; /* Check for redundancy */ if (bms_overlap(pathinfo->clauseids, clauseidsofar)) continue; /* 多余的路徑,consider it redundant */ if (pathinfo->preds)//部分索引? { bool redundant = false; /* we check each predicate clause separately */ //單獨檢查每一個謂詞 foreach(l, pathinfo->preds) { Node *np = (Node *) lfirst(l); if (predicate_implied_by(list_make1(np), qualsofar, false)) { redundant = true; break; /* out of inner foreach loop */ } } if (redundant) continue; } /* tentatively add new path to paths, so we can estimate cost */ //嘗試在路徑中添加新路徑,這樣我們就可以估算成本 paths = lappend(paths, pathinfo->path); newcost = bitmap_and_cost_est(root, rel, paths);//估算成本 if (newcost < costsofar)//新成本更低 { /* keep new path in paths, update subsidiary variables */ costsofar = newcost; qualsofar = list_concat(qualsofar, list_copy(pathinfo->quals));//添加此條件 qualsofar = list_concat(qualsofar, list_copy(pathinfo->preds));//添加此謂詞 clauseidsofar = bms_add_members(clauseidsofar, pathinfo->clauseids);//添加此子句ID lastcell = lnext(lastcell); } else { /* reject new path, remove it from paths list */ paths = list_delete_cell(paths, lnext(lastcell), lastcell);//去掉新路徑 } Assert(lnext(lastcell) == NULL); } /* Keep the cheapest AND-group (or singleton) */ if (i == 0 || costsofar < bestcost)//單條路徑或者取得最小的成本 { bestpaths = paths; bestcost = costsofar; } /* some easy cleanup (we don't try real hard though) */ list_free(qualsofar); } if (list_length(bestpaths) == 1) return (Path *) linitial(bestpaths); /* 無需AND路徑,no need for AND */ return (Path *) create_bitmap_and_path(root, rel, bestpaths);//生成BitmapAndPath } //-------------------------------------------------------------------------- bitmap_scan_cost_est /* * Estimate the cost of actually executing a bitmap scan with a single * index path (no BitmapAnd, at least not at this level; but it could be * a BitmapOr). */ static Cost bitmap_scan_cost_est(PlannerInfo *root, RelOptInfo *rel, Path *ipath) { BitmapHeapPath bpath; Relids required_outer; /* Identify required outer rels, in case it's a parameterized scan */ required_outer = get_bitmap_tree_required_outer(ipath); /* Set up a dummy BitmapHeapPath */ bpath.path.type = T_BitmapHeapPath; bpath.path.pathtype = T_BitmapHeapScan; bpath.path.parent = rel; bpath.path.pathtarget = rel->reltarget; bpath.path.param_info = get_baserel_parampathinfo(root, rel, required_outer); bpath.path.pathkeys = NIL; bpath.bitmapqual = ipath; /* * Check the cost of temporary path without considering parallelism. * Parallel bitmap heap path will be considered at later stage. */ bpath.path.parallel_workers = 0; cost_bitmap_heap_scan(&bpath.path, root, rel, bpath.path.param_info, ipath, get_loop_count(root, rel->relid, required_outer));//BitmapHeapPath計算成本 return bpath.path.total_cost; } //-------------------------------------------------------------------------- bitmap_and_cost_est /* * Estimate the cost of actually executing a BitmapAnd scan with the given * inputs. * 給定輸入,估算實際執行BitmapAnd掃描的實際成本 */ static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths) { BitmapAndPath apath; BitmapHeapPath bpath; Relids required_outer; /* Set up a dummy BitmapAndPath */ apath.path.type = T_BitmapAndPath; apath.path.pathtype = T_BitmapAnd; apath.path.parent = rel; apath.path.pathtarget = rel->reltarget; apath.path.param_info = NULL; /* not used in bitmap trees */ apath.path.pathkeys = NIL; apath.bitmapquals = paths; cost_bitmap_and_node(&apath, root); /* Identify required outer rels, in case it's a parameterized scan */ required_outer = get_bitmap_tree_required_outer((Path *) &apath); /* Set up a dummy BitmapHeapPath */ bpath.path.type = T_BitmapHeapPath; bpath.path.pathtype = T_BitmapHeapScan; bpath.path.parent = rel; bpath.path.pathtarget = rel->reltarget; bpath.path.param_info = get_baserel_parampathinfo(root, rel, required_outer); bpath.path.pathkeys = NIL; bpath.bitmapqual = (Path *) &apath; /* * Check the cost of temporary path without considering parallelism. * Parallel bitmap heap path will be considered at later stage. */ bpath.path.parallel_workers = 0; /* Now we can do cost_bitmap_heap_scan */ cost_bitmap_heap_scan(&bpath.path, root, rel, bpath.path.param_info, (Path *) &apath, get_loop_count(root, rel->relid, required_outer));//BitmapHeapPath計算成本 return bpath.path.total_cost; } //-------------------------------------------------------------------------- create_bitmap_and_path /* * create_bitmap_and_path * Creates a path node representing a BitmapAnd. */ BitmapAndPath * create_bitmap_and_path(PlannerInfo *root, RelOptInfo *rel, List *bitmapquals) { BitmapAndPath *pathnode = makeNode(BitmapAndPath); pathnode->path.pathtype = T_BitmapAnd; pathnode->path.parent = rel; pathnode->path.pathtarget = rel->reltarget; pathnode->path.param_info = NULL; /* not used in bitmap trees */ /* * Currently, a BitmapHeapPath, BitmapAndPath, or BitmapOrPath will be * parallel-safe if and only if rel->consider_parallel is set. So, we can * set the flag for this path based only on the relation-level flag, * without actually iterating over the list of children. */ pathnode->path.parallel_aware = false; pathnode->path.parallel_safe = rel->consider_parallel; pathnode->path.parallel_workers = 0; pathnode->path.pathkeys = NIL; /* always unordered */ pathnode->bitmapquals = bitmapquals; /* this sets bitmapselectivity as well as the regular cost fields: */ cost_bitmap_and_node(pathnode, root);//計算成本 return pathnode; } //----------------------------------------------------- cost_bitmap_and_node /* * cost_bitmap_and_node * Estimate the cost of a BitmapAnd node * 估算BitmapAnd節點成本 * * Note that this considers only the costs of index scanning and bitmap * creation, not the eventual heap access. In that sense the object isn't * truly a Path, but it has enough path-like properties (costs in particular) * to warrant treating it as one. We don't bother to set the path rows field, * however. */ void cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root) { Cost totalCost; Selectivity selec; ListCell *l; /* * We estimate AND selectivity on the assumption that the inputs are * independent. This is probably often wrong, but we don't have the info * to do better. * * The runtime cost of the BitmapAnd itself is estimated at 100x * cpu_operator_cost for each tbm_intersect needed. Probably too small, * definitely too simplistic? */ totalCost = 0.0; selec = 1.0; foreach(l, path->bitmapquals) { Path *subpath = (Path *) lfirst(l); Cost subCost; Selectivity subselec; cost_bitmap_tree_node(subpath, &subCost, &subselec); selec *= subselec; totalCost += subCost; if (l != list_head(path->bitmapquals)) totalCost += 100.0 * cpu_operator_cost; } path->bitmapselectivity = selec; path->path.rows = 0; /* per above, not used */ path->path.startup_cost = totalCost; path->path.total_cost = totalCost; }
測試腳本如下
select t1.* from t_dwxx t1 where (dwbh > '10000' and dwbh < '15000') AND (dwdz between 'DWDZ10000' and 'DWDZ15000');
啟動gdb跟蹤
(gdb) b choose_bitmap_and Breakpoint 1 at 0x74e8c2: file indxpath.c, line 1372. (gdb) c Continuing. Breakpoint 1, choose_bitmap_and (root=0x1666638, rel=0x1666a48, paths=0x166fdf0) at indxpath.c:1372 1372 int npaths = list_length(paths);
輸入參數
(gdb) p *paths $1 = {type = T_List, length = 2, head = 0x166fe20, tail = 0x16706b8} (gdb) p *(Node *)paths->head->data.ptr_value $2 = {type = T_IndexPath} (gdb) p *(Node *)paths->head->next->data.ptr_value $3 = {type = T_IndexPath} (gdb) set $p1=(IndexPath *)paths->head->data.ptr_value (gdb) set $p2=(IndexPath *)paths->head->next->data.ptr_value (gdb) p *$p1 $4 = {path = {type = T_IndexPath, pathtype = T_IndexScan, parent = 0x1666a48, pathtarget = 0x166d988, param_info = 0x0, parallel_aware = false, parallel_safe = true, parallel_workers = 0, rows = 33, startup_cost = 0.28500000000000003, total_cost = 116.20657683302848, pathkeys = 0x0}, indexinfo = 0x166e420, indexclauses = 0x166f528, indexquals = 0x166f730, indexqualcols = 0x166f780, indexorderbys = 0x0, indexorderbycols = 0x0, indexscandir = ForwardScanDirection, indextotalcost = 18.205000000000002, indexselectivity = 0.059246954595791879} (gdb) p *$p2 $5 = {path = {type = T_IndexPath, pathtype = T_IndexScan, parent = 0x1666a48, pathtarget = 0x166d988, param_info = 0x0, parallel_aware = false, parallel_safe = true, parallel_workers = 0, rows = 33, startup_cost = 0.28500000000000003, total_cost = 111.33157683302848, pathkeys = 0x0}, indexinfo = 0x1666c58, indexclauses = 0x166fed0, indexquals = 0x166ffc8, indexqualcols = 0x1670018, indexorderbys = 0x0, indexorderbycols = 0x0, indexscandir = ForwardScanDirection, indextotalcost = 13.855, indexselectivity = 0.055688888888888899}
paths中的第1個元素對應(dwbh > '10000' and dwbh < '15000') ,第2個元素對應(dwdz between 'DWDZ10000' and 'DWDZ15000')
(gdb) set $ri1=(RestrictInfo *)$p1->indexclauses->head->data.ptr_value (gdb) set $tmp=(RelabelType *)((OpExpr *)$ri1->clause)->args->head->data.ptr_value (gdb) p *(Var *)$tmp->arg $17 = {xpr = {type = T_Var}, varno = 1, varattno = 3, vartype = 1043, vartypmod = 104, varcollid = 100, varlevelsup = 0, varnoold = 1, varoattno = 3, location = 76} (gdb) p *(Node *)((OpExpr *)$ri1->clause)->args->head->next->data.ptr_value $18 = {type = T_Const} (gdb) p *(Const *)((OpExpr *)$ri1->clause)->args->head->next->data.ptr_value $19 = {xpr = {type = T_Const}, consttype = 25, consttypmod = -1, constcollid = 100, constlen = -1, constvalue = 23636608, constisnull = false, constbyval = false, location = 89}
開始遍歷paths,提取子句條件并檢測是否使用完全相同子句集的所有路徑,只保留這些路徑中成本最低的,這些路徑被放入一個數組中進行qsort.
... (gdb) 1444 npaths = 0; (gdb) 1445 foreach(l, paths) (gdb)
收集信息到PathClauseUsage數組中
... (gdb) n 1471 pathinfoarray[npaths++] = pathinfo; (gdb) 1445 foreach(l, paths) (gdb) 1476 if (npaths == 1) (gdb) p npaths $26 = 2 (gdb)
按成本排序
(gdb) n 1480 qsort(pathinfoarray, npaths, sizeof(PathClauseUsage *),
遍歷路徑,找到成本最低的AND group
1488 for (i = 0; i < npaths; i++) (gdb) n 1495 pathinfo = pathinfoarray[i]; (gdb) 1496 paths = list_make1(pathinfo->path); (gdb) 1497 costsofar = bitmap_scan_cost_est(root, rel, pathinfo->path); (gdb) 1499 list_copy(pathinfo->preds));
獲取當前的成本,設置當前的條件子句
(gdb) p costsofar $27 = 89.003250000000008 (gdb) n 1498 qualsofar = list_concat(list_copy(pathinfo->quals),
執行AND操作(路徑疊加),成本更低,調整當前成本和相關變量
(gdb) n 1531 newcost = bitmap_and_cost_est(root, rel, paths); (gdb) 1532 if (newcost < costsofar) (gdb) p newcost $30 = 88.375456720095343 (gdb) n 1535 costsofar = newcost; (gdb) n 1537 list_copy(pathinfo->quals)); (gdb) 1536 qualsofar = list_concat(qualsofar, (gdb) 1539 list_copy(pathinfo->preds));
處理下一個AND條件,單個AND條件比上一個條件成本高,保留原來的
1488 for (i = 0; i < npaths; i++) (gdb) 1495 pathinfo = pathinfoarray[i]; (gdb) 1496 paths = list_make1(pathinfo->path); (gdb) 1497 costsofar = bitmap_scan_cost_est(root, rel, pathinfo->path); (gdb) 1499 list_copy(pathinfo->preds)); (gdb) p costsofar $34 = 94.053250000000006 (gdb) n 1498 qualsofar = list_concat(list_copy(pathinfo->quals), (gdb) 1500 clauseidsofar = bms_copy(pathinfo->clauseids); (gdb) 1501 lastcell = list_head(paths); /* for quick deletions */ (gdb) 1503 for (j = i + 1; j < npaths; j++) (gdb) 1553 if (i == 0 || costsofar < bestcost) (gdb) p i $35 = 1 (gdb) p costsofar $36 = 94.053250000000006 (gdb) p bestcost $37 = 88.375456720095343 (gdb)
構建BitmapAndPath,返回
(gdb) n 1563 if (list_length(bestpaths) == 1) (gdb) 1565 return (Path *) create_bitmap_and_path(root, rel, bestpaths); (gdb) 1566 }
DONE!
(gdb) n create_index_paths (root=0x1666638, rel=0x1666a48) at indxpath.c:337 337 bpath = create_bitmap_heap_path(root, rel, bitmapqual,
感謝各位的閱讀,以上就是“PostgreSQL物理優化中的create_index_paths->choose_bitmap_and函數分析”的內容了,經過本文的學習后,相信大家對PostgreSQL物理優化中的create_index_paths->choose_bitmap_and函數分析這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。