Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9140cf8

Browse files
committed
Associate partitioning information with each RelOptInfo.
This is not used for anything yet, but it is necessary infrastructurefor partition-wise join and for partition pruning without constraintexclusion.Ashutosh Bapat, reviewed by Amit Langote and with quite a few changes,mostly cosmetic, by me. Additional review and testing of this patchseries by Antonin Houska, Amit Khandekar, Rafia Sabih, RajkumarRaghuwanshi, Thomas Munro, and Dilip Kumar.Discussion:http://postgr.es/m/CAFjFpRfneFG3H+F6BaiXemMrKF+FY-POpx3Ocy+RiH3yBmXSNw@mail.gmail.com
1 parent7b86c2a commit9140cf8

File tree

3 files changed

+249
-3
lines changed

3 files changed

+249
-3
lines changed

‎src/backend/optimizer/util/plancat.c

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,10 @@ static List *get_relation_constraints(PlannerInfo *root,
6868
staticList*build_index_tlist(PlannerInfo*root,IndexOptInfo*index,
6969
RelationheapRelation);
7070
staticList*get_relation_statistics(RelOptInfo*rel,Relationrelation);
71+
staticvoidset_relation_partition_info(PlannerInfo*root,RelOptInfo*rel,
72+
Relationrelation);
73+
staticPartitionSchemefind_partition_scheme(PlannerInfo*root,Relationrel);
74+
staticList**build_baserel_partition_key_exprs(Relationrelation,Indexvarno);
7175

7276
/*
7377
* get_relation_info -
@@ -420,6 +424,13 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
420424
/* Collect info about relation's foreign keys, if relevant */
421425
get_relation_foreign_keys(root,rel,relation,inhparent);
422426

427+
/*
428+
* Collect info about relation's partitioning scheme, if any. Only
429+
* inheritance parents may be partitioned.
430+
*/
431+
if (inhparent&&relation->rd_rel->relkind==RELKIND_PARTITIONED_TABLE)
432+
set_relation_partition_info(root,rel,relation);
433+
423434
heap_close(relation,NoLock);
424435

425436
/*
@@ -1802,3 +1813,151 @@ has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
18021813
heap_close(relation,NoLock);
18031814
returnresult;
18041815
}
1816+
1817+
/*
1818+
* set_relation_partition_info
1819+
*
1820+
* Set partitioning scheme and related information for a partitioned table.
1821+
*/
1822+
staticvoid
1823+
set_relation_partition_info(PlannerInfo*root,RelOptInfo*rel,
1824+
Relationrelation)
1825+
{
1826+
PartitionDescpartdesc;
1827+
1828+
Assert(relation->rd_rel->relkind==RELKIND_PARTITIONED_TABLE);
1829+
1830+
partdesc=RelationGetPartitionDesc(relation);
1831+
rel->part_scheme=find_partition_scheme(root,relation);
1832+
Assert(partdesc!=NULL&&rel->part_scheme!=NULL);
1833+
rel->boundinfo=partdesc->boundinfo;
1834+
rel->nparts=partdesc->nparts;
1835+
rel->partexprs=build_baserel_partition_key_exprs(relation,rel->relid);
1836+
}
1837+
1838+
/*
1839+
* find_partition_scheme
1840+
*
1841+
* Find or create a PartitionScheme for this Relation.
1842+
*/
1843+
staticPartitionScheme
1844+
find_partition_scheme(PlannerInfo*root,Relationrelation)
1845+
{
1846+
PartitionKeypartkey=RelationGetPartitionKey(relation);
1847+
ListCell*lc;
1848+
intpartnatts;
1849+
PartitionSchemepart_scheme;
1850+
1851+
/* A partitioned table should have a partition key. */
1852+
Assert(partkey!=NULL);
1853+
1854+
partnatts=partkey->partnatts;
1855+
1856+
/* Search for a matching partition scheme and return if found one. */
1857+
foreach(lc,root->part_schemes)
1858+
{
1859+
part_scheme=lfirst(lc);
1860+
1861+
/* Match partitioning strategy and number of keys. */
1862+
if (partkey->strategy!=part_scheme->strategy||
1863+
partnatts!=part_scheme->partnatts)
1864+
continue;
1865+
1866+
/* Match the partition key types. */
1867+
if (memcmp(partkey->partopfamily,part_scheme->partopfamily,
1868+
sizeof(Oid)*partnatts)!=0||
1869+
memcmp(partkey->partopcintype,part_scheme->partopcintype,
1870+
sizeof(Oid)*partnatts)!=0||
1871+
memcmp(partkey->parttypcoll,part_scheme->parttypcoll,
1872+
sizeof(Oid)*partnatts)!=0)
1873+
continue;
1874+
1875+
/*
1876+
* Length and byval information should match when partopcintype
1877+
* matches.
1878+
*/
1879+
Assert(memcmp(partkey->parttyplen,part_scheme->parttyplen,
1880+
sizeof(int16)*partnatts)==0);
1881+
Assert(memcmp(partkey->parttypbyval,part_scheme->parttypbyval,
1882+
sizeof(bool)*partnatts)==0);
1883+
1884+
/* Found matching partition scheme. */
1885+
returnpart_scheme;
1886+
}
1887+
1888+
/*
1889+
* Did not find matching partition scheme. Create one copying relevant
1890+
* information from the relcache. Instead of copying whole arrays, copy
1891+
* the pointers in relcache. It's safe to do so since
1892+
* RelationClearRelation() wouldn't change it while planner is using it.
1893+
*/
1894+
part_scheme= (PartitionScheme)palloc0(sizeof(PartitionSchemeData));
1895+
part_scheme->strategy=partkey->strategy;
1896+
part_scheme->partnatts=partkey->partnatts;
1897+
part_scheme->partopfamily=partkey->partopfamily;
1898+
part_scheme->partopcintype=partkey->partopcintype;
1899+
part_scheme->parttypcoll=partkey->parttypcoll;
1900+
part_scheme->parttyplen=partkey->parttyplen;
1901+
part_scheme->parttypbyval=partkey->parttypbyval;
1902+
1903+
/* Add the partitioning scheme to PlannerInfo. */
1904+
root->part_schemes=lappend(root->part_schemes,part_scheme);
1905+
1906+
returnpart_scheme;
1907+
}
1908+
1909+
/*
1910+
* build_baserel_partition_key_exprs
1911+
*
1912+
* Collects partition key expressions for a given base relation. Any single
1913+
* column partition keys are converted to Var nodes. All Var nodes are set
1914+
* to the given varno. The partition key expressions are returned as an array
1915+
* of single element lists to be stored in RelOptInfo of the base relation.
1916+
*/
1917+
staticList**
1918+
build_baserel_partition_key_exprs(Relationrelation,Indexvarno)
1919+
{
1920+
PartitionKeypartkey=RelationGetPartitionKey(relation);
1921+
intpartnatts;
1922+
intcnt;
1923+
List**partexprs;
1924+
ListCell*lc;
1925+
1926+
/* A partitioned table should have a partition key. */
1927+
Assert(partkey!=NULL);
1928+
1929+
partnatts=partkey->partnatts;
1930+
partexprs= (List**)palloc(sizeof(List*)*partnatts);
1931+
lc=list_head(partkey->partexprs);
1932+
1933+
for (cnt=0;cnt<partnatts;cnt++)
1934+
{
1935+
Expr*partexpr;
1936+
AttrNumberattno=partkey->partattrs[cnt];
1937+
1938+
if (attno!=InvalidAttrNumber)
1939+
{
1940+
/* Single column partition key is stored as a Var node. */
1941+
Assert(attno>0);
1942+
1943+
partexpr= (Expr*)makeVar(varno,attno,
1944+
partkey->parttypid[cnt],
1945+
partkey->parttypmod[cnt],
1946+
partkey->parttypcoll[cnt],0);
1947+
}
1948+
else
1949+
{
1950+
if (lc==NULL)
1951+
elog(ERROR,"wrong number of partition key expressions");
1952+
1953+
/* Re-stamp the expression with given varno. */
1954+
partexpr= (Expr*)copyObject(lfirst(lc));
1955+
ChangeVarNodes((Node*)partexpr,1,varno,0);
1956+
lc=lnext(lc);
1957+
}
1958+
1959+
partexprs[cnt]=list_make1(partexpr);
1960+
}
1961+
1962+
returnpartexprs;
1963+
}

‎src/backend/optimizer/util/relnode.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
146146
rel->baserestrict_min_security=UINT_MAX;
147147
rel->joininfo=NIL;
148148
rel->has_eclass_joins= false;
149+
rel->part_scheme=NULL;
150+
rel->nparts=0;
151+
rel->boundinfo=NULL;
152+
rel->part_rels=NULL;
153+
rel->partexprs=NULL;
149154

150155
/*
151156
* Pass top parent's relids down the inheritance hierarchy. If the parent
@@ -218,18 +223,41 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
218223
if (rte->inh)
219224
{
220225
ListCell*l;
226+
intnparts=rel->nparts;
227+
intcnt_parts=0;
228+
229+
if (nparts>0)
230+
rel->part_rels= (RelOptInfo**)
231+
palloc(sizeof(RelOptInfo*)*nparts);
221232

222233
foreach(l,root->append_rel_list)
223234
{
224235
AppendRelInfo*appinfo= (AppendRelInfo*)lfirst(l);
236+
RelOptInfo*childrel;
225237

226238
/* append_rel_list contains all append rels; ignore others */
227239
if (appinfo->parent_relid!=relid)
228240
continue;
229241

230-
(void)build_simple_rel(root,appinfo->child_relid,
231-
rel);
242+
childrel=build_simple_rel(root,appinfo->child_relid,
243+
rel);
244+
245+
/* Nothing more to do for an unpartitioned table. */
246+
if (!rel->part_scheme)
247+
continue;
248+
249+
/*
250+
* The order of partition OIDs in append_rel_list is the same as
251+
* the order in the PartitionDesc, so the order of part_rels will
252+
* also match the PartitionDesc. See expand_partitioned_rtentry.
253+
*/
254+
Assert(cnt_parts<nparts);
255+
rel->part_rels[cnt_parts]=childrel;
256+
cnt_parts++;
232257
}
258+
259+
/* We should have seen all the child partitions. */
260+
Assert(cnt_parts==nparts);
233261
}
234262

235263
returnrel;
@@ -527,6 +555,11 @@ build_join_rel(PlannerInfo *root,
527555
joinrel->joininfo=NIL;
528556
joinrel->has_eclass_joins= false;
529557
joinrel->top_parent_relids=NULL;
558+
joinrel->part_scheme=NULL;
559+
joinrel->nparts=0;
560+
joinrel->boundinfo=NULL;
561+
joinrel->part_rels=NULL;
562+
joinrel->partexprs=NULL;
530563

531564
/* Compute information relevant to the foreign relations. */
532565
set_foreign_rel_properties(joinrel,outer_rel,inner_rel);

‎src/include/nodes/relation.h

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,9 @@ typedef struct PlannerInfo
266266
List*distinct_pathkeys;/* distinctClause pathkeys, if any */
267267
List*sort_pathkeys;/* sortClause pathkeys, if any */
268268

269+
List*part_schemes;/* Canonicalised partition schemes used in the
270+
* query. */
271+
269272
List*initial_rels;/* RelOptInfos we are now trying to join */
270273

271274
/* Use fetch_upper_rel() to get any particular upper rel */
@@ -326,6 +329,34 @@ typedef struct PlannerInfo
326329
((root)->simple_rte_array ? (root)->simple_rte_array[rti] : \
327330
rt_fetch(rti, (root)->parse->rtable))
328331

332+
/*
333+
* If multiple relations are partitioned the same way, all such partitions
334+
* will have a pointer to the same PartitionScheme. A list of PartitionScheme
335+
* objects is attached to the PlannerInfo. By design, the partition scheme
336+
* incorporates only the general properties of the partition method (LIST vs.
337+
* RANGE, number of partitioning columns and the type information for each)
338+
* and not the specific bounds.
339+
*
340+
* We store the opclass-declared input data types instead of the partition key
341+
* datatypes since the former rather than the latter are used to compare
342+
* partition bounds. Since partition key data types and the opclass declared
343+
* input data types are expected to be binary compatible (per ResolveOpClass),
344+
* both of those should have same byval and length properties.
345+
*/
346+
typedefstructPartitionSchemeData
347+
{
348+
charstrategy;/* partition strategy */
349+
int16partnatts;/* number of partition attributes */
350+
Oid*partopfamily;/* OIDs of operator families */
351+
Oid*partopcintype;/* OIDs of opclass declared input data types */
352+
Oid*parttypcoll;/* OIDs of collations of partition keys. */
353+
354+
/* Cached information about partition key data types. */
355+
int16*parttyplen;
356+
bool*parttypbyval;
357+
}PartitionSchemeData;
358+
359+
typedefstructPartitionSchemeData*PartitionScheme;
329360

330361
/*----------
331362
* RelOptInfo
@@ -456,7 +487,7 @@ typedef struct PlannerInfo
456487
*other rels for which we have tried and failed to prove
457488
*this one unique
458489
*
459-
* The presence of theremaining fields depends on the restrictions
490+
* The presence of thefollowing fields depends on the restrictions
460491
* and joins that the relation participates in:
461492
*
462493
*baserestrictinfo - List of RestrictInfo nodes, containing info about
@@ -487,6 +518,21 @@ typedef struct PlannerInfo
487518
* We store baserestrictcost in the RelOptInfo (for base relations) because
488519
* we know we will need it at least once (to price the sequential scan)
489520
* and may need it multiple times to price index scans.
521+
*
522+
* If the relation is partitioned, these fields will be set:
523+
*
524+
* part_scheme - Partitioning scheme of the relation
525+
* boundinfo - Partition bounds
526+
* nparts - Number of partitions
527+
* part_rels - RelOptInfos for each partition
528+
* partexprs - Partition key expressions
529+
*
530+
* Note: A base relation always has only one set of partition keys, but a join
531+
* relation may have as many sets of partition keys as the number of relations
532+
* being joined. partexprs is an array containing part_scheme->partnatts
533+
* elements, each of which is a list of partition key expressions. For a base
534+
* relation each list contains only one expression, but for a join relation
535+
* there can be one per baserel.
490536
*----------
491537
*/
492538
typedefenumRelOptKind
@@ -592,6 +638,14 @@ typedef struct RelOptInfo
592638

593639
/* used by "other" relations */
594640
Relidstop_parent_relids;/* Relids of topmost parents */
641+
642+
/* used for partitioned relations */
643+
PartitionSchemepart_scheme;/* Partitioning scheme. */
644+
intnparts;/* number of partitions */
645+
structPartitionBoundInfoData*boundinfo;/* Partition bounds */
646+
structRelOptInfo**part_rels;/* Array of RelOptInfos of partitions,
647+
* stored in the same order of bounds */
648+
List**partexprs;/* Partition key expressions. */
595649
}RelOptInfo;
596650

597651
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp