Re: Postgresql 14 partitioning advice

2022-08-08 Thread Slava Mudry
> I'm spinning up a new Postgresql 14 database where I'll have to store a
couple years worth of time series data at the rate of single-digit millions
of rows per day.
I think you absolutely need to use partitioning for the following reasons:
1. maintenance and roll-off of older data
2. indexes are much smaller
3. performance is predictable (if partition pruning kicks in)

Postgres 14 improved partitioning quite a bit. I used it in Postgres 9 and
there was a lot of locking on partition hierarchy when you add/drop
partition tables.
Having thousands of partitions shouldn't be a problem, BUT you will incur
cost on query planning, which is usually under 0.1 second on modern
hardware.


On Tue, Aug 2, 2022 at 5:55 AM Rick Otten  wrote:

>
>
> On Mon, Aug 1, 2022 at 10:16 AM Rick Otten 
> wrote:
>
>>
>>> The other problem I ran into, which I'm still building a test case for
>>> and I fear might be a bug if I can easily reproduce it,
>>> is if I did the original select in a CTE, and then did a sort outside of
>>> the CTE, even though the CTE found 0 rows, the database
>>> still spent a _ton_ of time sorting those 0 rows:
>>> ```
>>>->  Sort  (cost=70.03..72.53 rows=1000 width=112) (actual
>>> time=84848.452..84848.453 rows=0 loops=1)
>>> ```
>>> Once I can reproduce this on test data I'll be able to pin down more
>>> closely what is happening and tell if I'm just reading
>>> the explain plan wrong or if something is broken.  It was getting mixed
>>> up with the lack of pruning/index usage problem.
>>>
>>> I'll report back again next week.  Anyway it is looking to me like it
>>> doesn't really matter (within reason) from a performance
>>> perspective how many partitions we use for our data set and query
>>> patterns.  We should be able to pick the most convenient
>>> from an archiving and data management perspective instead.
>>>
>>>
>> This behavior is definitely consistent.  0 rows end up slower than when I
>> find some rows in my CTE:
>> ```
>>->  Sort  (cost=109.44..113.19 rows=1500 width=112) (actual
>> time=87110.841..87110.842 rows=0 loops=1)
>>->  Sort  (cost=109.44..113.19 rows=1500 width=112) (actual
>> time=25367.867..25367.930 rows=840 loops=1)
>> ```
>> The only thing I changed in the query was the date range.  It is actually
>> the CTE scan step inside the Sort block that is slower when no rows are
>> returned than when rows are returned.  It also only happens when all the
>> partitions are sequence scanned instead of being partition pruned.
>>
>> I'm still writing up a test case that can demo this without using
>> proprietary data.
>>
>
> After a bunch of experiments I can explain this now.  :-)
>
> I had a `limit` clause in my test CTE.  When sequence scanning a bunch of
> partitions, if the limit is reached, the subsequent partitions are marked
> with `never executed` and not scanned.  On the other hand, when no rows are
> found, all of the partitions are scanned.
>
> Therefore, with many millions of rows in the partitions, and being forced
> to sequence scan because I put the `at time zone` clause in the `where`,
> the case when rows are found is always noticeably faster than the case when
> rows aren't found as long as at least one partition hasn't been scanned yet
> when the limit is hit.
>
> I'm now satisfied this is a good thing, and will move on to other
> problems.  Thanks for hearing me out.  I was scratching my head for a while
> over that one.
>
>
>


-- 
-slava


Re: Aggressive vacuum

2025-01-06 Thread Slava Mudry
Hello Graham,
I had to deal with "vacuum to prevent wraparound" a few times and it's not
fun :(
Postgres doc explains it very well.. if you see that nasty thing running on
your db, your best options are:
1. manually vacuum freeze the table
2. examine vacuum costs and lower them to make sure the autovacuum can do
it's job. Allow more vacuum processes by tuning *autovacuum_max_workers*
3. tune and set autovacuum settings for your table to make sure autovacuum
picks it up sooner than defaults allow it so.

Depending on your usage, there are some other good optimizations you can
try.. The best in my opinion is to partition the large table and isolate
old rows from frequently updated rows and manually vacuum freeze rows that
you know wan't change. Also newer postgres versions have improved the
autovacuuming, if you're on ver 15 (based on your link to docs), you should
consider upgrading to more recent version.
Good luck,
-Slava

On Thu, Dec 19, 2024 at 5:37 AM Graham Hay  wrote:

> Can anyone enlighten me on exactly what triggers an "aggressive"
> vacuum? I have read the docs multiple times (and watched several
> videos!), but the changes I make do not have the expected outcomes; so
> I'm clearly missing something.
>
>
> https://www.postgresql.org/docs/15/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND
>
> I have a fairly large table, that has outgrown the vacuum defaults. We
> started by setting:
>
> - autovacuum_vacuum_scale_factor=0
> - autovacuum_vacuum_threshold=10 # 100K
>
> (10% was a lot of tuples). This was definitely an improvement, but
> when the big vacuum (freeze) kicked off there was a noticeable
> io/latency spike. We then tried setting:
>
>   - autovacuum_freeze_table_age=1 # 100M
>
> which seemed to make it happen more frequently (and one would hope,
> with less work to do). We reduced this to 50M, and again it was more
> frequent (but not the 2x I expected). And when I dropped it to 10M,
> nothing changed.
>
> After re-reading the docs, I got the impression I also needed to set:
>
> - autovacuum_freeze_min_age=1000 # 10M
>
> As the system default was 50M. And again, this had an effect, but not
> the 5x I was expecting. The docs say:
>
> > all-visible but not all-frozen pages are scanned if the number of
> transactions that have passed since the last such scan is greater than
> vacuum_freeze_table_age minus vacuum_freeze_min_age
>
> but wouldn't that have been 10M - 50M? i.e. -40M. Is there some other
> setting I'm missing?
>
> All suggestions welcome!
>
> Thanks,
>
> Graham
>
>
>

-- 
-slava