Re: REINDEX : new parameter to preserve current average leaf density as new implicit FILLFACTOR

2019-07-08 Thread John Lumby
o  thinking there is a case for the subject of this 
thread,  an automatic way to preserve density.

Secondary points:

I did not expect to see the number of table pages grow so much larger for pg-12 
than for pg-9.4.  The number of table pages was almost identical at the 
start of each run.   However this was not the focus of the test.  

Also,  although not shown in those tables,  pg-12 was around 4.5 times faster 
in completing those 768 iterations,an enormous improvement.

And one question :
I notice that in some pg-11 release,   a new config parameter appeared  :
  vacuum_cleanup_index_scale_factor 
specifies the fraction of the total number of heap tuples counted in the 
previous statistics collection that can be inserted without incurring an index 
scan at the VACUUM cleanup stage. 

I have not researched this at all and nor did I set it to anything for my 
pg-12beta2 run,  but it sounds as though maybe it could be relevant to this 
kind of workload  -   Is that so?

CheersJohn Lumby



Re: REINDEX : new parameter to preserve current average leaf density as new implicit FILLFACTOR

2019-07-08 Thread John Lumby
Thanks Peter

> From: Peter Geoghegan 
> Sent: July 8, 2019 1:39 PM
> Subject: Re: REINDEX : new parameter to preserve current average leaf density 
> as new implicit FILLFACTOR
> 
> Perhaps you didn't take deleted_pages into account -- there must be
> free space that is reusable by the index that has yet to be reused.
> It would probably make sense to subtract that across the board.
> 

Correct,  I did not,   but will do so for the next runs.

> 
> I don't think that a test case that runs VACUUM when there are only
> 4300 deletions and 4300 insertions is particularly realistic, in
> general. You might see a larger difference if there was more churn
> between each VACUUM run.
> 

Actually the test workload does not run any explicit VACUUM command,
it relies on autovacuum with these settings
(same settings for 9.4 and 12beta2)

 autovacuum  | on  |   
 autovacuum_analyze_scale_factor | 0.4 |   
 autovacuum_analyze_threshold| 5   |   
 autovacuum_max_workers  | 6   |   
 autovacuum_naptime  | 20  | s 
 autovacuum_vacuum_cost_delay| 0   | ms
 autovacuum_vacuum_cost_limit| |   
 autovacuum_vacuum_scale_factor  | 0   |   
 autovacuum_vacuum_threshold | 2000|   
 autovacuum_work_mem | 1048576 | kB


To correspond to your " more churn between each VACUUM"
Would you then suggest increasing
autovacuum_vacuum_cost_delay and/or  autovacuum_vacuum_scale_factor?

Cheers,  John Lumby



Re: REINDEX : new parameter to preserve current average leaf density as new implicit FILLFACTOR

2019-07-09 Thread John Lumby

> From: Peter Geoghegan 
> Sent: July 8, 2019 1:39 PM
> Subject: Re: REINDEX : new parameter to preserve current average leaf density 
> as new implicit FILLFACTOR
> 
> On Mon, Jul 8, 2019 at 9:23 AM John Lumby  wrote:
> 
> > Although a welcome improvement,  I think it is not enough to justify 
> > stopping use of setting
> > a lower explicit FILLFACTOR.   Which then brings me back to  thinking there 
> > is a case
> > for the subject of this thread,  an automatic way to preserve density.
> 
> I don't think that such an option would make much sense. The "waves of
> misery" paper is about smoothing out the frequency of page splits
> following bulk loading and a CREATE INDEX. It is not about making
> splits occur less often. It's well understood that a certain amount of
> free space is the overhead of B-Tree indexes, albeit an overhead that
> can be avoided in certain specific instances.
> 
Yes,   I see that. But surely "making splits occur less often" is a 
desirable
objective in itself, is it not? And I believe that a parameter to preserve 
the "steady-state"
density in high-traffic indexes would help achieve that goal,   wouldn't you 
agree?

Cheers,  John Lumby





Re: REINDEX : new parameter to preserve current average leaf density as new implicit FILLFACTOR

2019-07-09 Thread John Lumby

> From: Peter Geoghegan 
> Sent: July 9, 2019 1:47 PM
> Subject: Re: REINDEX : new parameter to preserve current average leaf density 
> as new implicit FILLFACTOR
>  
> On Tue, Jul 9, 2019 at 10:31 AM John Lumby  wrote:
> > Yes,   I see that. But surely "making splits occur less often" is a 
> > desirable
> > objective in itself, is it not? And I believe that a parameter to 
> > preserve the "steady-state"
> > density in high-traffic indexes would help achieve that goal,   wouldn't 
> > you agree?
> 
> Anything that reliably reduces page splits without hurting space
> utilization is well worthwhile. I can't see how what you describe
> could have that effect, though. If you expect the leaf density to be
> the same after a REINDEX, then why bother at all? There is no reason
> to think that that will be more effective than simple vacuuming.
> 
Ah,  I did not explain the idea welll enough.
The scenario (simplified) is this:
Time 0  FILLFACTORs all set to default 90%
because we do not yet know what the steady-state density
will turn out to be.
   {   workload runs for a few weeks  }
Time N  gather table and index stats,   discover growth and learn density.
growth is more than autovacuum could control so
   {   ALTER INDEX ??? SET (fillfactor = AUTO); }
   {   REINDEX,   desiring to preserve current density whatever this is }
   {   workload runs for a few more weeks  }
Time 2*Ngather table and index stats,   discover little or no growth since 
time N.
we have achieved steady-state in total number of pages.

Would this not work?

Cheers,   John



Re: REINDEX : new parameter to preserve current average leaf density as new implicit FILLFACTOR

2019-07-09 Thread John Lumby
And the point of the REINDEX at that point (below) is to remove dead tuple 
keys-tids
and  reorganize those split pages back into physical order without losing the 
freespace.

> From: Peter Geoghegan 
> Sent: July 9, 2019 1:47 PM
> Subject: Re: REINDEX : new parameter to preserve current average leaf density 
> as new implicit FILLFACTOR
>  
> On Tue, Jul 9, 2019 at 10:31 AM John Lumby  wrote:
> > Yes,   I see that. But surely "making splits occur less often" is a 
> > desirable
> > objective in itself, is it not? And I believe that a parameter to 
> > preserve the "steady-state"
> > density in high-traffic indexes would help achieve that goal,   wouldn't 
> > you agree?
> 
> Anything that reliably reduces page splits without hurting space
> utilization is well worthwhile. I can't see how what you describe
> could have that effect, though. If you expect the leaf density to be
> the same after a REINDEX, then why bother at all? There is no reason
> to think that that will be more effective than simple vacuuming.
> 
Ah,  I did not explain the idea welll enough.
The scenario (simplified) is this:
Time 0  FILLFACTORs all set to default 90%
because we do not yet know what the steady-state density
will turn out to be.
   {   workload runs for a few weeks  }
Time N  gather table and index stats,   discover growth and learn density.
growth is more than autovacuum could control so
   {   ALTER INDEX ??? SET (fillfactor = AUTO); }
   {   REINDEX,   desiring to preserve current density whatever this is }
   {   workload runs for a few more weeks  }
Time 2*Ngather table and index stats,   discover little or no growth since 
time N.
we have achieved steady-state in total number of pages.

Would this not work?

Cheers,   John



Re: REINDEX : new parameter to preserve current average leaf density as new implicit FILLFACTOR

2019-07-09 Thread John Lumby
> From: Peter Geoghegan 
> Sent: July 9, 2019 3:01 PM
> Subject: Re: REINDEX : new parameter to preserve current average leaf density 
> as new implicit FILLFACTOR
>
> On Tue, Jul 9, 2019 at 11:27 AM John Lumby  wrote:
> > And the point of the REINDEX at that point (below) is to remove dead tuple 
> > keys-tids
> > and  reorganize those split pages back into physical order without losing 
> > the freespace.
>
> VACUUM already removes the tuples, accounting for all overhead.
>
> We could in principle come up with a way of moving pages around,
>  [ ... ]
> That would either necessitate that the command acquire a disruptive lock
>  [ ... ]
> Neither of which seem particularly appealing.

I was not thinking of a new command,  just an extension of the existing REINDEX
which would apply a fillfactor equal to current average page density,
by adding a preliminary step to sample that first.
Of course,   the user can do that for themselves by a series of steps with
ANALYZE, get page_density from pgstattuple,  ALTER INDEX,  REINDEX
so this new parameter would be a convenience,  assuming that this sequence
actually is beneficial,   which I believe it is  -  see my next.

>
> I believe that this is a lot more important in systems that generally
> use clustered indexes, such as MS SQL Server. This kind of
> "fragmentation" isn't usually much of a problem when using Postgres.
>
We have found that, for an index which has both experienced large number of 
page splits
and whose table has a large number of dead tuples (despite autovacuum),
REINDEX with FILLFACTOR set to current page_density does produce a performance 
improvement,
and also does reduce future growth in number of pages.I don't have numbers 
to
hand,  and in fact not sure if any catalog view or pgstattuple tells me about 
the proportion
of dead key-tids in the index itself (do you know of any source?) as opposed to 
the table,
but based on that recollection,  yes,   REINDEX can reduce fragmentation.

However we did not run a VACUUM command first. Maybe if we had run VACUUM 
instead of
the REINDEX commands,   we might have obtained the same degree of improvement,  
I don't know.
I think this was Tom's point earlier on in this thread.

Correct me if I'm wrong but I believe whether an index is "clustered" or not is 
not relevant for
this discussion because the clustering in that context is referring to ordering 
of the
table pages,  not the index pages.I believe it is quite possible to have a 
perfectly
"clustered" table whose clustering index is itself badly disorganized.

Cheers, John



Re: REINDEX : new parameter to preserve current average leaf density as new implicit FILLFACTOR

2019-07-09 Thread John Lumby
> From: Peter Geoghegan 
> Sent: July 9, 2019 5:15 PM
> Subject: Re: REINDEX : new parameter to preserve current average leaf density 
> as new implicit FILLFACTOR
>  
> On Tue, Jul 9, 2019 at 12:29 PM John Lumby  wrote:
> > I was not thinking of a new command,  just an extension of the existing 
> > REINDEX
> > which would apply a fillfactor equal to current average page density,
> > by adding a preliminary step to sample that first.
> 
> That would be a very different thing to REINDEX no matter how you
> spelt it, though. REINDEX creates a new index, from scratch, whereas
> you're talking about restructuring what's already there.

No,  no,   I really am talking about an extension to the *existing* REINDEX,
and yes,  yes,  my extended REINDEX *would* still; create a new index from 
scratch.
The *only* difference is that,  instead of taking the FILLFACTOR it uses from
whatever is set in the index attributes,  it would take it from first 
calculating
current average page density.  and then build a new index with that fillfactor.

> 
> Or, it could be that range scan performance benefitted from reduced 
> fragmentation,
> 

Yes,  I think so.

Cheers,  John



access to original-statement predicates in an INSTEAD-OF row trigger

2019-11-15 Thread John Lumby
I have an INSTEAD-OF row trigger one of whose purposes is to re-direct the 
original statement 
(which is operating on a VIEW) to a different real base table.

Suppose the original statement is 
          UPDATE myview VW set VW.counter = 11 where VW.primary_key =  and 
AND VW.counter = 10;

and my trigger constructs this statement
   UPDATE basetable BT set BT.counter = 11 where BT.primary_key = 
OLD.primary_key;
based on what it finds in OLD tuple and NEW tuple.

This will never update the wrong row since it specifies the primary key  -  
good.  But I have realized there is a problem concerning the returned TAG.
Suppose that,  *after* the backend executor started executing the statement but 
*before* the trigger is fired and this statement is issued,  a different 
transaction updated BT.counter to 11 (or higher).
My trigger still runs the update, but the original statement specified to do so 
only if the current value of counter is 10.
Or rather,  it specified that no row should be found for update if counter <> 
10.

Is there any way my trigger can discover this predicate condition and apply it 
to its generated statement?

Or if not,   (because I suppose in general such predicates could be very 
complex) is there some other way of doing this that avoids this problem and  
that does not require modification of the application?  (**)  

I have a feeling this must have come up before but Idon't see any reference.

postgresqI version 12.

Cheers,   John

 (**)I know a SHARE lock could be obtained by the application running the 
orginal statement but assume for this question that that is not possible.  
I am looking for some self-contained way in trigger or similar code.

 



Re: access to original-statement predicates in an INSTEAD-OF row trigger

2019-11-15 Thread John Lumby
Adrian Klaver wrote :
> 
> On 11/15/19 10:37 AM, John Lumby wrote:
> 
> > Suppose the original statement is
> 
> >  UPDATE myview VW set VW.counter = 11 where VW.primary_key =  and 
> > VW.counter = 10;
> 
> > and my trigger constructs this statement
> 
> > UPDATE basetable BT set BT.counter = 11 where BT.primary_key = 
> > OLD.primary_key;
> 
> Not following.
> 
> Do you want OLD.primary_key set to 11 or BT.counter set to 12/both/or 
> 
> some other action?

Sorry I did not make it clear.

I want some way for the trigger to discover and apply any predicates *other* 
than
primary key equality condition that were applied to the original statement,
which in the example is

VW.counter = 10

(the repeated AND in the original append's example was a typo,  corrected above)

so for this example I want the trigger to build a statement reading

 UPDATE basetable BT set BT.counter = 11 where BT.primary_key =  and 
BT.counter = 10;

where  is the value of OLD.primary_key

so that,  if some other transaction had updated BT.counter to some other value 
such as 11
in that tiny window I described in previous append,
the result of the generated statement would be no rows updated and a return TAG 
of 0 rows.

The significance being that the original application would be able to discover
that its update was not applied based on this return TAG 
(actually the trigger returns a null tuple to indicate this).

> 
> > Cheers, John
> 
> Adrian Klaver
> 
> adrian.kla...@aklaver.com
> 










Re: access to original-statement predicates in an INSTEAD-OF row trigger

2019-11-15 Thread John Lumby
Adrian Klaver wrote :
>
> Seems you are looking for Serializable Isolation Level:
>

True ,   that would solve the race condition,  but it is too drastic.
We need to run with Read Committed.

I am looking for a solution which does not alter the application or overall 
behaviour,
but just addresses detecting which predicates to apply in some way.

Cheers,  John



Re: access to original-statement predicates in an INSTEAD-OF row trigger

2019-11-16 Thread John Lumby
On 11/15/19 17:38, Adrian Klaver wrote:
> On 11/15/19 1:54 PM, John Lumby wrote:
>> Adrian Klaver wrote :
>>>
>> We need to run with Read Committed.
>>
>> I am looking for a solution which does not alter the application or 
>> overall behaviour,
>> but just addresses detecting which predicates to apply in some way.
>
> Not sure how that could be pulled off with Read Committed as it would 
> involve predicting the future from the POV of the transaction.
>

No need for time-travel!
Let me re-phrase the question in a simpler fashion :
How can a row trigger access the original SQL statement at the root of 
the current operation?
Either in string form or any other form (e.g. parse tree).

>>
>> Cheers,  John
>>
>
>





REINDEX : new parameter to preserve current average leaf density as new implicit FILLFACTOR

2019-06-25 Thread John Lumby
Background :   For some workloads involving high volume of 
INSERT/UPDATE/DELETE,  It is sometimes beneficial
to schedule regular REINDEX of high-activity indexes,   so as to improve 
performance,  or restore performance levels back to what it was earlier,   by 
removing dead keys etc.  This can result in the average page density of 
these indexes fluctuating up and down in a saw-tooth fashion,  REINDEX causing 
large increase in density (large drop in total number of pages) and the 
workload gradually  decreasing density back to some "steady-state".

Suggestion : it would be useful if REINDEX could ,   when some new parameter is 
set , first determine current average leaf page density in the index to be 
rebuilt,    (e.g. the value of pgstatindex().avg_leaf_density from the   
pgstattuple extension ),  and then adopt this density as the temporary override 
FILLFACTOR while rebuilding index pages,  as to to minimize change in density.

This would avoid the saw-tooth effect on number of pages,   and also reduce the 
number of index page-splits which occur during the period immediately following 
a REINDEX done with default FILLFACTOR of 90%.   In effect,  it lessens the 
need for the physical reorganization aspect of REINDEX and focusses more on the 
function of removing dead  keys.

An admin do this for themselves by monitoring index page density and setting 
the FILLFACTOR to the current density before each REINDEX (and may find that 
this doesn't change much if the workload is truly steady-state),   but I wonder 
if this community would agree that it would provide a useful automation of the 
process.

Cheers,  John Lumby





Re: REINDEX : new parameter to preserve current average leaf density as new implicit FILLFACTOR

2019-06-26 Thread John Lumby
Thanks Tom and Peter for those thoughts.

>
> I think you've confused REINDEX with VACUUM.  It seems like a pretty poor
> substitute for that --- it's much more expensive and has worse locking
> requirements.
>

I think the answer is mainly "I wish it were so" ,   but in practice,   even 
with a reasonably aggressive autovacuum configuration running,  eventually the 
number of pages and number of dead keys builds up too much.The assumption 
(which is the case in our particular workload) is that,  eventually,  
unavailable-service maintenance operation must be done,  and REINDEX does 
(today,  pg-11.x) play a useful role because it addresses various aspects.   
And then,  given we find it useful to REINDEX,   we would prefer to avoid the 
sawtooth / "wave of misery" syndrome.

>
> There is a very recent research paper that discusses the idea of
> varying fillfactor with a view to ameliorating page splits:
> 

Thanks,  I am chewing my way through that.  As you say,  it does address 
exactly the issues I raised. 
Do you happen to know if their source-code is available somewhere?
( I did see their db is MS SQL Server but it still might provide some portable 
ideas. )

> 
> I suspect that you might find that the enhancements to B-Tree indexes
> that went into Postgres 12 would help with this workload, especially
> if you notice that this happens with indexes that have a lot of duplicates
>

I had not noticed that,   thanks for pointing it out.  Yes ,  in my workload 
most of the indexes in question are non-unique and some have very low key card. 
   I will try out the pg-12 beta when I get a chance.

> 
> For the full background, you might take a look at my pgCon talk:
> https://youtu.be/p5RaATILoiE
>

Is there a pdf or text version?

> 
> Does it seem at all possible that you were affected by either the issue with 
> duplicates,
> 

definitely

> 
> or the issue that is addressed by the "split after new tuple" optimization?
> 

don't know,yet more research needed.is there a module or contrib which 
would tell me?

Thanks again  John Lumby





From: Peter Geoghegan 

Sent: June 25, 2019 6:12 PM

To: John Lumby

Cc: pgsql general

Subject: Re: REINDEX : new parameter to preserve current average leaf density 
as new implicit FILLFACTOR

 


On Tue, Jun 25, 2019 at 2:45 PM John Lumby  wrote:

> Background :   For some workloads involving high volume of 
> INSERT/UPDATE/DELETE,  It is sometimes beneficial

> to schedule regular REINDEX of high-activity indexes,   so as to improve 
> performance,  or restore performance levels back to what it was earlier,   by 
> removing dead keys etc.  This can result in the average page density of 
> these indexes fluctuating up
 and down in a saw-tooth fashion,  REINDEX causing large increase in density 
(large drop in total number of pages) and the workload gradually  decreasing 
density back to some "steady-state".



I suspect that you might find that the enhancements to B-Tree indexes

that went into Postgres 12 would help with this workload, especially

if you notice that this happens with indexes that have a lot of

duplicates. For the full background, you might take a look at my pgCon

talk:



https://youtu.be/p5RaATILoiE



Fair warning: this is a very technical talk.



Does it seem at all possible that you were affected by either the

issue with duplicates, or the issue that is addressed by the "split

after new tuple" optimization? They're both causes of index bloat that

VACUUM cannot usually prevent.



-- 

Peter Geoghegan