In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-04-12 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Database >
Share
Shulou(Shulou.com)05/31 Report--
This article mainly introduces "make_rel_from_joinlist function analysis in PostgreSQL". In daily operation, I believe many people have doubts about make_rel_from_joinlist function analysis in PostgreSQL. The editor consulted all kinds of data and sorted out simple and easy-to-use operation methods. I hope it will be helpful for you to answer the doubts about "make_rel_from_joinlist function analysis in PostgreSQL". Next, please follow the editor to study!
I. Source code interpretation
According to the connection relation list (joinlist), the make_rel_from_joinlist function constructs the connection path through the external algorithm (hook function) / genetic algorithm / dynamic programming algorithm, in which the joinlist linked list has been generated by calling the deconstruct_jointree function in the main function.
The standard_join_search function and genetic algorithm of dynamic programming algorithm are introduced in the following chapters.
/ * make_rel_from_joinlist * Build access paths using a "joinlist" to guide the join path search. * generate the connection path based on the joinlist constructed by the deconstruct_jointree function. * the detailed data structure of joinlist can be found in the deconstruct_jointree function notes * * See comments for deconstruct_jointree () for definition of the joinlist * data structure. * / static RelOptInfo * make_rel_from_joinlist (PlannerInfo * root, List * joinlist) {int levels_needed; List * initial_rels; ListCell * jl; / * Count the number of child joinlist nodes. This is the depth of the * dynamic-programming algorithm we must employ to consider all ways of * joining the child nodes. * count the number of nodes in the joinlist linked list. * determine the algorithm used (dynamic programming algorithm vs genetic algorithm), such as the number of join_rel_ levels [lev]) / / traversing the linked list {rel = (RelOptInfo *) lfirst (lc); / / the newly generated relationship / * Create paths for partitionwise joins. * / generate_partitionwise_join_paths (root, rel); / / create partitionwise path / * * Except for the topmost scan/join rel, consider gathering * partial paths. We'll do the same for the topmost scan/join rel * once we know the final targetlist (see grouping_planner). * / if (lev
< levels_needed) generate_gather_paths(root, rel, false);//并行执行需考虑gathering /* Find and save the cheapest paths for this rel */ set_cheapest(rel);//从形成该joinrel的所有路径中找到成本最低的 #ifdef OPTIMIZER_DEBUG debug_print_rel(root, rel);//DEBUG信息 #endif } } /* * We should have a single rel at the final level. * 连接的最终结果,只有一个RelOptInfo */ if (root->Join_rel_ level [levels _ needed] = = NIL) elog (ERROR, "failed to build any% d-way joins", levels_needed); Assert (list_length (root- > join_rel_ level [levels _ needed]) = = 1); rel = (RelOptInfo *) linitial (root- > join_rel_ levels [needed _ needed]); / / get the final result root- > join_rel_level = NULL;// reset return rel / / return} /-geqo / * * geqo * solution of the query optimization problem * similar to a constrained Traveling Salesman Problem (TSP) * genetic algorithm: refer to TSP's algorithm. * TSP- travel salesman problem (shortest path problem): * given the distance between a series of cities and each pair of cities, solve the shortest circuit to visit each city once and return to the starting city. * / RelOptInfo * geqo (PlannerInfo * root, int number_of_rels, List * initial_rels) {GeqoPrivateData private; int generation; Chromosome * momma; Chromosome * daddy; Chromosome * kid; Pool * pool; int pool_size, number_generations; # ifdef GEQO_DEBUG int status_interval; # endif Gene * best_tour; RelOptInfo * best_rel # if defined (ERX) Edge * edge_table; / * list of edges * / int edge_failures = 0; # endif # if defined (CX) | | defined (PX) | | defined (OX1) | | defined (OX2) City * city_table; / * list of cities * / # endif # if defined (CX) int cycle_diffs = 0; int mutations = 0 # endif / * set up private information * / root- > join_search_private = (void *) & private; private.initial_rels = initial_rels; / * initialize private number generator * / geqo_set_seed (root, Geqo_seed); / * set GA parameters * / pool_size = gimme_pool_size (number_of_rels); number_generations = gimme_number_generations (pool_size); # ifdef GEQO_DEBUG status_interval = 10 # endif / * allocate genetic pool memory * / pool = alloc_pool (root, pool_size, number_of_rels); / * random initialization of the pool * / random_init_pool (root, pool); / * sort the pool according to cheapest path as fitness * / sort_pool (root, pool) / * we have to do it only one time, since all * kids replace the worst individuals in * future (- > geqo_pool.c:spread_chromo) * / # ifdef GEQO_DEBUG elog (DEBUG1, "GEQO selected% d pool entries, best% .2f, worst% .2f", pool_size, pool- > data [0] .worth Pool- > data [pool _ size-1] .worth) # endif / * allocate chromosome momma and daddy memory * / momma = alloc_chromo (root, pool- > string_length); daddy = alloc_chromo (root, pool- > string_length); # if defined (ERX) # ifdef GEQO_DEBUG elog (DEBUG2, "using edge recombination crossover [ERX]"); # endif / * allocate edge table memory * / edge_table = alloc_edge_table (root, pool- > string_length) # elif defined (PMX) # ifdef GEQO_DEBUG elog (DEBUG2, "using partially matched crossover [PMX]"); # endif / * allocate chromosome kid memory * / kid = alloc_chromo (root, pool- > string_length); # elif defined (CX) # ifdef GEQO_DEBUG elog (DEBUG2, "using cycle crossover [CX]"); # endif / * allocate city table memory * / kid = alloc_chromo (root, pool- > string_length) City_table = alloc_city_table (root, pool- > string_length); # elif defined (PX) # ifdef GEQO_DEBUG elog (DEBUG2, "using position crossover [PX]"); # endif / * allocate city table memory * / kid = alloc_chromo (root, pool- > string_length); city_table = alloc_city_table (root, pool- > string_length); # elif defined (OX1) # ifdef GEQO_DEBUG elog (DEBUG2, "using order crossover [OX1]") # endif / * allocate city table memory * / kid = alloc_chromo (root, pool- > string_length); city_table = alloc_city_table (root, pool- > string_length); # elif defined (OX2) # ifdef GEQO_DEBUG elog (DEBUG2, "using order crossover [OX2]"); # endif / * allocate city table memory * / kid = alloc_chromo (root, pool- > string_length); city_table = alloc_city_table (root, pool- > string_length) # endif / * my pain main part: * / / * iterative optimization * / for (generation = 0; generation
< number_generations; generation++) { /* SELECTION: using linear bias function */ geqo_selection(root, momma, daddy, pool, Geqo_selection_bias); #if defined (ERX) /* EDGE RECOMBINATION CROSSOVER */ gimme_edge_table(root, momma->String, daddy- > string, pool- > string_length, edge_table); kid = momma; / * are there any edge failures? * / edge_failures + = gimme_tour (root, edge_table, kid- > string, pool- > string_length); # elif defined (PMX) / * PARTIALLY MATCHED CROSSOVER * / pmx (root, momma- > string, daddy- > string, kid- > string, pool- > string_length) # elif defined (CX) / * CYCLE CROSSOVER * / cycle_diffs = cx (root, momma- > string, daddy- > string, kid- > string, pool- > string_length, city_table); / * mutate the child * / if (cycle_diffs = = 0) {mutations++; geqo_mutation (root, kid- > string, pool- > string_length) } # elif defined (PX) / * POSITION CROSSOVER * / px (root, momma- > string, daddy- > string, kid- > string, pool- > string_length, city_table); # elif defined (OX1) / * ORDER CROSSOVER * / ox1 (root, momma- > string, daddy- > string, kid- > string, pool- > string_length, city_table) # elif defined (OX2) / * ORDER CROSSOVER * / ox2 (root, momma- > string, daddy- > string, kid- > string, pool- > string_length, city_table); # endif / * EVALUATE FITNESS * / kid- > worth = geqo_eval (root, kid- > string, pool- > string_length); / * push the kid into the wilderness of life according to its worth * / spread_chromo (root, kid, pool) # ifdef GEQO_DEBUG if (status_interval & &! (generation% status_interval) print_gen (stdout, pool, generation); # endif} # if defined (ERX) & & defined (GEQO_DEBUG) if (edge_failures! = 0) elog (LOG, "[GEQO] failures:% d, average:% d", edge_failures, (int) number_generations / edge_failures) Else elog (LOG, "[GEQO] no edge failures detected"); # endif # if defined (CX) & & defined (GEQO_DEBUG) if (mutations! = 0) elog (LOG, "[GEQO] mutations:% d, generations:% d", mutations, number_generations); else elog (LOG, "[GEQO] no mutations processed") # endif # ifdef GEQO_DEBUG print_pool (stdout, pool, 0, pool_size-1); # endif # ifdef GEQO_DEBUG elog (DEBUG1, "GEQO best is% .2f after% d generations", pool- > data [0] .worth, number_generations); # endif / * * got the cheapest query tree processed by geqo First element of the * population indicates the best query tree * / best_tour = (Gene *) pool- > data [0] .string; best_rel = gimme_tree (root, best_tour, pool- > string_length); if (best_rel = = NULL) elog (ERROR, "geqo failed to make a valid plan"); / * DBG: show the query plan * / # ifdef NOT_USED print_plan (best_plan, root) # endif / *. Free memory stuff * / free_chromo (root, momma); free_chromo (root, daddy); # if defined (ERX) free_edge_table (root, edge_table); # elif defined (PMX) free_chromo (root, kid); # elif defined (CX) free_chromo (root, kid); free_city_table (root, city_table); # elif defined (PX) free_chromo (root, kid) Free_city_table (root, city_table); # elif defined (OX1) free_chromo (root, kid); free_city_table (root, city_table); # elif defined (OX2) free_chromo (root, kid); free_city_table (root, city_table); # endif free_pool (root, pool); / *. Clear root pointer to our private storage * / root- > join_search_private = NULL; return best_rel;} II. Tracking analysis
The test script and execution plan are as follows:
Testdb=# explain verbose select a.from t_grxx testdb b.grbhjje testdb-# from t_dwxx a btestdb-# where a.dwbh t2.grbh # lateral (select t1.dwbh a.dwbh and t1.grbh t1.grbhmemt 2.je testdb (# grbh1 testdb (# grbh2 on t1.dwbh = t2.grbh) btestdb-# where a.dwbh = '1001'testdb-# order by b.dwbh QUERY PLAN -Nested Loop (cost=0.87..111.89 rows=10 width=37) Output: a.dwmc A.dwbh, a.dwdz, t1.grbh, t2.je, t1.dwbh-> Nested Loop (cost=0.58..28.69 rows=10 width=29) Output: a.dwmc, a.dwbh, a.dwdz, t1.grbh, t1.dwbh-> Index Scan using t_dwxx_pkey on public.t_dwxx a (cost=0.29..8.30 rows=1 width=20) Output: a.dwmc, a.dwbh A.dwdz Index Cond: (a.dwbh):: text = '1001'::text)-> Index Scan using idx_t_grxx_dwbh on public.t_grxx T1 (cost=0.29..20.29 rows=10 width=9) Output: t1.dwbh, t1.grbh, t1.xm, t1.xb T1.nl Index Cond: (t1.dwbh):: text = '1001'::text)-> Index Scan using idx_t_jfxx_grbh on public.t_jfxx T2 (cost=0.29..8.31 rows=1 width=13) Output: t2.grbh, t2.ny, t2.je Index Cond: (t2.grbh):: text = (t1.grbh):: text)
Start gdb trace
(gdb) b make_rel_from_joinlistBreakpoint 1 at 0x73f0d3: file allpaths.c, line 2617. (gdb) cContinuing.Breakpoint 1, make_rel_from_joinlist (root=0x176c750, joinlist=0x179e480) at allpaths.c:26172617 levels_needed = list_length (joinlist)
Go to the make_rel_from_joinlist function and view joinlist. The Node in the linked list is RangeTblRef,rindex, respectively, on 1-3-4.
(gdb) p * joinlist$1 = {type = T_List, length = 3, head = 0x17a0448, tail = 0x17a0408} (gdb) p * (Node *) joinlist- > head- > data.ptr_value$2 = {type = T_RangeTblRef} (RangeTblRef *) joinlist- > head- > data.ptr_value$3 = {type = T_RangeTblRef, rtindex = 1} (gdb) p * (RangeTblRef *) joinlist- > head- > next- > data.ptr_value$4 = {type = T_RangeTblRef Rtindex = 3} (gdb) p * (RangeTblRef *) joinlist- > head- > next- > next- > data.ptr_value$5 = {type = T_RangeTblRef, rtindex = 4}
The number of Node in the linked list is 3 level levels needed3.
(gdb) n2619 if (levels_needed = geqo_threshold) (gdb) 2677 return standard_join_search (root, levels_needed, initial_rels); (gdb) p geqo_threshold$7 = 12
Enter the function standard_join_search
(gdb) stepstandard_join_search (root=0x176c750, levels_needed=3, initial_rels=0x17a6308) at allpaths.c:27332733 root- > join_rel_level = (List * *) palloc0 ((levels_needed + 1) * sizeof (List *))
Start to construct 2-> N rel linked lists corresponding to item
(gdb) 2746 join_search_one_level (root, lev); (gdb) n2757 foreach (lc, root- > join_rel_ level])
Call the function join_search_one_level to see root- > join_rel_ level [j]
(gdb) p * root- > join_rel_level [2] $10 = {type = T_List, length = 2, head = 0x17a67a8, tail = 0x17a6ec0}
View the RelOptInfo in the linked list
(gdb) p * (RelOptInfo *) root- > join_rel_level [2]-> head- > data.ptr_value$12 = {type = T_RelOptInfo, reloptkind = RELOPT_JOINREL, relids = 0x17a65d0, rows = 10, consider_startup = false, consider_param_startup = false, consider_parallel = true, reltarget = 0x17a65e8, pathlist = 0x17a68a8, ppilist = 0x0, partial_pathlist = 0x0, cheapest_startup_path = 0x0, cheapest_total_path = 0x0, cheapest_unique_path = 0x0, cheapest_parameterized_paths = 0x0, direct_lateral_relids = direct_lateral_relids Lateral_relids = 0x0, relid = 0, reltablespace = 0, rtekind = RTE_JOIN, min_attr = 0, max_attr = 0, attr_needed = 0x0, attr_widths = 0x0, lateral_vars = 0x0, lateral_referencers = 0x0, indexlist = 0x0, statlist = 0x0, pages = 0, tuples = 0, allvisfrac = 0, subroot = 0x0, subplan_params = 0x0, rel_parallel_workers =-1, serverid = 0, userid = 0, useridiscurrent = false, fdwroutine = 0x0, fdw_private = 0x0, unique_for_rels = 0x0 Non_unique_for_rels = 0x0, baserestrictinfo = 0x0, baserestrictcost = {startup = 0, per_tuple = 0}, baserestrict_min_security = 4294967295, joininfo = 0x0, has_eclass_joins = true, top_parent_relids = 0x0, part_scheme = 0x0, nparts = 0, boundinfo = 0x0, partition_qual = 0x0, part_rels = 0x0, partexprs = 0x0, nullable_partexprs = 0x0 Partitioned_child_rels = 0x0} (gdb) p * (RelOptInfo *) root- > join_rel_level [2]-> head- > next- > data.ptr_value$13 = {type = T_RelOptInfo, reloptkind = RELOPT_JOINREL, relids = 0x17a68d8, rows = 10, consider_startup = false, consider_param_startup = false, consider_parallel = true, reltarget = 0x17a6cd0, pathlist = 0x17a7720, ppilist = 0x0, partial_pathlist = 0x0, cheapest_startup_path = 0x0, cheapest_total_path = 0x0, cheapest_unique_path = 0x0, cheapest_parameterized_paths = cheapest_parameterized_paths Direct_lateral_relids = 0x0, lateral_relids = 0x0, relid = 0, reltablespace = 0, rtekind = RTE_JOIN, min_attr = 0, max_attr = 0, attr_needed = 0x0, attr_widths = 0x0, lateral_vars = 0x0, lateral_referencers = 0x0, indexlist = 0x0, statlist = 0x0, pages = 0, tuples = 0, allvisfrac = 0, subroot = 0x0, subplan_params = 0x0, rel_parallel_workers =-1, serverid = 0, userid = 0, useridiscurrent = false, fdwroutine = 0x0, 0x0 = fdw_private Unique_for_rels = 0x0, non_unique_for_rels = 0x0, baserestrictinfo = 0x0, baserestrictcost = {startup = 0, per_tuple = 0}, baserestrict_min_security = 4294967295, joininfo = 0x0, has_eclass_joins = true, top_parent_relids = 0x0, part_scheme = 0x0, nparts = 0, boundinfo = 0x0, partition_qual = 0x0, part_rels = 0x0, partexprs = 0x0, nullable_partexprs = 0x0, partitioned_child_rels = 0x0}
View relids in RelOptInfo
Through relids, we can know that the first RelOptInfo is the Relation generated by the rel connection No. 3, and the second RelOptInfo is the Relation generated by the rel connection No. 3.
(gdb) set $roi1= (RelOptInfo *) root- > join_rel_level [2]-> head- > data.ptr_value (gdb) set $roi2= (RelOptInfo *) root- > join_rel_level [2]-> head- > next- > data.ptr_value (gdb) p * $roi1- > relids$16 = {nwords = 1, words = 0x17a65d4} (gdb) p * $roi1- > relids- > words$17 = 10-- > 2 + 8-- > 1Green3 rel (gdb) p * $roi2- > relids- > words$18 = 24-> 8 + 16-> rel 4
Look at the pathlist in the first RelOptInfo. The linked list has two Node, both of type T_NestPath (nested join), with a total cost of 28.69 and 4308.57, respectively.
(gdb) p * $roi1- > pathlist$19 = {type = T_List, length = 2, head = 0x17a6888, tail = 0x17a6a10} (gdb) p * (Node *) $roi1- > pathlist- > head- > data.ptr_value$20 = {type = T_NestPath} (gdb) p * (NestPath *) $roi1- > pathlist- > head- > data.ptr_value$21 = {path = {type = T_NestPath, pathtype = T_NestLoop, parent = 0x17a63c0, pathtarget = 0x17a65e8, param_info = 0x0, parallel_aware = parallel_aware, false = false, false = 0, false = 10 Startup_cost = 0.577500000000001, total_cost = 28.688484322533327, pathkeys = 0x0}, jointype = JOIN_INNER, inner_unique = false, outerjoinpath = 0x17a2638, innerjoinpath = 0x17a2908, joinrestrictinfo = 0x0} (gdb) p * (Node *) $roi1- > pathlist- > head- > next- > data.ptr_value$22 = {type = T_NestPath} (gdb) p * (NestPath *) $roi1- > pathlist- > head- > next- > data.ptr_value$23 = {path = {type = T_NestPath, pathtype = T_NestLoop, parent = parent, 0x17a63c0 = 0x17a63c0, pathtarget = pathtarget Parallel_aware = false, parallel_safe = true, parallel_workers = 0, rows = 10, startup_cost = 0.57750000000000001, total_cost = 4308.5748727883229, pathkeys = 0x17a3650}, jointype = JOIN_INNER, inner_unique = false, outerjoinpath = 0x17a3190, innerjoinpath = 0x17a68f0, joinrestrictinfo = 0x0}
Looking at the pathlist in the second RelOptInfo, there is only 1 Node, type T_NestPath (nested join), and the total cost is 103.49
(gdb) p * $roi2- > pathlist$24 = {type = T_List, length = 1, head = 0x17a7700, tail = 0x17a7700} (gdb) p * (Node *) $roi2- > pathlist- > head- > data.ptr_value$27 = {type = T_NestPath} (gdb) p * (NestPath *) $roi2- > pathlist- > head- > data.ptr_value$28 = {path = {type = T_NestPath, pathtype = T_NestLoop, parent = 0x17a6ac0, pathtarget = 0x17a6cd0, param_info = 0x0, parallel_aware = parallel_aware, false = false, false = 0, false = 10 Startup_cost = 0.58499999999999996, total_cost = 103.48598432253331, pathkeys = 0x0}, jointype = JOIN_INNER, inner_unique = false, outerjoinpath = 0x17a2908, innerjoinpath = 0x17a5470, joinrestrictinfo = 0x0}
The lowest cost access path is set through the set_cheapest function, and the results are stored in cheapest_startup_path and cheapest_total_path
(gdb) 2773 set_cheapest (rel); (gdb) 2757 foreach (lc, root- > join_rel_ level [lev])... (gdb) p * $roi1 $35 =..., cheapest_startup_path = 0x17a67f8, cheapest_total_path = 0x17a67f8,... (gdb) p * $roi2 $36 =..., cheapest_startup_path = 0x17a7750, cheapest_total_path = 0x17a7750,.
Continue the cycle, and at this time lev=3
(gdb) n2737 for (lev = 2) Lev join_rel_level [3] $41 = {type = T_List, length = 1, head = 0x17a8090, tail = 0x17a8090} (gdb) p * (RelOptInfo *) root- > join_rel_level [3]-> head- > data.ptr_value$42 = {type = T_RelOptInfo, reloptkind = RELOPT_JOINREL, relids = 0x17a74d8, rows = 10, consider_startup = false, consider_param_startup = false, consider_parallel = true, reltarget = 0x17a7e40, pathlist = 0x17a8258, ppilist = 0x0, partial_pathlist = 0x0, cheapest_startup_path = cheapest_startup_path Cheapest_total_path = 0x0, cheapest_unique_path = 0x0, cheapest_parameterized_paths = 0x0, direct_lateral_relids = 0x0, lateral_relids = 0x0, relid = 0, reltablespace = 0, rtekind = RTE_JOIN, min_attr = 0, max_attr = 0, attr_needed = 0x0, attr_widths = 0x0, lateral_vars = 0x0, lateral_referencers = 0x0, indexlist = 0x0, statlist = 0x0, pages = 0, tuples = 0, allvisfrac = 0, subroot = 0x0, subplan_params = 0x0, rel_parallel_workers =-1 Serverid = 0, userid = 0, useridiscurrent = false, fdwroutine = 0x0, fdw_private = 0x0, unique_for_rels = 0x0, non_unique_for_rels = 0x0, baserestrictinfo = 0x0, baserestrictcost = {startup = 0, per_tuple = 0}, baserestrict_min_security = 4294967295, joininfo = 0x0, has_eclass_joins = false, top_parent_relids = 0x0, part_scheme = 0x0, nparts = 0, boundinfo = 0x0, partition_qual = 0x0, part_rels = 0x0, partexprs = 0x0, nullable_partexprs = nullable_partexprs Partitioned_child_rels = 0x0}
If you look at pathlist, there is only 1 element of type NestPath, and the cost of the access path is 111.89
(gdb) set $roi= (RelOptInfo *) root- > join_rel_level [3]-> head- > data.ptr_value (gdb) p * $roi- > pathlist$44 = {type = T_List, length = 1, head = 0x17a8238, tail = 0x17a8238} (gdb) p * (Node *) $roi- > pathlist- > head- > data.ptr_value$45 = {type = T_NestPath} (gdb) p * (NestPath *) $roi- > pathlist- > head- > data.ptr_value$46 = {path = {type = T_NestPath, pathtype = pathtype, T_NestLoop = T_NestLoop, T_NestLoop = T_NestLoop Param_info = 0x0, parallel_aware = false, parallel_safe = true, parallel_workers = 0, rows = 10, startup_cost = 0.87, total_cost = 111.88848432253332, pathkeys = 0x0}, jointype = JOIN_INNER, inner_unique = false, outerjoinpath = 0x17a67f8, innerjoinpath = 0x17a5470, joinrestrictinfo = 0x0}
Get the final result
... 2792 return rel (gdb) p * rel$47 = {type = T_RelOptInfo, reloptkind = RELOPT_JOINREL, relids = 0x17a74d8, rows = 10, consider_startup = false, consider_param_startup = false, consider_parallel = true, reltarget = 0x17a7e40, pathlist = 0x17a8258, ppilist = 0x0, partial_pathlist = 0x0, cheapest_startup_path = 0x17a8318, cheapest_total_path = 0x17a8318, cheapest_unique_path = 0x0, cheapest_parameterized_paths = 0x17a89b0, direct_lateral_relids = 0x0, lateral_relids = 0x0, relid = 0, reltablespace = 0, reltablespace = reltablespace Min_attr = 0, max_attr = 0, attr_needed = 0x0, attr_widths = 0x0, lateral_vars = 0x0, lateral_referencers = 0x0, indexlist = 0x0, statlist = 0x0, pages = 0, tuples = 0, allvisfrac = 0, subroot = 0x0, subplan_params = 0x0, rel_parallel_workers =-1, serverid = 0, userid = 0, useridiscurrent = false, fdwroutine = 0x0, fdw_private = 0x0, unique_for_rels = 0x0, non_unique_for_rels = 0x0, baserestrictinfo = 0x0, 0x0 = {baserestrictcost = 0 Per_tuple = 0}, baserestrict_min_security = 4294967295, joininfo = 0x0, has_eclass_joins = false, top_parent_relids = 0x0, part_scheme = 0x0, nparts = 0, boundinfo = 0x0, partition_qual = 0x0, part_rels = 0x0, partexprs = 0x0, nullable_partexprs = 0x0, partitioned_child_rels = 0x0} (gdb) p * rel- > cheapest_total_path$48 = {type = T_NestPath, pathtype = T_NestLoop, parent = 0x17a7c30, pathtarget = 0x17a7e40, param_info = 0x0, parallel_aware = parallel_aware Parallel_safe = true, parallel_workers = 0, rows = 10, startup_cost = 0.87, total_cost = 111.88848432253332, pathkeys = 0x0} so far The study of "make_rel_from_joinlist function Analysis in PostgreSQL" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.