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

Commitbd12080

Browse files
committed
Preserve pg_attribute.attstattarget across REINDEX CONCURRENTLY
For an index, attstattarget can be updated using ALTER INDEX SETSTATISTICS. This data was lost on the new index after REINDEXCONCURRENTLY.The update of this field is done when the old and new indexes areswapped to make the fix back-patchable. Another approach we could lookafter in the long-term is to change index_create() to pass the wantedvalues of attstattarget when creating the new relation, but, as thiswould cause an ABI breakage this can be done only on HEAD.Reported-by: Ronan DunklauAuthor: Michael PaquierReviewed-by: Ronan Dunklau, Tomas VondraDiscussion:https://postgr.es/m/16628084.uLZWGnKmhe@laptop-ronandBackpatch-through: 12
1 parentcd142e0 commitbd12080

File tree

5 files changed

+107
-0
lines changed

5 files changed

+107
-0
lines changed

‎src/backend/catalog/index.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1884,6 +1884,62 @@ index_concurrently_swap(Oid newIndexId, Oid oldIndexId, const char *oldName)
18841884
/* Copy data of pg_statistic from the old index to the new one */
18851885
CopyStatistics(oldIndexId,newIndexId);
18861886

1887+
/* Copy pg_attribute.attstattarget for each index attribute */
1888+
{
1889+
HeapTupleattrTuple;
1890+
Relationpg_attribute;
1891+
SysScanDescscan;
1892+
ScanKeyDatakey[1];
1893+
1894+
pg_attribute=table_open(AttributeRelationId,RowExclusiveLock);
1895+
ScanKeyInit(&key[0],
1896+
Anum_pg_attribute_attrelid,
1897+
BTEqualStrategyNumber,F_OIDEQ,
1898+
ObjectIdGetDatum(newIndexId));
1899+
scan=systable_beginscan(pg_attribute,AttributeRelidNumIndexId,
1900+
true,NULL,1,key);
1901+
1902+
while (HeapTupleIsValid((attrTuple=systable_getnext(scan))))
1903+
{
1904+
Form_pg_attributeatt= (Form_pg_attribute)GETSTRUCT(attrTuple);
1905+
Datumrepl_val[Natts_pg_attribute];
1906+
boolrepl_null[Natts_pg_attribute];
1907+
boolrepl_repl[Natts_pg_attribute];
1908+
intattstattarget;
1909+
HeapTuplenewTuple;
1910+
1911+
/* Ignore dropped columns */
1912+
if (att->attisdropped)
1913+
continue;
1914+
1915+
/*
1916+
* Get attstattarget from the old index and refresh the new value.
1917+
*/
1918+
attstattarget=get_attstattarget(oldIndexId,att->attnum);
1919+
1920+
/* no need for a refresh if both match */
1921+
if (attstattarget==att->attstattarget)
1922+
continue;
1923+
1924+
memset(repl_val,0,sizeof(repl_val));
1925+
memset(repl_null, false,sizeof(repl_null));
1926+
memset(repl_repl, false,sizeof(repl_repl));
1927+
1928+
repl_repl[Anum_pg_attribute_attstattarget-1]= true;
1929+
repl_val[Anum_pg_attribute_attstattarget-1]=Int32GetDatum(attstattarget);
1930+
1931+
newTuple=heap_modify_tuple(attrTuple,
1932+
RelationGetDescr(pg_attribute),
1933+
repl_val,repl_null,repl_repl);
1934+
CatalogTupleUpdate(pg_attribute,&newTuple->t_self,newTuple);
1935+
1936+
heap_freetuple(newTuple);
1937+
}
1938+
1939+
systable_endscan(scan);
1940+
table_close(pg_attribute,RowExclusiveLock);
1941+
}
1942+
18871943
/* Close relations */
18881944
table_close(pg_class,RowExclusiveLock);
18891945
table_close(pg_index,RowExclusiveLock);

‎src/backend/utils/cache/lsyscache.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -871,6 +871,33 @@ get_attnum(Oid relid, const char *attname)
871871
returnInvalidAttrNumber;
872872
}
873873

874+
/*
875+
* get_attstattarget
876+
*
877+
*Given the relation id and the attribute number,
878+
*return the "attstattarget" field from the attribute relation.
879+
*
880+
*Errors if not found.
881+
*/
882+
int
883+
get_attstattarget(Oidrelid,AttrNumberattnum)
884+
{
885+
HeapTupletp;
886+
Form_pg_attributeatt_tup;
887+
intresult;
888+
889+
tp=SearchSysCache2(ATTNUM,
890+
ObjectIdGetDatum(relid),
891+
Int16GetDatum(attnum));
892+
if (!HeapTupleIsValid(tp))
893+
elog(ERROR,"cache lookup failed for attribute %d of relation %u",
894+
attnum,relid);
895+
att_tup= (Form_pg_attribute)GETSTRUCT(tp);
896+
result=att_tup->attstattarget;
897+
ReleaseSysCache(tp);
898+
returnresult;
899+
}
900+
874901
/*
875902
* get_attgenerated
876903
*

‎src/include/utils/lsyscache.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ extern Oidget_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype,
9090
int16procnum);
9191
externchar*get_attname(Oidrelid,AttrNumberattnum,boolmissing_ok);
9292
externAttrNumberget_attnum(Oidrelid,constchar*attname);
93+
externintget_attstattarget(Oidrelid,AttrNumberattnum);
9394
externcharget_attgenerated(Oidrelid,AttrNumberattnum);
9495
externOidget_atttype(Oidrelid,AttrNumberattnum);
9596
externvoidget_atttypetypmodcoll(Oidrelid,AttrNumberattnum,

‎src/test/regress/expected/create_index.out

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2559,6 +2559,7 @@ CREATE UNIQUE INDEX concur_exprs_index_pred ON concur_exprs_tab (c1)
25592559
CREATE UNIQUE INDEX concur_exprs_index_pred_2
25602560
ON concur_exprs_tab ((1 / c1))
25612561
WHERE ('-H') >= (c2::TEXT) COLLATE "C";
2562+
ALTER INDEX concur_exprs_index_expr ALTER COLUMN 1 SET STATISTICS 100;
25622563
ANALYZE concur_exprs_tab;
25632564
SELECT starelid::regclass, count(*) FROM pg_statistic WHERE starelid IN (
25642565
'concur_exprs_index_expr'::regclass,
@@ -2638,6 +2639,20 @@ SELECT starelid::regclass, count(*) FROM pg_statistic WHERE starelid IN (
26382639
concur_exprs_index_expr | 1
26392640
(1 row)
26402641

2642+
-- attstattarget should remain intact
2643+
SELECT attrelid::regclass, attnum, attstattarget
2644+
FROM pg_attribute WHERE attrelid IN (
2645+
'concur_exprs_index_expr'::regclass,
2646+
'concur_exprs_index_pred'::regclass,
2647+
'concur_exprs_index_pred_2'::regclass)
2648+
ORDER BY 'concur_exprs_index_expr'::regclass::text, attnum;
2649+
attrelid | attnum | attstattarget
2650+
---------------------------+--------+---------------
2651+
concur_exprs_index_expr | 1 | 100
2652+
concur_exprs_index_pred | 1 | -1
2653+
concur_exprs_index_pred_2 | 1 | -1
2654+
(3 rows)
2655+
26412656
DROP TABLE concur_exprs_tab;
26422657
-- Temporary tables and on-commit actions, where CONCURRENTLY is ignored.
26432658
-- ON COMMIT PRESERVE ROWS, the default.

‎src/test/regress/sql/create_index.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,7 @@ CREATE UNIQUE INDEX concur_exprs_index_pred ON concur_exprs_tab (c1)
10791079
CREATEUNIQUE INDEXconcur_exprs_index_pred_2
10801080
ON concur_exprs_tab ((1/ c1))
10811081
WHERE ('-H')>= (c2::TEXT) COLLATE"C";
1082+
ALTERINDEX concur_exprs_index_expr ALTER COLUMN1SET STATISTICS100;
10821083
ANALYZE concur_exprs_tab;
10831084
SELECT starelid::regclass,count(*)FROM pg_statisticWHERE starelidIN (
10841085
'concur_exprs_index_expr'::regclass,
@@ -1103,6 +1104,13 @@ SELECT starelid::regclass, count(*) FROM pg_statistic WHERE starelid IN (
11031104
'concur_exprs_index_pred'::regclass,
11041105
'concur_exprs_index_pred_2'::regclass)
11051106
GROUP BY starelidORDER BY starelid::regclass::text;
1107+
-- attstattarget should remain intact
1108+
SELECT attrelid::regclass, attnum, attstattarget
1109+
FROM pg_attributeWHERE attrelidIN (
1110+
'concur_exprs_index_expr'::regclass,
1111+
'concur_exprs_index_pred'::regclass,
1112+
'concur_exprs_index_pred_2'::regclass)
1113+
ORDER BY'concur_exprs_index_expr'::regclass::text, attnum;
11061114
DROPTABLE concur_exprs_tab;
11071115

11081116
-- Temporary tables and on-commit actions, where CONCURRENTLY is ignored.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp