Re: pg_stat_statements and "IN" conditions - Mailing list pgsql-hackers
From | Álvaro Herrera |
---|---|
Subject | Re: pg_stat_statements and "IN" conditions |
Date | |
Msg-id | 202502131247.zls4jgcl2yqe@alvherre.pgsql Whole thread Raw |
In response to | pg_stat_statements and "IN" conditions (Dmitry Dolgov <9erthalion6@gmail.com>) |
List | pgsql-hackers |
On 2025-Feb-13, Dmitry Dolgov wrote: > Here is how it looks like (posting only the first patch, since we > concentrate on it). This version handles just a little more to cover > simpe cases like the implicit convertion above. The GUC is also moved > out from pgss and renamed to query_id_merge_values. On top I've added > more tests showing the impact, as well as sometimes awkward looking > normalized query I was talking about. I'm going to experiment how to > iron out the latter. Thanks! It's looking better. Some small comments -- please add the new GUC to postgresql.conf.sample. Also, how wed are you to "query_id_merge_values" as a name? It's not in any way obvious that this is about values in arrays. How about query_id_squash_arrays? Or are you thinking in having values in other types of structures squashed as well, and that this first patch does it for arrays only but you want the GUC to also control some future feature? (I think I prefer "squash" here as a verb to "merge"). > +static bool > +IsMergeableConst(Node *element) > +{ > + if (IsA(element, RelabelType)) > + element = (Node *) ((RelabelType *) element)->arg; > + > + if (IsA(element, CoerceViaIO)) > + element = (Node *) ((CoerceViaIO *) element)->arg; > + > + if(IsA(element, FuncExpr)) > + { > + FuncExpr *func = (FuncExpr *) element; > + char provolatile = func_volatile(func->funcid); I think calling func_volatile potentially once per array element is not good; this might cause dozens/thousands of identical syscache lookups. Maybe we can pass an initially NIL list from IsMergeableConstList (as List **), which IsMergeableConst fills with OIDs of functions that have been checked and found acceptable. Then the second time around we search the list first and only do func_volatile() after not finding a match. Another thing I didn't quite understand is why you did this rather baroque-looking list scan: > +static bool > +IsMergeableConstList(List *elements, Node **firstExpr, Node **lastExpr) > +{ > + ListCell *temp; > + Node *firstElem = NULL; > + > + if (elements == NIL) > + return false; > + > + if (!query_id_merge_values) > + { > + /* Merging is disabled, process everything one by one */ > + return false; > + } > + > + firstElem = linitial(elements); > + > + /* > + * If the first expression is a constant, verify if the following elements > + * are constants as well. If yes, the list is eligible for merging. > + */ > + if (IsMergeableConst(firstElem)) > + { > + foreach(temp, elements) > + { > + Node *element = lfirst(temp); > + > + if (!IsMergeableConst(element)) > + return false; > + } > + > + *firstExpr = firstElem; > + *lastExpr = llast(elements); > + return true; > + } Why not just scan the list in the straightforward way, that is foreach(temp, elements) { if (!IsMergeableConst(lfirst(temp))) return false; } *firstExpr = linitial(elements); *lastExpr = llast(elements); return true; Is there something being optimized here specifically for the first element? I don't see it. -- Álvaro Herrera PostgreSQL Developer — https://www.EnterpriseDB.com/
pgsql-hackers by date: