Greatly speed up "\d tablename" on servers with many tables

We introduce a filter to every query on pg_class to automatically remove
shards. This is useful to make sure \d and PgAdmin are not cluttered
with shards. However, the way we were introducing this filter was using
`securityQuals` which can have negative impact on query performance.

On clusters with 100k+ tables this could cause a simple "\d tablename"
command to take multiple seconds, because a skipped optimization by
Postgres causes a full table scan. This changes the code to introduce
this filter in the regular `quals` list instead of in `securityQuals`.
Which causes Postgres to use the intended optimization again.

For reference this was initially reported as a Postgres issue by me:
https://www.postgresql.org/message-id/flat/4189982.1712785863%40sss.pgh.pa.us#b87421293b362d581ea8677e3bfea920
fix-all
Jelte Fennema-Nio 2024-04-11 12:13:32 +02:00
parent 41d99249d9
commit f711dfe8ae
1 changed files with 16 additions and 5 deletions

View File

@ -460,8 +460,19 @@ FilterShardsFromPgclass(Node *node, void *context)
MemoryContext originalContext = MemoryContextSwitchTo(queryContext);
/* add NOT relation_is_a_known_shard(oid) to the security quals of the RTE */
rangeTableEntry->securityQuals =
list_make1(CreateRelationIsAKnownShardFilter(varno));
Node *oldQuals = query->jointree->quals;
if (oldQuals)
{
query->jointree->quals = (Node *) makeBoolExpr(
AND_EXPR,
list_make2(oldQuals, CreateRelationIsAKnownShardFilter(varno)),
-1);
}
else
{
query->jointree->quals = (Node *) CreateRelationIsAKnownShardFilter(
varno);
}
MemoryContextSwitchTo(originalContext);
}
@ -496,9 +507,9 @@ CreateRelationIsAKnownShardFilter(int pgClassVarno)
funcExpr->location = -1;
funcExpr->args = list_make1(oidVar);
BoolExpr *notExpr = makeNode(BoolExpr);
notExpr->boolop = NOT_EXPR;
notExpr->args = list_make1(funcExpr);
BooleanTest *notExpr = makeNode(BooleanTest);
notExpr->booltesttype = IS_NOT_TRUE;
notExpr->arg = (Expr *) funcExpr;
notExpr->location = -1;
return (Node *) notExpr;