bug or lacking doc hint

2023-06-25 Thread Marc Millas
Hi,

I have had a perf (++) pb with a join plan  cf the pb with join plan thread.
I did simplify the thing up to when its a simple join between a 15M lines
table and a 30k lines table.
if I put in the on part something like table1.a=table2.b, Postgres does the
job in around 1 seconde.

if in the on part of the join I write table1.a=table2.b OR
substr(table1.c,x,x) =table2.d

then I have to cancel the request after  20 minutes seeing disk usage
growing and growing.

When I ask this list, David Rowley suggest to rewrite the SQL, replacing
the OR by a union.

Fine, this do work, even if a bit complex as the original SQL was a set of
intricate joins.


So, either this behaviour ( postgres unable to find an appropriate plan for
join with OR clauses)
is a true bug which is waiting to be corrected, either the doc is lacking a
chapter on which one can read that Postgres does NOT support that syntax as
soon as there is some data volumes.

So, now I am writing some kind of recipe book for the users of that DB.

What should I write ?

Marc MILLAS
Senior Architect
+33607850334
www.mokadb.com


Re: Why can't lseek the STDIN_FILENO?

2023-06-25 Thread wen-yi
OK, I see, I'm so sorry for my action.
I will ask in cpplang slack community in the future.
And really thanks for your advice.



Your,
Wen Yi





-- Original --
From:   
 "John McKown"  
  
https://unix.stackexchange.com/questions/502518/problems-when-test-whether-standard-input-is-capable-of-seeking


The bottom line from the above post is that STDIN is not seekable when it is a 
terminal.

On Fri, Jun 23, 2023, 21:17 Wen Yi <896634...@qq.com> wrote:

Hi community,
I am testing the lseek & write & read, and I write the code like this:


/*
    lseek_test.c
    Test the lseek
    Wen Yi
*/
#include 

Re: bug or lacking doc hint

2023-06-25 Thread Ron

On 6/25/23 10:01, Marc Millas wrote:

Hi,

I have had a perf (++) pb with a join plan  cf the pb with join plan thread.
I did simplify the thing up to when its a simple join between a 15M lines 
table and a 30k lines table.
if I put in the on part something like table1.a=table2.b, Postgres does 
the job in around 1 seconde.


if in the on part of the join I write table1.a=table2.b OR 
substr(table1.c,x,x) =table2.d


That left side SUBSTR() can't be good for the query optimizer.  (Or I'm old 
and still using habits picked up 25 years ago on a different RDBMS.)


Maybe a function index on table1 would help.

--
Born in Arizona, moved to Babylonia.




Re: Helping planner to chose sequential scan when it improves performance

2023-06-25 Thread Jeff Janes
On Tue, Jun 13, 2023 at 3:28 PM Patrick O'Toole 
wrote:

>  run the query twice first, then...

Is that a realistic way to run the test?  Often forcing all the data needed
for the query into memory is going to make things less realistic, not more
realistic.  Assuming the system has more stuff to do than just perform this
one query, it might be unusual for the query to find everything it needs in
memory.  Also, if you really do want to do it this way, then you should do
this for every plan.  Different plans need to access a different
collections of buffers, so prewarming just one plan will privilege that one
over the others.



>
> PLAN A (default config, effective cache size just shy of 15GB): 3.829
> seconds. A nested loop is used to probe the hash index
> `conversation_item_item_hash_index` for each row of item_text. Although the
> cost of probing once is low, a fair amount of time passes because the
> operation is repeated ~1.3 million times.
>
> PLAN B (enable_indexscan off, effective cache same as before): 3.254
> seconds (~15% speedup, sometimes 30%). Both tables are scanned sequentially
> and conversation_item is hashed before results are combined with a hash
> join.
>
> PLAN C: (random_page_cost = 8.0, instead of default 4, effective cache
> same as before): 2.959 (~23% speedup, sometimes 38%). Same overall plan as
> PLAN B, some differences in buffers and I/O. I'll note we had to get to 8.0
> before we saw a change to planner behavior; 5.0, 6.0, and 7.0 were too low
> to make a difference.
>

The difference between B and C looks like it is entirely noise, having to
do with how many buffers it found already in the cache and how many of them
needed cleaning (which causes the buffer to be dirty as the cleaned version
now needs to be written to disk) and how many dirty buffers it found that
needed to be written in order to make way to read other buffers it needs.
(This last number most generally reflects dirty buffers left around by
other things which this query encountered, not the buffers the query itself
dirtied).  None of this is likely to be reproducible, and so not worth
investigating.

And the difference between A and BC is small enough that it is unlikely to
be worth pursuing, either, even if it is reproducible.  If your apps runs
this one exact query often enough that a 30% difference is worth worrying
about, you would probably be better served by questioning the business
case.  What are you doing with 1.4 million rows once you do fetch them,
that it needs to be repeated so often?

If you think that taking a deep dive into this one query is going to
deliver knowledge which will pay off for other (so far unexamined) queries,
I suspect you are wrong. Look for queries where the misestimation is more
stark than 30% to serve as your case studies.


>
> Environment:
>
> Postgres 15.2
> Amazon RDS — db.m6g.2xlarge
>
>
> Questions:
>


> In Plan A, what factors are causing the planner to select a substantially
> slower plan despite having recent stats about number of rows?
>

Even if it were worth trying to answer this (which I think it is not),
there isn't much we can do with dummy tables containing no data.  You would
need to include a script to generate data of a size and distribution which
reproduces the given behavior.

> Is there a substantial difference between the on-the-fly hash done in
Plan B and Plan C compared to the hash-index used in Plan A? Can I assume
they are essentially the same? Perhaps there are there differences in how
they're applied?

They are pretty much entirely different.  Once jumps all over the index on
disk, the other reads the table sequentially and (due to work_mem) parcels
it out into chunks where it expects each chunk can also be read back in
sequentially as well.  About the only thing not different is that they both
involve computing a hash function.

> Is it common to see values for random_page_cost set as high as 8.0? We
would of course need to investigate whether we see a net positive or net
negative impact on other queries, to adopt this as a general setting, but
is it a proposal we should actually consider?

I've never needed to set it that high, but there is no a priori reason it
wouldn't make sense to do.  Settings that high would probably only be
suitable for HDD (rather than SSD) storage and when caching is not very
effective, which does seem to be the opposite of your situation.  So I
certainly wouldn't do it just based on the evidence at hand.

Cheers,

Jeff


>


Re: bug or lacking doc hint

2023-06-25 Thread David Rowley
On Mon, 26 Jun 2023 at 03:02, Marc Millas  wrote:
> When I ask this list, David Rowley suggest to rewrite the SQL, replacing the 
> OR by a union.
>
> Fine, this do work, even if a bit complex as the original SQL was a set of 
> intricate joins.
>
>
> So, either this behaviour ( postgres unable to find an appropriate plan for 
> join with OR clauses)
> is a true bug which is waiting to be corrected, either the doc is lacking a 
> chapter on which one can read that Postgres does NOT support that syntax as 
> soon as there is some data volumes.

The problem is that out of the 3 methods PostgreSQL uses to join
tables, only 1 of them supports join conditions with an OR clause.
Merge Join cannot do this because results can only be ordered one way
at a time.  Hash Join technically could do this, but it would require
that it built multiple hash tables. Currently, it only builds one
table.  That leaves Nested Loop as the join method to implement joins
with OR clauses. Unfortunately, nested loops are quadratic and the
join condition must be evaluated once per each cartesian product row.
That does not scale well.

Tom Lane did start some work [1] to allow the planner to convert some
queries to use UNION instead of evaluating OR clauses, but, if I
remember correctly, it didn't handle ORs in join conditions, though
perhaps having it do that would be a natural phase 2. I don't recall
why the work stopped.

> So, now I am writing some kind of recipe book for the users of that DB.
>
> What should I write ?

You're asking a public mailing list to write private documentation for
the company you work for? hmm.

David

[1] 
https://www.postgresql.org/message-id/flat/20180904015910.GA1797012%40rfd.leadboat.com#0ddccc114c74d1ddaedcb07b64530967




Re: bug or lacking doc hint

2023-06-25 Thread Marc Millas
On Sun, Jun 25, 2023 at 9:35 PM David Rowley  wrote:

> On Mon, 26 Jun 2023 at 03:02, Marc Millas  wrote:
> > When I ask this list, David Rowley suggest to rewrite the SQL, replacing
> the OR by a union.
> >
> > Fine, this do work, even if a bit complex as the original SQL was a set
> of intricate joins.
> >
> >
> > So, either this behaviour ( postgres unable to find an appropriate plan
> for join with OR clauses)
> > is a true bug which is waiting to be corrected, either the doc is
> lacking a chapter on which one can read that Postgres does NOT support that
> syntax as soon as there is some data volumes.
>
> The problem is that out of the 3 methods PostgreSQL uses to join
> tables, only 1 of them supports join conditions with an OR clause.
> Merge Join cannot do this because results can only be ordered one way
> at a time.  Hash Join technically could do this, but it would require
> that it built multiple hash tables. Currently, it only builds one
> table.  That leaves Nested Loop as the join method to implement joins
> with OR clauses. Unfortunately, nested loops are quadratic and the
> join condition must be evaluated once per each cartesian product row.
> That does not scale well.
>
> Tom Lane did start some work [1] to allow the planner to convert some
> queries to use UNION instead of evaluating OR clauses, but, if I
> remember correctly, it didn't handle ORs in join conditions, though
> perhaps having it do that would be a natural phase 2. I don't recall
> why the work stopped.
>
> > So, now I am writing some kind of recipe book for the users of that DB.
> >
> > What should I write ?
>
> You're asking a public mailing list to write private documentation for
> the company you work for? hmm.
>
looks like some kind of misunderstanding:
what I am asking is: should I , or am I allowed to write that, according to
the community,  Postgres is unable to do something ?


> David
>
> [1]
> https://www.postgresql.org/message-id/flat/20180904015910.GA1797012%40rfd.leadboat.com#0ddccc114c74d1ddaedcb07b64530967



Marc MILLAS
Senior Architect
+33607850334
www.mokadb.com


Re: Helping planner to chose sequential scan when it improves performance

2023-06-25 Thread David Rowley
On Wed, 14 Jun 2023 at 07:28, Patrick O'Toole  wrote:
> Maybe we are barking up the wrong tree with the previous questions. Are there 
> other configuration parameters we should consider first to improve 
> performance in situations like the one illustrated?

random_page_cost and effective_cache_size are the main settings which
will influence plan A vs plan B.  Larger values of
effective_cache_size will have the planner apply more seq_page_costs
to the index scan.  Lower values of effective_cache_size will mean
more pages will be assumed to cost random_page_cost.

David




Re: bug or lacking doc hint

2023-06-25 Thread Tom Lane
David Rowley  writes:
> The problem is that out of the 3 methods PostgreSQL uses to join
> tables, only 1 of them supports join conditions with an OR clause.
> Merge Join cannot do this because results can only be ordered one way
> at a time.  Hash Join technically could do this, but it would require
> that it built multiple hash tables. Currently, it only builds one
> table.  That leaves Nested Loop as the join method to implement joins
> with OR clauses. Unfortunately, nested loops are quadratic and the
> join condition must be evaluated once per each cartesian product row.

We can do better than that if the OR'd conditions are each amenable
to an index scan on one of the tables: then it can be a nestloop with
a bitmap-OR'd inner index scan.  I thought the upthread advice to
convert the substr() condition into something that could be indexed
was on-point.

> Tom Lane did start some work [1] to allow the planner to convert some
> queries to use UNION instead of evaluating OR clauses, but, if I
> remember correctly, it didn't handle ORs in join conditions, though
> perhaps having it do that would be a natural phase 2. I don't recall
> why the work stopped.

As I recall, I was having difficulty convincing myself that
de-duplication of results (for cases where the same row satisfies
more than one of the OR'd conditions) would work correctly.
You can't just blindly make it a UNION because that might remove
identical rows that *should* appear more than once in the result.

regards, tom lane




Re: bug or lacking doc hint

2023-06-25 Thread Marc Millas
On Sun, Jun 25, 2023 at 11:48 PM Tom Lane  wrote:

> David Rowley  writes:
> > The problem is that out of the 3 methods PostgreSQL uses to join
> > tables, only 1 of them supports join conditions with an OR clause.
> > Merge Join cannot do this because results can only be ordered one way
> > at a time.  Hash Join technically could do this, but it would require
> > that it built multiple hash tables. Currently, it only builds one
> > table.  That leaves Nested Loop as the join method to implement joins
> > with OR clauses. Unfortunately, nested loops are quadratic and the
> > join condition must be evaluated once per each cartesian product row.
>
> We can do better than that if the OR'd conditions are each amenable
> to an index scan on one of the tables: then it can be a nestloop with
> a bitmap-OR'd inner index scan.  I thought the upthread advice to
> convert the substr() condition into something that could be indexed
> was on-point.
>
ok. but one of the tables within the join(s) tables is 10 billions rows,
splitted in 120 partitions. Creating something like 20 more indexes to
fulfill that condition do have its own problems.

>
> > Tom Lane did start some work [1] to allow the planner to convert some
> > queries to use UNION instead of evaluating OR clauses, but, if I
> > remember correctly, it didn't handle ORs in join conditions, though
> > perhaps having it do that would be a natural phase 2. I don't recall
> > why the work stopped.
>
> As I recall, I was having difficulty convincing myself that
> de-duplication of results (for cases where the same row satisfies
> more than one of the OR'd conditions) would work correctly.
> You can't just blindly make it a UNION because that might remove
> identical rows that *should* appear more than once in the result.
>

I did rewrite the query using a cte and union(s). For that query, no dedup
point.
But my pb is that  that DB will be used by a bunch of people writing raw
SQL queries, and I cannot let them write queries that are going to go on
for ages, and eventually crash over temp_file_limit after hours every now
and then.
So, my understanding of the above is that I must inform the users NOT to
use OR clauses into joins.
which maybe a pb by itself.
regards
Marc


> regards, tom lane
>

Marc MILLAS


Re: bug or lacking doc hint

2023-06-25 Thread Avin Kavish
Sounds like the problem you are having is, the server is running out of
temporary resources for the operation that users are trying to do. So
according to Tom, on the postgres side, the operation cannot be optimized
further.

I think you have few choices here,
  - See if increasing the resources of the server will allow them to run
the operation
  - Ask users not to do that operation
  - Use a extension like citus to scale horizontally

But I'm thinking why a massively inefficient join is needed in the first
place. Shouldn't joins be for following keyed relationships. So ideally a
unique indexed column, but at the very least an indexed column. Why is a
join required on a dynamically calculated substring? Can it be made into a
static computed value and indexed? Substring sounds like an op that should
be in the filter stage.

Can you describe your data model? Maybe we can give some specific advice.

Regards,
Avin

On Mon, Jun 26, 2023 at 3:57 AM Marc Millas  wrote:

>
> On Sun, Jun 25, 2023 at 11:48 PM Tom Lane  wrote:
>
>> David Rowley  writes:
>> > The problem is that out of the 3 methods PostgreSQL uses to join
>> > tables, only 1 of them supports join conditions with an OR clause.
>> > Merge Join cannot do this because results can only be ordered one way
>> > at a time.  Hash Join technically could do this, but it would require
>> > that it built multiple hash tables. Currently, it only builds one
>> > table.  That leaves Nested Loop as the join method to implement joins
>> > with OR clauses. Unfortunately, nested loops are quadratic and the
>> > join condition must be evaluated once per each cartesian product row.
>>
>> We can do better than that if the OR'd conditions are each amenable
>> to an index scan on one of the tables: then it can be a nestloop with
>> a bitmap-OR'd inner index scan.  I thought the upthread advice to
>> convert the substr() condition into something that could be indexed
>> was on-point.
>>
> ok. but one of the tables within the join(s) tables is 10 billions rows,
> splitted in 120 partitions. Creating something like 20 more indexes to
> fulfill that condition do have its own problems.
>
>>
>> > Tom Lane did start some work [1] to allow the planner to convert some
>> > queries to use UNION instead of evaluating OR clauses, but, if I
>> > remember correctly, it didn't handle ORs in join conditions, though
>> > perhaps having it do that would be a natural phase 2. I don't recall
>> > why the work stopped.
>>
>> As I recall, I was having difficulty convincing myself that
>> de-duplication of results (for cases where the same row satisfies
>> more than one of the OR'd conditions) would work correctly.
>> You can't just blindly make it a UNION because that might remove
>> identical rows that *should* appear more than once in the result.
>>
>
> I did rewrite the query using a cte and union(s). For that query, no dedup
> point.
> But my pb is that  that DB will be used by a bunch of people writing raw
> SQL queries, and I cannot let them write queries that are going to go on
> for ages, and eventually crash over temp_file_limit after hours every now
> and then.
> So, my understanding of the above is that I must inform the users NOT to
> use OR clauses into joins.
> which maybe a pb by itself.
> regards
> Marc
>
>
>> regards, tom lane
>>
>
> Marc MILLAS
>


Re: plan using BTree VS GIN

2023-06-25 Thread Nicolas Seinlet
On Friday, June 23rd, 2023 at 2:52 PM, Laurenz Albe  
wrote:


> 

> 

> On Fri, 2023-06-23 at 12:08 +, Nicolas Seinlet wrote:
> 

> > we faced an issue with a select query on a relatively large table on our 
> > database.
> > The query involves one single table. The table has more than 10 million 
> > records.
> > It's mainly composed of varchar fields, have a primary key (id) of type 
> > serial,
> > and when records of this table are shown to users, they are sorted users 2 
> > fields,
> > display_name (varchar) and id (the primary key). Because this table is 
> > heavily used
> > in various contexts in our application, we have multiple indexes on it. 
> > Among other
> > index, we have gin index on some fields of the table.
> > 

> > The btree index res_partner_displayname_id_idx have been added lately and 
> > perfectly
> > match a criteria (where active) and sorting (display_name, id) we have in 
> > quite all
> > our queries on this table.
> > 

> > The query that cause the issue is this one:
> > SELECT "res_partner"."id"
> > FROM "res_partner"
> > WHERE (("res_partner"."active" = true) AND
> > (
> > (
> > (
> > ((unaccent("res_partner"."display_name"::text) ilike unaccent('%nse%'))
> > OR (unaccent("res_partner"."email"::text) ilike unaccent('%nse%')))
> > OR (unaccent("res_partner"."ref"::text) ilike unaccent('%nse)%')))
> > OR (unaccent("res_partner"."vat"::text) ilike unaccent('%nse%')))
> > OR (unaccent("res_partner"."company_registry"::text) ilike 
> > unaccent('%nse)%'
> > 

> > AND ((("res_partner"."type" != 'private') OR "res_partner"."type" IS NULL) 
> > OR "res_partner"."type" IS NULL )
> > 

> > ORDER BY "res_partner"."display_name" ,"res_partner"."id"
> > LIMIT 100
> > 

> > We have the common criteria (active=true), the common sorting, a limit, and 
> > a search
> > on various fields. The fields on which we're searching with criteria like 
> > '% whatever%' are gin indexed.
> > 

> > Here is the query plan:
> > Limit (cost=0.56..10703.36 rows=100 width=25) (actual 
> > time=56383.794..86509.036 rows=1 loops=1)
> > Output: id, display_name
> > Buffers: shared hit=4322296 read=1608998 dirtied=1 written=1247
> > -> Index Scan using res_partner_displayname_id_idx on public.res_partner 
> > (cost=0.56..1200212.37 rows=11214 width=25) (actual 
> > time=56383.793..86509.022 rows=1 loops=1)
> > Output: id, display_name
> > Filter: res_partner.type)::text <> 'private'::text) OR 
> > (res_partner.type IS NULL) OR (res_partner.type IS NULL)) AND 
> > ((unaccent((res_partner.display_name)::text) ~~* '%nse%'::text) OR
> > (unaccent((res_partner.email)::text) ~~
> > * '%nse%'::text) OR (unaccent((res_partner.ref)::text) ~~* '%nse%'::text) 
> > OR (unaccent((res_partner.vat)::text) ~~* '%nse%'::text) OR 
> > (unaccent((res_partner.company_registry)::text) ~~*
> > '%nse%'::text)))
> > Rows Removed by Filter: 6226870
> > Buffers: shared hit=4322296 read=1608998 dirtied=1 written=1247
> > Planning Time: 0.891 ms
> > Execution Time: 86509.070 ms
> > (10 rows)
> > 

> > It's not using our gin index at all, but the btree one.
> 

> 

> The problem is that PostgreSQL estimates that the index scan will return 11214
> rows, when it is actually one. This makes the plan to scan the table using
> an index that matches the ORDER BY clause appealing: we might find 100 rows
> quickly and avoid a sort.
> 

> You can try to improve the estimates with more detailed statistics,
> but if that doesn't do the job, you can modify the ORDER BY clause so
> that it cannot use the bad index:
> 

> ORDER BY res_partner.display_name ,res_partner.id + 0
> 

> Yours,
> Laurenz Albe

Hello,

First of all, thanks, this solves the issue for the given query.

Some more questions then,
> we might find 100 rows quickly
The cost estimate for 11214 rows is 1200212.37
If I look at the other plan, none of the estimated cost reach such levels (~2k 
for indexes + 1k for the BitmapOr, 3k for Bitmap Heap Scan, and finally 1k for 
sort and limit), roughly 7k

And that's part of what I didn't understand. How is the first cost estimated? 
If we divide by 110 the cost to go from 11k records to 100, it's still ~10k, 
more than the other plan.

Thanks again,

Nicolas.



publickey - nicolas@seinlet.com - 0xCAEB7FAF.asc
Description: application/pgp-keys


signature.asc
Description: OpenPGP digital signature


How to show current schema of running queries in postgresql 13

2023-06-25 Thread 陈锡汉
Hello,I use multi-schemas in one database in Postgres,such as

```
Postgres(instance)
 MyDB
   public
   MySchema1
 table1
 table2
   MySchema2
 table1
 table2
   MySchema3
 table1
 table2
```

And It's open to my users,my users will run queries,
such as
User1:
```
set search_path=MySchema1;
select * from table1,table2;
```

User2:
```
set search_path=MySchema2;
select * from table1,table2;
```

User3:
```
set search_path=MySchema3;
insert into table3 select * from MySchema1.table1,MySchema2.table2;
select * from table3;
```

I want to show current schema of running queries,But pg_stat_activity can only 
show database name, not schema name.

I want current schema (search_path ) as

| datname  | username | schema   | query   |
|  |  |  |  |
| MyDB | User1| MySchema1  | select * from table1,table2;  |
| MyDB | User2| MySchema2  | select * from table1,table2;  |
| MyDB | User3| MySchema3  | insert into table3 select * from 
MySchema1.table1,MySchema2.table2;  |

Is there any sys views can do it?

Thank you!
Best regards,
CavonChen