1
0:0:4,96 --> 0:0:7,8999996
Nikolay: Everyone who is running
Postgres has autovacuum, and
2
0:0:7,8999996 --> 0:0:12,0199995
most of people heard about autovacuum
and vacuuming and bloat
3
0:0:12,04 --> 0:0:13,48
and this garbage collection.
4
0:0:14,28 --> 0:0:22,08
But a lot of databases grow with
problems being unnoticed and
5
0:0:22,08 --> 0:0:25,08
they start tuning autovacuum
too late.
6
0:0:25,64 --> 0:0:30,04
So this topic today is brought
by you Michael, right?
7
0:0:30,06 --> 0:0:30,72
Hi Michael.
8
0:0:31,24 --> 0:0:31,98
Michael: Hi Nik.
9
0:0:32,84 --> 0:0:36,1
Nikolay: And we definitely had
this topic discussed in the past
10
0:0:36,1 --> 0:0:40,96
in terms of like vacuum and bloat,
but we never discussed the
11
0:0:40,96 --> 0:0:44,54
vacuum itself and how to tune it
properly and what are the best
12
0:0:44,54 --> 0:0:45,04
practices.
13
0:0:46,02 --> 0:0:48,059998
And yeah, I'm glad that you brought
it.
14
0:0:48,059998 --> 0:0:49,22
Let's talk about this.
15
0:0:49,81 --> 0:0:51,14
Michael: Sounds good.
16
0:0:51,14 --> 0:0:51,38
Yeah.
17
0:0:51,38 --> 0:0:54,14
I'm looking forward to hearing
your views on this kind of from
18
0:0:54,14 --> 0:0:57,62
a seeing lots and lots of different
clients perspective because
19
0:0:57,62 --> 0:1:1,82
I get the impression dealing with
people less frequently that
20
0:1:2,68 --> 0:1:6,66
Often it's left really late before
people start tuning or to
21
0:1:6,66 --> 0:1:10,46
vacuum and when I say late a startup
will grow to relatively
22
0:1:10,52 --> 0:1:15,72
significant size before touching
those parameters And I often
23
0:1:15,72 --> 0:1:20,64
think they could have avoided quite
a few headaches and got into
24
0:1:20,76 --> 0:1:26,06
issues slower, if that makes sense,
by just changing a few settings
25
0:1:26,28 --> 0:1:27,1
much earlier.
26
0:1:27,38 --> 0:1:31,2
So yeah, I was keen to get your
thoughts on If you see the same
27
0:1:31,2 --> 0:1:34,9
and also like, when would you advise
people like startup life's
28
0:1:34,9 --> 0:1:37,8
busy, when would you advise people
looking at this kind of thing?
29
0:1:38,04 --> 0:1:38,4
Nikolay: Yeah.
30
0:1:38,4 --> 0:1:43,74
First of all, every single client
which comes to us, we talk
31
0:1:43,74 --> 0:1:47,04
about autovacuum tuning on any
platform.
32
0:1:47,04 --> 0:1:47,7
Doesn't matter.
33
0:1:47,7 --> 0:1:49,4
Self-managed, any managed service.
34
0:1:49,4 --> 0:1:53,4
We always touch this topic and
always like in hundred percent
35
0:1:53,4 --> 0:1:56,26
of cases there is something that
should be done there.
36
0:1:56,78 --> 0:1:59,18
Which means your point is absolutely
right.
37
0:1:59,18 --> 0:2:3,16
It should be done earlier because
when people come to us for
38
0:2:3,16 --> 0:2:7,42
help it's already, they experience
already some problems, some
39
0:2:7,42 --> 0:2:9,7
troubles, right, and this is a
reactive approach.
40
0:2:10,38 --> 0:2:13,22
Michael: And just to clarify, when
you say 100 percent, do you
41
0:2:13,22 --> 0:2:17,84
mean some percentage have done
loads of tuning and still have
42
0:2:17,84 --> 0:2:20,38
issues and some percentage have
done nothing at all.
43
0:2:20,38 --> 0:2:22,26
What's the kind of distribution
like?
44
0:2:22,26 --> 0:2:23,4
Nikolay: It's hard to say.
45
0:2:23,4 --> 0:2:26,48
Actually I checked how many clusters
we observed lately.
46
0:2:26,48 --> 0:2:32,08
It was like 140 or something where
we used thorough like comprehensive
47
0:2:32,08 --> 0:2:35,68
health analysis and tuning and
recommendations and work closely
48
0:2:35,68 --> 0:2:36,48
and so on.
49
0:2:36,68 --> 0:2:43,48
So I'd say 0% have an ideal picture
in terms of how autovacuum
50
0:2:43,48 --> 0:2:44,12
is tuned.
51
0:2:45,04 --> 0:2:49,06
Most customers running on managed
services, especially RDS, have,
52
0:2:49,06 --> 0:2:51,72
let me say it, half-ass tuned
autovacuum.
53
0:2:53,5 --> 0:2:58,52
This is new term we can use here
because this is like, it amazes
54
0:2:58,52 --> 0:2:59,7
me why it's so.
55
0:2:59,7 --> 0:3:1,9
We can dive into details soon.
56
0:3:2,38 --> 0:3:8,36
And only few, like literally that's
a several, I saw they have
57
0:3:8,36 --> 0:3:12,94
very well tuned autovacuum and
we just shift focus to why it's
58
0:3:12,94 --> 0:3:16,4
still not enough and what we should
do with specific pieces of
59
0:3:16,4 --> 0:3:16,9
workload.
60
0:3:17,62 --> 0:3:18,96
Michael: Sure, makes sense.
61
0:3:19,2 --> 0:3:21,6
Nikolay: Local tuning already,
what to do about it.
62
0:3:21,6 --> 0:3:26,08
And in most cases there we also
involve, we focus on specific
63
0:3:26,16 --> 0:3:30,04
workload, but also we go, of course,
beyond just autovacuum
64
0:3:30,04 --> 0:3:34,08
tuning, because usually this is
like some pathological workload
65
0:3:34,12 --> 0:3:38,62
or some, there are some problems
which are not conflicting, how
66
0:3:38,62 --> 0:3:41,94
to say, like they are blocking
autovacuum work, right?
67
0:3:41,98 --> 0:3:42,48
Yes.
68
0:3:42,98 --> 0:3:48,22
Before we dive into details, maybe
let's just explain to wider
69
0:3:48,22 --> 0:3:53,22
audience what autovacuum is, because
I think many still misunderstand
70
0:3:53,3 --> 0:3:53,8
it.
71
0:3:53,94 --> 0:3:59,82
Recently I talked to, you know,
like our focus is fast growing
72
0:3:59,82 --> 0:4:3,38
startups and I talked to technical
founders quite often.
73
0:4:4,28 --> 0:4:6,42
These guys are super smart.
74
0:4:6,42 --> 0:4:9,1
Technically they understand, they
definitely understand throughput,
75
0:4:9,14 --> 0:4:10,76
latency, all the numbers and so
on.
76
0:4:10,76 --> 0:4:15,98
But I see they just didn't have
time to dive into autovacuum,
77
0:4:15,98 --> 0:4:16,64
what it is.
78
0:4:16,64 --> 0:4:20,82
They heard bloat issue, MVCC, Postgres
is very widely criticized,
79
0:4:21,18 --> 0:4:21,6
right?
80
0:4:21,6 --> 0:4:24,72
But what autovacuum is and what to
do about it, what they need
81
0:4:24,72 --> 0:4:28,98
to have, it's like, it's always
a good topic to discuss and dive
82
0:4:28,98 --> 0:4:29,48
into.
83
0:4:29,5 --> 0:4:33,42
So my simple explanation, autovacuum
is just garbage collection,
84
0:4:33,42 --> 0:4:34,3
first of all.
85
0:4:35,66 --> 0:4:40,32
It has a few more jobs, but the
main job, original job, is garbage
86
0:4:40,32 --> 0:4:40,82
collection.
87
0:4:41,18 --> 0:4:48,14
When you have updates, deletes,
or failed inserts, by the way,
88
0:4:48,14 --> 0:4:52,6
the third part is usually forgotten,
but failed inserts, all
89
0:4:52,6 --> 0:4:56,68
of them produce successful updates,
successful deletes, and failed
90
0:4:56,68 --> 0:4:58,34
inserts, rolled back inserts.
91
0:4:58,86 --> 0:5:5,44
They all produce dead row versions
called tuples, right?
92
0:5:6,22 --> 0:5:8,16
Michael: Probably also rolled back
updates.
93
0:5:10,08 --> 0:5:11,36
Nikolay: Oh yes, you're right.
94
0:5:11,48 --> 0:5:11,98
Yeah.
95
0:5:12,44 --> 0:5:19,08
Successful deletes, rolled back
inserts, or any updates.
96
0:5:19,62 --> 0:5:20,12
Yeah.
97
0:5:20,42 --> 0:5:24,86
Besides HOT updates, which are
nuances, right?
98
0:5:25,08 --> 0:5:25,68
Even HOT
99
0:5:25,68 --> 0:5:26,68
Michael: updates, yeah.
100
0:5:26,88 --> 0:5:29,44
Nikolay: If we want to be thorough,
like we are destroying my
101
0:5:29,44 --> 0:5:31,54
intention to provide simple explanation.
102
0:5:31,84 --> 0:5:33,5
Let's keep it short.
103
0:5:33,9 --> 0:5:36,36
So it's first of all garbage collections.
104
0:5:37,9 --> 0:5:41,94
So if, especially for guys who
run Postgres on machines with a
105
0:5:41,94 --> 0:5:48,74
lot of cores, like typical like
Intel machine 96 cores or 48
106
0:5:48,86 --> 0:5:51,72
or like AMD hundreds of cores,
right?
107
0:5:53,16 --> 0:5:55,9
Michael: They- We have very, we
have a very different definition
108
0:5:55,9 --> 0:5:57,54
of what typical is for-
109
0:5:57,7 --> 0:5:59,54
Nikolay: Well, typical big, large
database.
110
0:6:0,08 --> 0:6:0,9
Michael: Sure, sure.
111
0:6:1,06 --> 0:6:4,44
Nikolay: So it's, it amazes me,
like I, I saw, I told you, I
112
0:6:4,44 --> 0:6:9,48
saw Postgres clusters achieving
10, 20 terabytes with default
113
0:6:9,52 --> 0:6:10,58
autovacuum settings.
114
0:6:11,0 --> 0:6:14,32
Somehow surviving, already having
5 replicas.
115
0:6:14,76 --> 0:6:15,3
It's insane.
116
0:6:15,3 --> 0:6:18,48
Michael: This is what I meant in
terms of like, should people
117
0:6:18,66 --> 0:6:20,6
be doing it earlier or is it okay?
118
0:6:20,74 --> 0:6:21,35
There's a certain argument.
119
0:6:21,35 --> 0:6:21,54
Nikolay: It's not
120
0:6:21,54 --> 0:6:22,38
Michael: okay, no.
121
0:6:22,38 --> 0:6:26,7
Yeah, I think I agree, but as you
say, they've somehow got by
122
0:6:26,92 --> 0:6:28,54
even to that large extent.
123
0:6:28,74 --> 0:6:33,42
But I've also seen smaller systems
really struggling because
124
0:6:33,42 --> 0:6:34,84
autovacuum hasn't been tuned.
125
0:6:34,84 --> 0:6:38,12
So far fewer, like maybe not even
a terabyte, but struggling
126
0:6:38,12 --> 0:6:39,58
because of a certain workload.
127
0:6:40,24 --> 0:6:42,94
So yeah, it's not just size, right?
128
0:6:43,26 --> 0:6:47,12
Nikolay: It can be a table of 2
gigabytes in size, but it's mostly
129
0:6:47,12 --> 0:6:48,3
bloated, like 99.9%.
130
0:6:49,14 --> 0:6:52,32
I saw it many times, especially
with queue-like workloads.
131
0:6:52,38 --> 0:6:55,52
And then it can suffer, small database,
but it suffers from the
132
0:6:55,52 --> 0:6:58,7
fact that autovacuum is not tuned
and maybe something is blocking
133
0:6:58,7 --> 0:6:59,2
it.
134
0:6:59,34 --> 0:7:1,4
Garbage collection job is blocking
it.
135
0:7:1,4 --> 0:7:3,74
So we need to combine both things
here.
136
0:7:3,74 --> 0:7:6,86
But my point is, autovacuum is
just garbage collection.
137
0:7:7,48 --> 0:7:11,4
If you tune Postgres, or maybe
your provider tuned, for example,
138
0:7:11,4 --> 0:7:15,9
to have bigger shared_buffers,
bigger cache, right, and a work_mem
139
0:7:16,24 --> 0:7:19,24
for sort and join operations and
so on.
140
0:7:19,24 --> 0:7:22,36
If it's already tuned and max_connections
has increased, maybe
141
0:7:22,36 --> 0:7:25,62
a pooler is in front of it, like
you tuned it to handle workload.
142
0:7:26,72 --> 0:7:31,6
Why the heck garbage collection
remains untuned?
143
0:7:31,72 --> 0:7:34,54
It should be tuned together with
everything else, right?
144
0:7:34,54 --> 0:7:36,18
So it should be.
145
0:7:36,4 --> 0:7:39,2
But we see it's often lagging in
tuning.
146
0:7:40,24 --> 0:7:43,9
And it can be a local workload
on small database already suffering,
147
0:7:43,9 --> 0:7:48,4
or it can be a big cluster and
garbage collection mostly default.
148
0:7:48,76 --> 0:7:50,2
autovacuum is mostly default.
149
0:7:50,34 --> 0:7:53,76
But that being said, we should
mention that there are a few more
150
0:7:53,76 --> 0:7:55,3
jobs that the vacuum has.
151
0:7:55,72 --> 0:7:56,76
Maintenance statistics.
152
0:7:57,74 --> 0:7:58,14
Yeah?
153
0:7:58,14 --> 0:7:58,62
Do you want to
154
0:7:58,62 --> 0:8:0,02
Michael: stick to the vacuum ones
first?
155
0:8:0,02 --> 0:8:3,7
Because I think the name autovacuum
is quite a good name in
156
0:8:3,7 --> 0:8:9,38
that it's all of the jobs that
vacuum does but automated But
157
0:8:9,38 --> 0:8:13,7
with 1 addition, which is there
is also an auto-analyze
158
0:8:13,7 --> 0:8:15,72
feature Right, which is what you're
just about to talk about
159
0:8:15,72 --> 0:8:18,8
in terms of statistics, but I feel
like the other vacuum jobs
160
0:8:18,8 --> 0:8:22,5
are worth—do you think of it like
as garbage collection, statistics,
161
0:8:22,54 --> 0:8:23,95
and then the other vacuum jobs?
162
0:8:23,95 --> 0:8:25,64
Nikolay: — It's just easier to
memorize.
163
0:8:25,84 --> 0:8:29,36
Statistics also should be maintained
up to date.
164
0:8:30,02 --> 0:8:33,22
If it's lagging, it may affect
performance, might affect performance.
165
0:8:33,66 --> 0:8:36,44
But you're right, there are also
a couple of more jobs.
166
0:8:36,46 --> 0:8:37,62
Transaction ID wraparound.
167
0:8:38,22 --> 0:8:43,44
If you have a lot of transactions
per day, we know there are
168
0:8:43,44 --> 0:8:45,92
sometimes some like 1000000000
per day.
169
0:8:45,92 --> 0:8:46,64
It's a lot.
170
0:8:46,64 --> 0:8:50,14
In this case, churn is high and
int4 is not enough.
171
0:8:50,14 --> 0:8:51,94
Half of int4 is not enough.
172
0:8:52,36 --> 0:8:55,38
transaction ID wraparound prevention
should be very frequent
173
0:8:55,38 --> 0:8:58,22
in each tuple, in each row version.
174
0:8:58,98 --> 0:9:2,66
And also there is Another very
important job, especially for
175
0:9:2,66 --> 0:9:6,3
performance, it's maintaining visibility
maps.
176
0:9:7,12 --> 0:9:11,26
It's a bitmap with 2 bits for each
page.
177
0:9:11,28 --> 0:9:13,68
Page is 8 kibibytes, right?
178
0:9:13,68 --> 0:9:18,28
And 2 bits, is the whole page fully
visible, All visible?
179
0:9:18,5 --> 0:9:20,94
Means all tuples are visible to
all transactions.
180
0:9:21,18 --> 0:9:23,64
And second is all frozen.
181
0:9:24,34 --> 0:9:26,0
Yeah, just previous topic.
182
0:9:26,0 --> 0:9:28,54
Transaction ID wraparound prevention.
183
0:9:28,6 --> 0:9:32,54
So not to visit this page again
if we know that all the tuples
184
0:9:32,54 --> 0:9:35,58
are in the past, they're already
marked frozen, so they're definitely
185
0:9:35,58 --> 0:9:40,52
in the past, even if their xmin,
xmax look like they are in the
186
0:9:40,52 --> 0:9:41,02
future.
187
0:9:41,6 --> 0:9:42,46
This is freezing.
188
0:9:42,54 --> 0:9:43,4
It marks like...
189
0:9:44,16 --> 0:9:47,86
All frozen bit means like it's
a whole page in the past.
190
0:9:47,86 --> 0:9:49,78
The next vacuum will just skip
it.
191
0:9:49,92 --> 0:9:51,58
That's optimization as well, right?
192
0:9:51,58 --> 0:9:56,66
So for more frequent vacuuming,
not to do the same job once again,
193
0:9:57,26 --> 0:9:57,76
right?
194
0:9:58,14 --> 0:10:0,72
Michael: I want to come back to
that, but before we do, The all
195
0:10:0,72 --> 0:10:4,26
visible is really important for
index only scan performance,
196
0:10:4,34 --> 0:10:4,84
right?
197
0:10:5,46 --> 0:10:14,1
So if an index only scan can know
that every single tuple on
198
0:10:14,1 --> 0:10:19,18
that page is visible to all transactions
then it can serve the
199
0:10:20,02 --> 0:10:23,3
result it finds in the index because
it knows it can't have changed.
200
0:10:23,42 --> 0:10:27,72
So that's a really neat optimization
without having to do what
201
0:10:27,72 --> 0:10:28,94
it calls a heap fetch.
202
0:10:28,94 --> 0:10:31,56
So it's like fetching the data
from the table instead of from
203
0:10:31,56 --> 0:10:32,2
the index.
204
0:10:32,2 --> 0:10:34,86
So if you ever if you see an index
only scan that ends up with
205
0:10:34,86 --> 0:10:38,92
a lot of heap fetches that's because
Postgres couldn't...
206
0:10:39,38 --> 0:10:43,14
Yeah it might it might be that
information was in the index but
207
0:10:43,14 --> 0:10:46,8
because it Postgres didn't know
for sure that it hadn't changed
208
0:10:46,8 --> 0:10:48,66
it still went and got it from the
heap.
209
0:10:48,66 --> 0:10:51,04
So it might be the exact same information
that it already had
210
0:10:51,04 --> 0:10:53,6
from the index, but there's this
inefficiency if vacuum hasn't
211
0:10:53,6 --> 0:10:54,76
run recently enough.
212
0:10:54,76 --> 0:10:58,62
And it only takes, because it's
that bit 0 or 1, it only takes
213
0:10:58,62 --> 0:11:2,88
1 tuple on the page to have changed
for any of the tuples on
214
0:11:2,88 --> 0:11:6,36
that page to lose out on index
only scans.
215
0:11:6,58 --> 0:11:9,34
Nikolay: I think if information
is not in the index, you mean
216
0:11:9,34 --> 0:11:12,9
if we select columns which are
not part of index definition,
217
0:11:12,94 --> 0:11:15,62
it will be index scan immediately,
not index only scan.
218
0:11:15,62 --> 0:11:16,52
Michael: Yeah, of course.
219
0:11:16,52 --> 0:11:19,1
Nikolay: And index only scan already
means that information is
220
0:11:19,1 --> 0:11:19,6
present.
221
0:11:19,9 --> 0:11:25,54
Information means values, but what
is never present in indexes
222
0:11:26,32 --> 0:11:27,7
is visibility information.
223
0:11:27,7 --> 0:11:29,16
This xmin, xmax.
224
0:11:29,88 --> 0:11:35,32
So For that we need heap, but if
visibility map bit says for
225
0:11:35,32 --> 0:11:38,0
this page it's all visible, this
can be skipped.
226
0:11:38,24 --> 0:11:42,26
So if the fetch's number goes lower,
ideally it should be 0,
227
0:11:42,26 --> 0:11:45,26
then it's a perfect situation,
it's a true index-only scan.
228
0:11:45,3 --> 0:11:49,4
If it's high, it approaches the
performance of index scan, which
229
0:11:49,4 --> 0:11:51,26
is like always consulting heap.
230
0:11:52,28 --> 0:11:55,52
Yeah, naming should be better here,
but my position on naming,
231
0:11:55,52 --> 0:11:59,78
I'm always like, index scan could
be renamed to something which
232
0:11:59,78 --> 0:12:3,58
would be explicitly mentioning
that heap is always consulted.
233
0:12:4,46 --> 0:12:6,36
Anyway, this is a different topic.
234
0:12:6,7 --> 0:12:11,4
I think we covered quite well what
autovacuum does, and again,
235
0:12:11,4 --> 0:12:13,74
the main job is just garbage collection.
236
0:12:14,06 --> 0:12:19,92
Also, I wanted to mention, autovacuum
is improving a lot from
237
0:12:19,92 --> 0:12:20,94
release to release.
238
0:12:21,42 --> 0:12:23,4
And it's enabled by default, of
course.
239
0:12:24,64 --> 0:12:27,02
It should be disabled only by experts.
240
0:12:27,12 --> 0:12:32,58
For example, PgQ, Skype engineers
decided to disable autovacuum
241
0:12:32,68 --> 0:12:34,44
for queue partitions.
242
0:12:35,32 --> 0:12:38,8
And it's also disabled in PgQue tool,
which is built on top of
243
0:12:38,8 --> 0:12:39,3
PgQ.
244
0:12:39,52 --> 0:12:40,82
Name is awful, right?
245
0:12:43,14 --> 0:12:47,54
So anyway, there autovacuum is
disabled, but normally it should
246
0:12:47,54 --> 0:12:50,0
be never disabled, and it's enabled
by default.
247
0:12:50,28 --> 0:12:52,08
And it's done, drop, and so on.
248
0:12:52,58 --> 0:12:57,26
So it's just a garbage collection
plus additional features and
249
0:12:57,26 --> 0:13:1,92
it's improving from release to
release and Funny fact I recently
250
0:13:2,02 --> 0:13:6,58
purchased some Chinese modern auto
vacuum for home with washing
251
0:13:6,58 --> 0:13:6,98
feature.
252
0:13:6,98 --> 0:13:10,28
It's very similar, like advancement,
like I had a few years ago,
253
0:13:10,28 --> 0:13:13,44
I had a couple of them and they
were now there, like so many
254
0:13:13,44 --> 0:13:15,6
features, so it became much smarter.
255
0:13:15,86 --> 0:13:17,78
And they have multiple functions.
256
0:13:18,28 --> 0:13:20,46
So I enjoy how it works really.
257
0:13:20,92 --> 0:13:22,98
But it requires some tuning as
well.
258
0:13:23,6 --> 0:13:26,08
Michael: Yeah, I was gonna say,
Bruce brought this up in our
259
0:13:26,08 --> 0:13:27,16
episode with him, didn't he?
260
0:13:27,16 --> 0:13:30,82
He said people complain about vacuum
and bloat with Postgres
261
0:13:31,4 --> 0:13:34,12
and MVCC, but he's saying, which
version are you complaining
262
0:13:34,12 --> 0:13:34,44
about?
263
0:13:34,44 --> 0:13:36,68
Because it is continually getting
better.
264
0:13:36,82 --> 0:13:42,9
But I would say that some of the
defaults are still very conservative,
265
0:13:43,3 --> 0:13:47,12
or maybe make sense at smaller
table sizes.
266
0:13:47,46 --> 0:13:51,22
And they do have scale factors
built in, but they make less and
267
0:13:51,22 --> 0:13:54,52
less sense I think as tables get
bigger, some of them.
268
0:13:54,96 --> 0:13:59,34
Nikolay: So my position on defaults,
they are all BS defaults.
269
0:14:1,56 --> 0:14:8,5
They are like for, I call it Postgres,
kitchen kettle Postgres,
270
0:14:8,64 --> 0:14:13,2
which should have, I don't know,
like 1 gigabyte memory and some
271
0:14:13,2 --> 0:14:16,08
Raspberry Pi or something, a smart
pod or something.
272
0:14:16,08 --> 0:14:16,98
This is it.
273
0:14:17,22 --> 0:14:22,04
For them it's okay, but for any
even like small cluster with
274
0:14:22,04 --> 0:14:28,08
8 cores, 16 gig of memory, it's
not enough at all.
275
0:14:28,26 --> 0:14:32,02
And the settings can be split to
3 categories for simplicity.
276
0:14:32,86 --> 0:14:34,78
Number of workers, which requires
restart.
277
0:14:34,78 --> 0:14:37,8
The only thing which requires restarted
number is number of workers,
278
0:14:37,8 --> 0:14:39,18
which is 3 by default.
279
0:14:39,52 --> 0:14:41,96
If you have 8 cores, 3 maybe is
okay.
280
0:14:41,96 --> 0:14:42,68
It's okay.
281
0:14:42,88 --> 0:14:53,46
If you have 32, 64, 48, 96 cores,
3 is not enough, but we see
282
0:14:53,46 --> 0:14:54,44
it all the time.
283
0:14:54,6 --> 0:14:57,54
People come to us, 96 cores, 3
workers.
284
0:14:58,38 --> 0:14:59,44
This is 1 thing.
285
0:14:59,48 --> 0:15:0,92
Michael: You say it's not enough.
286
0:15:1,84 --> 0:15:4,9
I think you're right in the sense
it's not a sensible default.
287
0:15:4,9 --> 0:15:8,14
Like why not give it more in case
it needs it?
288
0:15:8,14 --> 0:15:8,64
Nikolay: Right.
289
0:15:9,14 --> 0:15:12,04
Michael: But as you said, sometimes
people come to you and they've
290
0:15:12,04 --> 0:15:15,92
only had 3 workers the whole time
and somehow it's not fallen
291
0:15:15,92 --> 0:15:16,42
over.
292
0:15:18,72 --> 0:15:21,48
Nikolay: It's grinding through
challenges.
293
0:15:21,53 --> 0:15:22,03
Yeah.
294
0:15:22,08 --> 0:15:26,82
Like super bloated tables, super
bloated indexes, and it's a
295
0:15:26,82 --> 0:15:30,68
lot of dirt to clean, which is
great for us.
296
0:15:30,68 --> 0:15:32,54
We have opportunity to help them.
297
0:15:32,64 --> 0:15:35,86
Instead of framing, oh, how bad
it is, I actually have it, and
298
0:15:35,86 --> 0:15:37,52
it's actually our product strategy.
299
0:15:38,16 --> 0:15:41,52
We frame it, oh, great, we can
help you really quickly, really
300
0:15:41,52 --> 0:15:42,02
quickly.
301
0:15:42,04 --> 0:15:43,94
Either way, we have low-hanging
fruit.
302
0:15:43,94 --> 0:15:44,68
Let's go.
303
0:15:45,06 --> 0:15:47,8
With our tooling and methodologies,
it's super simple.
304
0:15:47,8 --> 0:15:52,36
This low-hanging fruit, let's go,
and your database will fill
305
0:15:52,36 --> 0:15:54,12
and breathe quite soon.
306
0:15:54,28 --> 0:15:55,14
Much better.
307
0:15:55,24 --> 0:15:59,24
You can even consider downgrading
or postponing upgrade for a
308
0:15:59,24 --> 0:16:0,74
couple of years after this.
309
0:16:0,74 --> 0:16:1,24
Yeah.
310
0:16:1,38 --> 0:16:2,42
And this is great.
311
0:16:2,78 --> 0:16:3,94
Yeah, this is 1 thing.
312
0:16:3,94 --> 0:16:6,02
And this is super important thing,
we just discussed.
313
0:16:6,02 --> 0:16:10,92
This is how garbage collection
works and updates, deletes, and
314
0:16:10,92 --> 0:16:11,82
sometimes inserts.
315
0:16:11,82 --> 0:16:13,44
They do just part of the job.
316
0:16:14,28 --> 0:16:14,78
Right?
317
0:16:14,82 --> 0:16:20,98
And these poor autovacuum workers
need to do the rest of the
318
0:16:20,98 --> 0:16:21,48
job.
319
0:16:22,36 --> 0:16:23,6
Michael: The tidying up afterwards,
320
0:16:23,64 --> 0:16:24,14
Nikolay: yeah.
321
0:16:24,24 --> 0:16:28,16
You have 1,000 max_connections,
meaning you have up to 1,000
322
0:16:28,32 --> 0:16:34,22
back-end workers which produce
all those dead tuples.
323
0:16:34,94 --> 0:16:37,54
And only 3 that should catch up
with them.
324
0:16:37,54 --> 0:16:38,56
It's nonsense, right?
325
0:16:38,56 --> 0:16:40,1
It feels like it's nonsense.
326
0:16:40,28 --> 0:16:42,1
So it should be tuned.
327
0:16:42,1 --> 0:16:46,4
And simple rule, like we say, like
actually let's consider like
328
0:16:46,4 --> 0:16:51,94
25% of vCPU count, But we should
do it very properly, thinking
329
0:16:51,94 --> 0:16:54,22
about memory management and so
on.
330
0:16:54,78 --> 0:16:58,78
I know there is opposition to this
view, but this is my position.
331
0:16:58,78 --> 0:17:1,64
It's a simple case, just let's
give more workers, especially
332
0:17:1,64 --> 0:17:2,58
if you have partitioning.
333
0:17:3,68 --> 0:17:10,08
Because, fun fact, a worker processing
a table, if it's a huge
334
0:17:10,08 --> 0:17:13,38
table, it will be processing it
sequentially, your table and
335
0:17:13,38 --> 0:17:14,92
its indexes, and that's it.
336
0:17:14,92 --> 0:17:18,34
If it's a partitioned table, it
can be distributed.
337
0:17:18,4 --> 0:17:21,42
Each partition can be, you can
parallelize this, right?
338
0:17:21,6 --> 0:17:24,98
So it makes sense to have more
workers if you have more partitions.
339
0:17:25,6 --> 0:17:28,62
And it's great to have partitions
and more workers together.
340
0:17:28,62 --> 0:17:29,78
This is the best situation.
341
0:17:30,18 --> 0:17:31,74
And 2 more categories.
342
0:17:32,22 --> 0:17:34,66
1 defines frequency of revisiting.
343
0:17:35,82 --> 0:17:40,46
Frequency, how frequent workers
come to do stuff.
344
0:17:40,84 --> 0:17:45,04
And another defines how fast they
can throughput, basically,
345
0:17:45,04 --> 0:17:46,04
or throttling.
346
0:17:46,38 --> 0:17:47,42
I think
347
0:17:47,42 --> 0:17:49,66
Michael: throttling's the better
way of thinking about it, yeah.
348
0:17:49,66 --> 0:17:50,82
Nikolay: Throttling, yeah, limiting.
349
0:17:51,22 --> 0:17:53,22
It's cost_limit and cost_delay.
350
0:17:53,32 --> 0:17:56,6
And how often they visit defines
by scale factors and threshold,
351
0:17:56,6 --> 0:17:59,84
but I'm okay to think about only
scale factors, actually.
352
0:18:0,52 --> 0:18:2,22
At first glance, it's enough.
353
0:18:2,86 --> 0:18:6,02
So we have 3 scale factors today,
right?
354
0:18:6,02 --> 0:18:10,22
Or maybe there is also in Postgres
18, there is
355
0:18:10,58 --> 0:18:12,22
autovacuum_vacuum_max_threshold.
356
0:18:12,88 --> 0:18:17,22
This is a new stuff in Postgres
18, which changes the picture.
357
0:18:17,82 --> 0:18:23,22
So usually we talked about only
scale factor and threshold.
358
0:18:23,22 --> 0:18:28,68
Scale factor by default, 3 scale
factors, but the basic 1 is
359
0:18:28,78 --> 0:18:31,5
autovacuum_vacuum_scale_factor,
right?
360
0:18:31,98 --> 0:18:34,34
And it is either 10 or 20 percent.
361
0:18:34,54 --> 0:18:37,08
So I think 20 percent, right?
362
0:18:37,36 --> 0:18:40,76
Michael: Yeah, so I suppose because
the threshold by default
363
0:18:40,76 --> 0:18:43,04
is 0.2, right, so 20 percent.
364
0:18:43,04 --> 0:18:45,2
Let's say you've got 1000000000
rows in the table.
365
0:18:45,2 --> 0:18:49,5
It doesn't wait to get to 200 million,
it starts at 100 million.
366
0:18:49,9 --> 0:18:53,04
Nikolay: Yeah, so we don't allow
more than 100 million, which
367
0:18:53,04 --> 0:18:54,04
is a huge number.
368
0:18:54,38 --> 0:18:55,68
Maybe huge, maybe not.
369
0:18:55,68 --> 0:18:57,98
100 million dead tuples in the
table.
370
0:18:58,08 --> 0:18:59,94
Michael: It's quite a lot though,
yeah.
371
0:19:0,2 --> 0:19:4,8
Nikolay: Yeah, so the basic is
the vacuum scale factor.
372
0:19:5,86 --> 0:19:7,06
This is the first thing.
373
0:19:7,06 --> 0:19:10,88
And it's 20% by default, which
means you need to accumulate 20%
374
0:19:11,12 --> 0:19:15,04
of dead tuples in the table before
it starts garbage collection.
375
0:19:15,32 --> 0:19:17,6
When I just say this, I had recent
experiences.
376
0:19:18,42 --> 0:19:21,76
When I said this to some startup
CTO who which is growing and
377
0:19:21,76 --> 0:19:26,5
so on he like, oh We don't have
garbage collection before 20%
378
0:19:26,64 --> 0:19:30,9
of dirt accumulated This is
379
0:19:32,68 --> 0:19:35,2
Michael: Of course when when things
are small, it's not a big
380
0:19:35,2 --> 0:19:35,6
deal.
381
0:19:35,6 --> 0:19:39,16
But when things get big, this is
just a huge number.
382
0:19:39,16 --> 0:19:40,36
And it's not just...
383
0:19:41,04 --> 0:19:41,7
Nikolay: Yeah, it's...
384
0:19:41,94 --> 0:19:46,96
Let's say you have like almost
terabyte size table in terms of
385
0:19:46,96 --> 0:19:52,1
size, billion rows unpartitioned,
which is common, I see this.
386
0:19:53,0 --> 0:19:58,66
20% means 200 million rows, dead
tuples, right?
387
0:19:58,66 --> 0:20:2,54
Which is by the way above that
threshold introduced in Postgres
388
0:20:2,56 --> 0:20:3,06
18.
389
0:20:4,4 --> 0:20:5,26
So, it's like, wow.
390
0:20:5,34 --> 0:20:7,74
Michael: But it's not just storage,
right?
391
0:20:7,74 --> 0:20:12,02
It's also polluting caches and
indexes.
392
0:20:12,34 --> 0:20:13,12
It's everything.
393
0:20:13,12 --> 0:20:14,6
Nikolay: Oh yes, oh yes.
394
0:20:14,6 --> 0:20:15,36
This is big point.
395
0:20:15,36 --> 0:20:18,82
And actually, let me add 1 important
notice here.
396
0:20:19,7 --> 0:20:23,94
Usually, it's not a big deal for
smaller tables.
397
0:20:24,52 --> 0:20:26,9
But in some cases, we see local...
398
0:20:27,98 --> 0:20:31,86
So if, for example, 1 row updated
many times, thousands of times.
399
0:20:32,36 --> 0:20:36,14
For 1 logical row, you have many
versions.
400
0:20:37,9 --> 0:20:44,74
And globally, like table is big,
but for this not lucky row,
401
0:20:45,3 --> 0:20:49,88
You have so many versions and they
can be, might be scattered
402
0:20:49,9 --> 0:20:51,0
among many pages.
403
0:20:51,94 --> 0:20:56,74
So, they are sitting there as data
tuples and for this specific
404
0:20:56,8 --> 0:20:59,18
query select where id equals something.
405
0:21:0,58 --> 0:21:4,16
This means that all of them need
to be fetched to be checked
406
0:21:4,16 --> 0:21:7,54
in terms of visibility for this
transaction and it degrades for
407
0:21:7,54 --> 0:21:10,08
a particular ID, like local degradation.
408
0:21:11,08 --> 0:21:15,88
Lots of queries are fine, but this
unlucky because it had a lot
409
0:21:15,88 --> 0:21:17,82
of updates or something, right?
410
0:21:18,08 --> 0:21:19,92
It became really degraded.
411
0:21:19,92 --> 0:21:21,82
And it's like, what's happening
here?
412
0:21:21,82 --> 0:21:25,92
This is where p99s or something
are good to have because average
413
0:21:25,92 --> 0:21:29,1
will hide it, average latency and
so on.
414
0:21:30,06 --> 0:21:34,4
And this means you should be vacuuming
more frequently, even
415
0:21:34,4 --> 0:21:35,46
on smaller tables.
416
0:21:36,28 --> 0:21:41,82
So this local degradation due to
dead tuple for particular logical
417
0:21:41,82 --> 0:21:44,62
rows, dead tuple count is high.
418
0:21:45,6 --> 0:21:47,78
So it's happening, and it's happening
silently.
419
0:21:47,9 --> 0:21:48,78
That's the problem.
420
0:21:48,92 --> 0:21:52,8
And tooling, which is like lacking
p99s and so on, is not helping
421
0:21:52,8 --> 0:21:53,72
us to understand.
422
0:21:53,8 --> 0:21:58,56
That's why still logging of slow
queries helps, and auto_explain
423
0:21:58,84 --> 0:22:5,28
helps to catch these like edge
cases and start analyzing why
424
0:22:5,28 --> 0:22:6,08
it's happening.
425
0:22:6,22 --> 0:22:9,94
The next day you select the same
row, maybe it's already vacuumed
426
0:22:9,96 --> 0:22:11,46
and degradation has gone.
427
0:22:12,98 --> 0:22:18,96
But in that moment, if you go back
in time and select it, you
428
0:22:18,96 --> 0:22:20,24
see so many buffers.
429
0:22:20,74 --> 0:22:23,68
This particular query, it's very
like it's primary key lookup,
430
0:22:23,68 --> 0:22:25,14
but too many buffers somehow.
431
0:22:25,14 --> 0:22:25,82
That's why.
432
0:22:26,14 --> 0:22:29,8
So it's important to feel it because
it's really like subtle
433
0:22:29,8 --> 0:22:30,14
problem.
434
0:22:30,14 --> 0:22:33,06
It's hard to catch it if you don't
know where to look at.
435
0:22:33,74 --> 0:22:34,24
Yeah.
436
0:22:34,54 --> 0:22:35,38
And you're right.
437
0:22:35,38 --> 0:22:36,36
So scale factors.
438
0:22:36,58 --> 0:22:39,66
And since Postgres 13, there is
also autovacuum_vacuum_insert_scale_factor,
439
0:22:39,66 --> 0:22:42,54
and there is also
scale factor for analyzing.
440
0:22:43,52 --> 0:22:44,9
For insert, it's really great.
441
0:22:44,9 --> 0:22:49,94
I remember Darafei, the guy who,
from Belarus, I think, he introduced
442
0:22:49,94 --> 0:22:50,14
it.
443
0:22:50,14 --> 0:22:52,12
It was so obvious, why didn't we
have it?
444
0:22:52,12 --> 0:22:55,84
We insert a lot with double table
in size, but vacuum doesn't
445
0:22:55,84 --> 0:22:56,34
come.
446
0:22:56,4 --> 0:23:0,04
And we need vacuum not to clean
up the tuples after successful
447
0:23:0,08 --> 0:23:3,66
insert, but to rebuild visibility
maps, first of all.
448
0:23:4,12 --> 0:23:8,46
And yeah, it is great because if
you have select count or something,
449
0:23:8,46 --> 0:23:11,76
you want index-only scan to be
with low heap fetches, as you
450
0:23:11,76 --> 0:23:12,26
mentioned.
451
0:23:12,44 --> 0:23:15,84
So anyway, there are these scale
factors, And it's enough at
452
0:23:15,84 --> 0:23:17,54
first glance to look only at them.
453
0:23:17,72 --> 0:23:21,64
Yes, you can go deeper and think
about thresholds and how additional
454
0:23:21,72 --> 0:23:24,78
tuning, but scale factors is already
enough.
455
0:23:25,34 --> 0:23:30,22
You want them to be really low
in OLTP workloads, just 1%.
456
0:23:31,32 --> 0:23:35,08
Sometimes 2%, sometimes 1%, I see
people choose, but 1% is is
457
0:23:35,08 --> 0:23:35,96
simple rule.
458
0:23:36,66 --> 0:23:40,58
Set it to 1 percent for all scale
factors and benefit.
459
0:23:40,92 --> 0:23:43,9
Michael: And to give people an
idea of how drastic a change that
460
0:23:43,9 --> 0:23:48,3
is, these scale factors are 20
percent for the vacuum threshold,
461
0:23:48,52 --> 0:23:52,04
10 percent for the analyze threshold,
and I think 20% also for
462
0:23:52,04 --> 0:23:53,48
the insert scale factor.
463
0:23:53,48 --> 0:23:53,88
Nikolay: Yes.
464
0:23:53,88 --> 0:23:54,34
So
465
0:23:54,34 --> 0:23:58,74
Michael: dropping from 20 to 1
might feel like a huge change,
466
0:23:58,74 --> 0:24:2,44
it is quite a huge change, But
you're not repeating the same
467
0:24:2,44 --> 0:24:2,98
work, right?
468
0:24:2,98 --> 0:24:5,42
Like it's not, there's a tiny bit
of repetition.
469
0:24:6,2 --> 0:24:10,84
Yeah, it's, this is a slight difference
to analyze, isn't it,
470
0:24:10,84 --> 0:24:14,62
in that if you run vacuum twice
in quick succession on the same
471
0:24:14,62 --> 0:24:17,8
table, It's not doing all of the
same work again.
472
0:24:17,8 --> 0:24:19,12
It's done a lot of the cleanup.
473
0:24:19,12 --> 0:24:20,7
It's like tidying a room.
474
0:24:20,74 --> 0:24:21,4
Nikolay: Some work
475
0:24:21,54 --> 0:24:21,82
Michael: can
476
0:24:21,82 --> 0:24:22,82
Nikolay: be done again.
477
0:24:22,82 --> 0:24:25,92
For example, it's very nuanced
here.
478
0:24:25,92 --> 0:24:26,92
It's super interesting.
479
0:24:26,98 --> 0:24:29,8
Like you mentioned, it's not only
about data storage.
480
0:24:29,8 --> 0:24:32,56
It's polluting memory, WAL.
481
0:24:32,78 --> 0:24:34,84
WAL means replication, WAL backups.
482
0:24:35,5 --> 0:24:36,64
It's polluting everything.
483
0:24:36,76 --> 0:24:40,14
And memory is super, memory is
expensive these days, right?
484
0:24:42,04 --> 0:24:45,1
So we should optimize, not about
data storage, we should think
485
0:24:45,1 --> 0:24:49,46
about how many pages we need to
keep in this working set.
486
0:24:49,74 --> 0:24:55,58
But the ideal situation when you
raise the workers, make a vacuum
487
0:24:55,58 --> 0:24:59,62
to visit us frequently with lowering
scale factors, all of them
488
0:24:59,62 --> 0:25:2,5
to say 1% is very rough rule here.
489
0:25:2,94 --> 0:25:7,08
But also partition quite well,
because in this case some partitions,
490
0:25:7,2 --> 0:25:11,26
especially if it's historic data,
they will be processed with
491
0:25:11,26 --> 0:25:15,52
marked all visible, all frozen,
and very rarely those pages will
492
0:25:15,52 --> 0:25:16,2
be touched.
493
0:25:17,52 --> 0:25:21,24
So vacuuming will be like a breeze,
like skipping, right?
494
0:25:21,34 --> 0:25:27,0
Unlike if it's a huge, messy heap
with terabyte in size or so,
495
0:25:27,34 --> 0:25:30,6
and any page can be touched at
any given time.
496
0:25:31,1 --> 0:25:33,58
It means it will be need to process
again.
497
0:25:34,08 --> 0:25:38,24
Of course it means that if you
have infrequent vacuuming of a
498
0:25:38,24 --> 0:25:43,26
huge table, of course you're doing
work less, because maybe this
499
0:25:43,26 --> 0:25:46,28
page was visited multiple times
before it was vacuumed.
500
0:25:47,02 --> 0:25:51,6
And if you start vacuuming frequently
and between 2 processing
501
0:25:51,7 --> 0:25:56,82
these pages are revisited by some
rates, then it needs to be
502
0:25:56,82 --> 0:25:57,76
vacuumed again.
503
0:25:58,18 --> 0:26:2,96
So it's multiple processing of
the same page versus a single
504
0:26:2,96 --> 0:26:3,34
processing.
505
0:26:3,34 --> 0:26:7,12
So we cannot say it will be, but
it's highly optimized.
506
0:26:7,12 --> 0:26:8,34
Vacuum is highly optimized.
507
0:26:9,02 --> 0:26:12,9
But if you have a huge table, not
partition, maybe it will be
508
0:26:12,9 --> 0:26:17,16
like frequency, high frequency
vacuuming will cost you some extra,
509
0:26:17,16 --> 0:26:18,58
but it's worth it usually.
510
0:26:18,94 --> 0:26:21,38
So there are nuances here and trade-offs,
of course.
511
0:26:21,58 --> 0:26:27,42
But usually in OLTP, we very strongly
recommend to lower down
512
0:26:27,44 --> 0:26:30,26
scale factors so vacuuming happens
more frequently.
513
0:26:30,78 --> 0:26:35,2
And the fact is that if you're
on managed service, I see it's
514
0:26:35,2 --> 0:26:36,0
quite common.
515
0:26:36,66 --> 0:26:37,86
This is a big problem.
516
0:26:38,26 --> 0:26:39,9
RDS included, for example.
517
0:26:40,4 --> 0:26:43,26
They don't care about this somehow
and they keep defaults.
518
0:26:44,5 --> 0:26:48,58
I would like to hear their reasoning
why they don't proactively
519
0:26:48,8 --> 0:26:50,3
tune it for the customers.
520
0:26:51,5 --> 0:26:52,96
And because I
521
0:26:52,96 --> 0:26:54,92
Michael: mean, I mean, I mean,
I'm just makes, because they're
522
0:26:54,92 --> 0:26:55,92
a scale factor, right?
523
0:26:55,92 --> 0:26:57,72
They can make sense at any scale,
right?
524
0:26:57,72 --> 0:27:1,32
Like it, it's fine when you're
small, These are inexpensive things
525
0:27:1,32 --> 0:27:3,94
to run on small tables, and it
works when it's big.
526
0:27:4,12 --> 0:27:7,54
There's no reason not to tune it
from the start for all customers.
527
0:27:7,78 --> 0:27:11,38
You don't have to be careful about
which instance size.
528
0:27:11,38 --> 0:27:14,96
Nikolay: And I don't complain,
because as I said, I enjoy when
529
0:27:14,96 --> 0:27:16,08
I see the problem.
530
0:27:16,08 --> 0:27:20,28
And I'm excited to help and have
low-hanging fruit and see
531
0:27:20,28 --> 0:27:22,54
how health next day is much better.
532
0:27:22,72 --> 0:27:25,96
But of course we need also automated
reindexing, we need the
533
0:27:25,96 --> 0:27:28,38
pg_repack to be used and so on.
534
0:27:28,86 --> 0:27:32,7
By the way, we mentioned that Postgres
19 will have...
535
0:27:33,4 --> 0:27:33,54
Yeah.
536
0:27:33,54 --> 0:27:34,62
Yeah, it will have...
537
0:27:36,28 --> 0:27:37,8
Michael: REPACK and REPACK CONCURRENTLY.
538
0:27:38,68 --> 0:27:39,86
Nikolay: That's awesome.
539
0:27:39,96 --> 0:27:43,84
And we should somehow revisit this
topic, maybe inviting the
540
0:27:43,84 --> 0:27:45,6
guy who made it, right?
541
0:27:45,9 --> 0:27:47,01
Michael: Yeah, I think it was...
542
0:27:47,01 --> 0:27:47,38
Antonín, right?
543
0:27:47,38 --> 0:27:48,48
Yeah, Antonín was...
544
0:27:48,48 --> 0:27:51,92
We had him on, didn't we, to talk
about pg_squeeze, which inspired
545
0:27:52,04 --> 0:27:52,42
the work.
546
0:27:52,42 --> 0:27:56,88
Nikolay: Remember in the very end
of the episode, I learned about
547
0:27:56,88 --> 0:27:59,68
these plans to make VACUUM FULL
concurrently basically, which
548
0:27:59,68 --> 0:28:2,06
is like became REPACK CONCURRENTLY.
549
0:28:2,24 --> 0:28:5,8
I couldn't believe, I had like
doubts, is it like, but here we
550
0:28:5,8 --> 0:28:10,84
go, like this is happening a year
later, it's planned to be released,
551
0:28:10,84 --> 0:28:13,66
I hope it won't be reverted, it's
a super important feature to
552
0:28:13,66 --> 0:28:15,58
have, it's interesting how out
of the box.
553
0:28:15,58 --> 0:28:20,02
Michael: I have to admit when I,
yeah, I saw that REPACK, they
554
0:28:20,02 --> 0:28:24,28
introduced effectively a rename
of VACUUM FULL to REPACK and that
555
0:28:24,28 --> 0:28:26,98
was going to make 19 but it didn't
have a concurrently option
556
0:28:26,98 --> 0:28:29,6
and I was like, oh, that's such
a shame but it makes sense.
557
0:28:29,6 --> 0:28:30,76
Nikolay: Another year of waiting.
558
0:28:31,68 --> 0:28:34,28
Michael: And then about a week
later, REPACK CONCURRENTLY gets
559
0:28:34,28 --> 0:28:35,2
committed as well.
560
0:28:35,2 --> 0:28:36,22
So yeah, that was great.
561
0:28:36,22 --> 0:28:40,32
Nikolay: It's yeah, it was a mood
swing for me as well.
562
0:28:40,32 --> 0:28:41,38
It was like, oh no.
563
0:28:41,38 --> 0:28:43,14
Oh, yeah.
564
0:28:43,14 --> 0:28:45,42
So anyway, back to scale factors.
565
0:28:45,66 --> 0:28:51,54
This is probably 1 of the most
important to lower scale factors
566
0:28:51,54 --> 0:28:55,46
for OLTP workloads and benefit
from more frequent vacuuming
567
0:28:56,6 --> 0:28:58,24
and analyzing as well, right?
568
0:28:58,26 --> 0:29:0,72
Michael: Just a question, is there
any stage that people are
569
0:29:0,72 --> 0:29:2,54
at where you wouldn't recommend
this.
570
0:29:2,64 --> 0:29:5,38
I was thinking when should people
be thinking about these things
571
0:29:5,38 --> 0:29:8,6
but I think those 2 are such simple
or those 3 let's say are
572
0:29:8,6 --> 0:29:11,96
such simple settings to change
you could change them from the
573
0:29:11,96 --> 0:29:14,18
start and never think about it
again like
574
0:29:14,18 --> 0:29:14,8
Nikolay: globally I
575
0:29:14,8 --> 0:29:15,52
Michael: was thinking.
576
0:29:15,72 --> 0:29:20,34
Nikolay: This is complex and this
is complex thing in terms of
577
0:29:20,74 --> 0:29:24,98
we cannot talk about autovacuum
tuning completely without analyzing
578
0:29:25,38 --> 0:29:28,58
what's blocking the work.
579
0:29:28,78 --> 0:29:29,52
Michael: If anything.
580
0:29:30,34 --> 0:29:33,28
Nikolay: Yes and that's why I'm
like we recently developed a
581
0:29:33,28 --> 0:29:37,2
dashboard for xmin horizon analysis
because we we probably need
582
0:29:37,2 --> 0:29:41,98
to revisit it once again in terms
of long transactions versus
583
0:29:42,42 --> 0:29:47,16
pure xmin horizon blocker analysis
and autovacuum throughput
584
0:29:47,16 --> 0:29:50,46
analysis and again like this I
cannot recommend enough Laurenz
585
0:29:50,46 --> 0:29:54,26
Albe recent blog post about how
he monitors autovacuum.
586
0:29:55,68 --> 0:29:58,94
Combining with what, how we monitor
autovacuum, I think it's
587
0:29:58,94 --> 0:30:3,82
much like we leveled up monitoring
of autovacuum blockers basically,
588
0:30:3,82 --> 0:30:4,04
right?
589
0:30:4,04 --> 0:30:8,42
So xmin horizon, there are 5 reasons
why it can be blocked.
590
0:30:9,52 --> 0:30:14,6
And if you keep those problems
unresolved for hours, or sometimes
591
0:30:14,6 --> 0:30:19,08
dozens of hours, tuning autovacuum
to run more frequently, especially
592
0:30:19,08 --> 0:30:23,86
if you reduce also autovacuum_naptime, how
long it sleeps between runs,
593
0:30:24,16 --> 0:30:25,18
and raised workers.
594
0:30:25,84 --> 0:30:28,62
And also, some problems might happen.
595
0:30:28,62 --> 0:30:32,06
For example, it might start consuming
too much resources just
596
0:30:32,06 --> 0:30:33,14
trying to do something.
597
0:30:33,14 --> 0:30:34,48
It cannot do something.
598
0:30:34,7 --> 0:30:38,22
And also, logging can be, you can
have observer effect.
599
0:30:38,8 --> 0:30:41,82
If there is a, like it tries to
do something, it cannot, but
600
0:30:41,82 --> 0:30:43,78
it reports and many workers report.
601
0:30:43,78 --> 0:30:47,92
And if you, at extreme, you have
log_autovacuum_min_duration
602
0:30:48,04 --> 0:30:51,3
set to 0, meaning all attempts
are logged.
603
0:30:51,42 --> 0:30:55,44
In this case, if you have 25 workers,
for example, and they cannot
604
0:30:55,44 --> 0:30:59,7
do, and they autovacuum_naptime 1 second,
it's a storm of logs.
605
0:30:59,72 --> 0:31:1,96
This is 1 problem I can definitely
imagine.
606
0:31:1,96 --> 0:31:3,06
Michael: You mean 1 millisecond?
607
0:31:3,84 --> 0:31:6,6
Nikolay: No, by default autovacuum_naptime
is 30 seconds.
608
0:31:7,2 --> 0:31:9,94
Michael: What am I thinking of
that's 2 milliseconds by default?
609
0:31:10,2 --> 0:31:11,48
Nikolay: Oh, actually I was wrong.
610
0:31:11,48 --> 0:31:14,28
I'm looking at it right now, it's
60, 1 minute.
611
0:31:15,48 --> 0:31:20,58
autovacuum_naptime is by default 1 minute,
which is quite long in my opinion,
612
0:31:20,9 --> 0:31:25,58
so we usually say let's choose
a few seconds, but I admit aggressive
613
0:31:25,68 --> 0:31:30,06
tuning without resolution of xmin horizon
blockers might lead
614
0:31:30,06 --> 0:31:33,66
to storm of logging and resource
utilization as well.
615
0:31:33,7 --> 0:31:37,08
So this is what I can think of
from top of my head.
616
0:31:37,54 --> 0:31:40,76
Michael: Yeah, so sorry, I was
thinking of cost, there's a cost
617
0:31:40,76 --> 0:31:41,26
delay.
618
0:31:41,28 --> 0:31:43,94
Nikolay: Right, this is the last
thing we haven't touched.
619
0:31:43,94 --> 0:31:47,16
So as I said, There are like throughput
in terms of number of
620
0:31:47,16 --> 0:31:50,68
workers, there is frequency, how
often vacuum and analyzing happens,
621
0:31:50,68 --> 0:31:54,22
and also the remaining piece, big
piece is throttling.
622
0:31:54,28 --> 0:31:56,26
You said we should say throttling,
right?
623
0:31:56,26 --> 0:31:57,42
So 2 parameters.
624
0:31:58,48 --> 0:32:0,88
And in Postgres, who is responsible
for naming?
625
0:32:1,64 --> 0:32:8,32
So there is an attempt to save
on some defaults or something.
626
0:32:8,32 --> 0:32:11,42
There is some parameters that have
relationships.
627
0:32:13,66 --> 0:32:14,98
Inheritance, right?
628
0:32:15,04 --> 0:32:17,74
So there are 2 parameters,
cost_delay and cost_limit.
629
0:32:18,2 --> 0:32:21,6
There are vacuum_cost_delay,
vacuum_cost_limit, this pair.
630
0:32:21,88 --> 0:32:25,14
And by default, I think cost_delay
is 0, means it's unthrottled.
631
0:32:25,24 --> 0:32:27,34
If you run vacuum manually, it's
unthrottled.
632
0:32:28,26 --> 0:32:32,6
It tries to go full speed, usually
bounded by I/O, disk.
633
0:32:33,06 --> 0:32:33,56
Right?
634
0:32:34,7 --> 0:32:37,66
And there is also autovacuum_vacuum_cost_delay,
635
0:32:37,66 --> 0:32:40,08
autovacuum_vacuum_cost_limit, 2 parameters.
636
0:32:40,08 --> 0:32:45,2
1 of which I think
autovacuum_vacuum_cost_limit is set to minus
637
0:32:45,2 --> 0:32:50,02
1, which means it inherits from
vacuum_cost_limit, which is set
638
0:32:50,02 --> 0:32:52,7
to 2 milliseconds, right?
639
0:32:52,7 --> 0:32:56,8
It was 200 milliseconds and then
it was, or 20 milliseconds in
640
0:32:56,8 --> 0:32:58,04
the past before Postgres.
641
0:32:59,18 --> 0:33:1,62
Michael: Yeah, the delay is, I've
just looked it up:
642
0:33:1,62 --> 0:33:3,46
autovacuum_vacuum_cost_delay is
643
0:33:3,46 --> 0:33:3,98
Nikolay: 2 milliseconds.
644
0:33:4,14 --> 0:33:6,04
Yeah, I confused everything, I
see.
645
0:33:6,26 --> 0:33:10,84
So autovacuum_vacuum_cost_delay
is 2 milliseconds and it was
646
0:33:10,92 --> 0:33:15,44
before Postgres 12 it was 30, so
it became 2 in Postgres 12 which
647
0:33:15,44 --> 0:33:16,12
is great.
648
0:33:16,62 --> 0:33:20,88
And autovacuum_vacuum_cost_limit
is minus 1 means that it inherits
649
0:33:20,92 --> 0:33:25,3
from vacuum_cost_limit Which is
by default 200
650
0:33:26,54 --> 0:33:30,3
Michael: Which is like an arbitrary
unit of like work right and
651
0:33:30,3 --> 0:33:33,22
there's some various things that
make up, yeah.
652
0:33:33,34 --> 0:33:37,94
Nikolay: Yeah, I your CPU cycles,
there is some math.
653
0:33:38,36 --> 0:33:42,8
What I don't like about acquisition
of EDB, of SecondQuadrant
654
0:33:42,8 --> 0:33:45,64
by EDB, they just killed the blog.
655
0:33:45,78 --> 0:33:47,06
Blog was brilliant.
656
0:33:47,22 --> 0:33:50,78
And they had a great blog post
about some math.
657
0:33:50,8 --> 0:33:54,9
If you think only about the I/O part,
all defaults before Postgres
658
0:33:54,9 --> 0:33:59,2
12 yielded to 8 MB/s of reads.
659
0:34:0,06 --> 0:34:4,78
So with 120 milliseconds, it was
roughly 8 mb of reads.
660
0:34:4,94 --> 0:34:10,32
So bumping 20 milliseconds to 2
milliseconds, I remember it was
661
0:34:10,32 --> 0:34:14,28
first considered to raise cost
limit, but then decided to reduce
662
0:34:14,38 --> 0:34:17,66
frequency of this
throttling, right?
663
0:34:17,66 --> 0:34:20,1
Because it makes things smoother,
right?
664
0:34:21,74 --> 0:34:25,18
So going down from 20 milliseconds
to 2 milliseconds and maintaining
665
0:34:25,38 --> 0:34:29,55
the cost_limit 200, inherited from
vacuum_cost_limit.
666
0:34:29,55 --> 0:34:32,96
I don't like this, just put straightforward
defaults.
667
0:34:32,96 --> 0:34:33,98
It doesn't hurt.
668
0:34:34,12 --> 0:34:39,52
Minus 1 makes life of humans much
harder, much harder, right?
669
0:34:39,52 --> 0:34:44,02
Like it's, okay, anyway, maybe
I should just propose it.
670
0:34:44,02 --> 0:34:44,92
Maybe it wasn't proposed.
671
0:34:44,92 --> 0:34:45,92
Maybe it was proposed.
672
0:34:46,42 --> 0:34:47,02
I don't know.
673
0:34:47,02 --> 0:34:50,74
It's My battle over dozens of,
over decades already.
674
0:34:50,74 --> 0:34:55,52
This is happening decades, this
suffering from memorizing what
675
0:34:55,52 --> 0:34:56,52
minus 1 means.
676
0:34:56,52 --> 0:34:58,22
We forgot actually memory management.
677
0:34:58,52 --> 0:34:59,48
Fourth piece, right?
678
0:34:59,54 --> 0:35:1,26
There is minus 1 there as well.
679
0:35:1,28 --> 0:35:5,2
autovacuum_work_mem is minus 1
by default, which means you need
680
0:35:5,2 --> 0:35:8,16
to go and consult and there is
big interesting trick happened
681
0:35:8,16 --> 0:35:10,22
in Postgres 17, separate story.
682
0:35:10,44 --> 0:35:10,84
So that's
683
0:35:10,84 --> 0:35:12,38
Michael: maintenance_work_mem,
right?
684
0:35:12,84 --> 0:35:14,28
Nikolay: Yeah, maintenance_work_mem.
685
0:35:14,34 --> 0:35:17,28
If we have time, we can talk about
that as well and dive into
686
0:35:17,28 --> 0:35:18,04
it a little bit.
687
0:35:18,04 --> 0:35:22,7
So, minus 1 for
autovacuum_vacuum_cost_limit inherited 200,
688
0:35:23,2 --> 0:35:27,04
this like arbitrary cost, not arbitrary
actually, but some cost
689
0:35:27,04 --> 0:35:28,28
like 2 milliseconds.
690
0:35:28,78 --> 0:35:31,8
Since Postgres 12, meaning in all
current versions, it means by
691
0:35:31,8 --> 0:35:37,8
default that can just take reads
of 80 MB/s,
692
0:35:38,44 --> 0:35:41,92
roughly, which is not enough in
modern systems.
693
0:35:42,26 --> 0:35:46,88
Ah, and it's shared among all workers,
unless you start tuning
694
0:35:46,88 --> 0:35:50,68
a table level, which makes things
much more complex because then
695
0:35:50,68 --> 0:35:53,9
quotas with throttling becomes
local for this table, for this
696
0:35:53,9 --> 0:35:56,54
worker which is processing specific
table.
697
0:35:56,76 --> 0:35:58,26
I prefer not to go there.
698
0:35:58,26 --> 0:36:1,66
We can have a separate episode
for table level analysis.
699
0:36:2,84 --> 0:36:4,36
Tuning, table level tuning.
700
0:36:4,36 --> 0:36:9,62
So big picture is like by default
it has only 80 MB/s
701
0:36:9,62 --> 0:36:15,06
of reads and if you
have powerful, even EBS volume
702
0:36:15,06 --> 0:36:21,34
which I don't know it's a nitro,
old nitro architecture so it
703
0:36:21,34 --> 0:36:25,08
definitely NVMe, like it has
good throughput.
704
0:36:25,96 --> 0:36:27,9
80 is tiny among all workers.
705
0:36:27,9 --> 0:36:30,26
Again, this is garbage collection
for everything.
706
0:36:30,76 --> 0:36:34,68
So it should have several hundred
megabytes per second at least.
707
0:36:34,78 --> 0:36:38,66
But the good thing is, for example,
RDS fixes this, especially
708
0:36:38,72 --> 0:36:42,24
on Aurora we see enormous quota.
709
0:36:42,78 --> 0:36:46,36
Throttling there is quite good
in terms of like it has a lot
710
0:36:46,36 --> 0:36:47,14
of power.
711
0:36:47,72 --> 0:36:53,1
But in many other cases, we see
it needs attention and we need
712
0:36:53,1 --> 0:36:59,22
to give more like, how to say,
work capacity because otherwise
713
0:36:59,22 --> 0:37:1,7
it's too slow And that's not good.
714
0:37:4,3 --> 0:37:6,4
Michael: It never catches up, if
that makes sense.
715
0:37:8,16 --> 0:37:9,36
Nikolay: It's a kind of situation.
716
0:37:9,52 --> 0:37:13,18
You see all the workers you allocated,
they're always busy.
717
0:37:13,18 --> 0:37:16,2
This is number 1, how you can understand
that something is not
718
0:37:16,2 --> 0:37:16,7
okay.
719
0:37:17,02 --> 0:37:20,14
And second, we have a special report,
we have a query, I have
720
0:37:20,14 --> 0:37:23,1
a blog post about that, and we
also have it in our monitoring,
721
0:37:23,72 --> 0:37:27,98
like a queue or line of tables
which sit there and should be
722
0:37:27,98 --> 0:37:30,4
already processed but not processed
yet.
723
0:37:30,4 --> 0:37:34,98
And this, like, basically a wait
line for tables.
724
0:37:35,28 --> 0:37:38,88
And I think Laurenz also has in
his blog post a slightly different
725
0:37:38,88 --> 0:37:39,38
analysis.
726
0:37:40,08 --> 0:37:41,88
But the idea is the same.
727
0:37:41,88 --> 0:37:43,5
How bad is it, the picture?
728
0:37:44,22 --> 0:37:46,24
It should be done already, but
not yet done.
729
0:37:46,24 --> 0:37:49,34
This is how you also feel this
situation happening.
730
0:37:50,98 --> 0:37:54,94
Michael: From the other side of
things, I saw a good post recently
731
0:37:54,94 --> 0:38:1,74
by Jeremy Schneider about the risk
of completely removing throttling.
732
0:38:2,08 --> 0:38:5,72
So he wrote a good post recently
about an issue they encountered
733
0:38:5,92 --> 0:38:6,16
once.
734
0:38:6,16 --> 0:38:7,7
I think they reduced the...
735
0:38:9,24 --> 0:38:10,34
Nikolay: I haven't seen it.
736
0:38:11,76 --> 0:38:13,48
Sometimes people put to Cron.
737
0:38:13,78 --> 0:38:16,58
We haven't touched this specific
cases related to MultiXact
738
0:38:16,92 --> 0:38:20,58
member situation when people have
this approaching and they need
739
0:38:20,58 --> 0:38:21,84
to vacuum separately.
740
0:38:22,34 --> 0:38:25,68
Switching of indexes because index
vacuuming because for that
741
0:38:25,68 --> 0:38:29,34
problem you don't need, and this
is actually another job to clean
742
0:38:29,34 --> 0:38:30,54
up those things.
743
0:38:30,92 --> 0:38:34,2
You don't need indexes to be involved
and this slows down the
744
0:38:34,2 --> 0:38:35,88
whole thing if you have many indexes.
745
0:38:35,98 --> 0:38:41,68
So anyway, I wonder, I need to
look at that, but, and when you
746
0:38:41,68 --> 0:38:45,66
do manual vacuuming it's unthrottled,
as I said, because
747
0:38:45,66 --> 0:38:46,98
vacuum_cost_delay is 0.
748
0:38:47,12 --> 0:38:48,48
So it's not checking at all.
749
0:38:48,48 --> 0:38:49,22
Let's go.
750
0:38:49,74 --> 0:38:52,48
Michael: But I think that's, isn't
that because every now and
751
0:38:52,48 --> 0:38:56,26
again, you want to run a manual
vacuum as like an emergency procedure?
752
0:38:56,42 --> 0:38:56,92
Like,
753
0:38:57,16 --> 0:38:58,24
Nikolay: yeah, it makes sense.
754
0:38:58,24 --> 0:38:58,86
I agree.
755
0:38:58,94 --> 0:39:3,58
But if it's throttled and it's
unthrottled, Actually, this is
756
0:39:3,58 --> 0:39:4,64
super interesting for me.
757
0:39:4,64 --> 0:39:7,74
In the past, I had problems with
unthrottled vacuum, but it was
758
0:39:7,74 --> 0:39:13,66
when we had some enterprise disks
and self-hosted Postgres and
759
0:39:13,66 --> 0:39:16,76
our capacity was like 400 megabytes
per second.
760
0:39:17,02 --> 0:39:22,42
I also am very curious right now
in Postgres 18 with AIO and
761
0:39:22,42 --> 0:39:26,12
so on, like how a single worker
might behave.
762
0:39:26,12 --> 0:39:29,54
Remember I told you I was super
impressed to see the pg_basebackup,
763
0:39:29,54 --> 0:39:33,04
which is single threaded
and I expected 100 megabytes
764
0:39:33,04 --> 0:39:34,78
of reads from it.
765
0:39:34,94 --> 0:39:37,96
Suddenly it amazed me, approaching
like gigabyte per second of
766
0:39:37,96 --> 0:39:39,78
reads in Postgres 18.
767
0:39:40,44 --> 0:39:44,68
So maybe a vacuum also, I'm not
sure, like this I haven't visited.
768
0:39:44,68 --> 0:39:45,36
So- Yeah,
769
0:39:45,36 --> 0:39:48,54
Michael: I think it was me that
suggested it might be AIO related.
770
0:39:49,22 --> 0:39:51,88
Nikolay: Yeah, but let me correct
myself.
771
0:39:51,88 --> 0:39:54,36
So there is fourth piece memory,
super important.
772
0:39:54,8 --> 0:39:58,0
And if we don't think about it,
it might bite badly, especially
773
0:39:58,08 --> 0:39:59,16
if we raise workers.
774
0:39:59,16 --> 0:40:2,4
So all our clients, we say, okay,
we raised workers, but we're
775
0:40:2,4 --> 0:40:7,76
jumping from say Postgres 15 to
17, you must limit memory for
776
0:40:7,76 --> 0:40:11,76
autovacuum in advance because
it's by default minus 1 means
777
0:40:11,76 --> 0:40:14,8
it takes the value from maintenance_work_mem.
778
0:40:14,8 --> 0:40:19,24
And maintenance_work_mem people
usually raise quite quickly thinking
779
0:40:19,24 --> 0:40:21,94
they will have much faster index
creation.
780
0:40:21,94 --> 0:40:23,94
So they put 2 gigabytes or so.
781
0:40:24,06 --> 0:40:28,94
Now I think like 25 workers, 2
gigabytes is already a lot, right?
782
0:40:28,98 --> 0:40:32,48
And the problem is like before
Postgres 17, you might not notice
783
0:40:32,48 --> 0:40:37,36
it because autovacuum workers
suddenly limit themselves with
784
0:40:37,36 --> 0:40:41,68
1 gigabyte and then suddenly jump
to no obvious limit anymore.
785
0:40:41,82 --> 0:40:44,96
No 1 gigabyte limit anymore for
autovacuum workers.
786
0:40:44,96 --> 0:40:49,04
And If you have 4 gigabytes, I
saw 8 gigabytes, like these things,
787
0:40:49,04 --> 0:40:49,54
right?
788
0:40:49,54 --> 0:40:52,16
And many workers, it's huge memory
consumption.
789
0:40:52,92 --> 0:40:56,12
Michael: Or risk, like not necessarily,
but there's the risk
790
0:40:56,12 --> 0:40:57,8
that they could take up that much,
right?
791
0:40:57,8 --> 0:40:59,54
It's not pre-allocated or anything.
792
0:40:59,54 --> 0:41:1,66
It's just that's the budget they
have.
793
0:41:1,66 --> 0:41:5,64
Nikolay: It can influence and it
can increase risks of out of
794
0:41:5,64 --> 0:41:6,14
memory.
795
0:41:6,4 --> 0:41:6,5
—
796
0:41:6,5 --> 0:41:7,36
Michael: Yeah, yeah, yeah.
797
0:41:7,36 --> 0:41:8,04
— OOM killer.
798
0:41:8,68 --> 0:41:8,8
Nikolay: —
799
0:41:8,8 --> 0:41:12,6
Michael: So, but then you can set,
yeah, great.
800
0:41:12,66 --> 0:41:15,78
But then you can set the autovacuum_work_mem.
801
0:41:16,08 --> 0:41:17,74
I've forgotten the exact name of
it.
802
0:41:17,74 --> 0:41:20,58
Nikolay: — Yeah, I found like half
a gigabyte, some math should
803
0:41:20,58 --> 0:41:24,86
be done there, and we usually like,
we have it, like some formulas.
804
0:41:25,26 --> 0:41:30,06
So usually half a gigabyte, even
maybe lower, and it will be
805
0:41:30,06 --> 0:41:31,42
okay, right?
806
0:41:31,46 --> 0:41:34,54
It's interesting topic, but yeah,
so usually for maintenance
807
0:41:34,54 --> 0:41:39,32
work, again, I wish like this minus
1 is killing me, like decayed
808
0:41:39,32 --> 0:41:39,72
already.
809
0:41:39,72 --> 0:41:45,14
Like why we don't put explicit
value right away?
810
0:41:45,42 --> 0:41:49,24
Why this like I need to go in some
maze and remember.
811
0:41:49,94 --> 0:41:55,68
It took me many years to settle
in terms of these, like, relationship
812
0:41:55,8 --> 0:41:58,16
between vacuum and autovacuum
settings.
813
0:41:58,98 --> 0:42:2,64
And for non-expert who is not working
with Postgres settings
814
0:42:2,64 --> 0:42:5,28
every day, it's impossible to memorize.
815
0:42:5,74 --> 0:42:6,24
Right?
816
0:42:6,46 --> 0:42:7,12
It's super tricky.
817
0:42:7,12 --> 0:42:9,66
Michael: So you would have hard-coded
values for each even if
818
0:42:9,66 --> 0:42:10,92
they start with the same value?
819
0:42:10,92 --> 0:42:11,78
Nikolay: Doesn't hurt.
820
0:42:12,04 --> 0:42:15,02
Yeah, so if we have maintenance_work_mem by default, I don't know,
821
0:42:15,02 --> 0:42:18,7
what is it, like 128 megabytes
or so, like maybe more.
822
0:42:18,94 --> 0:42:19,84
Just copy paste.
823
0:42:19,84 --> 0:42:23,18
This is not the place where we
should save on copy pasting.
824
0:42:23,6 --> 0:42:26,42
We shouldn't save like few bytes.
825
0:42:26,98 --> 0:42:28,82
Minus 1 is 2 bytes, right?
826
0:42:29,06 --> 0:42:30,92
128, it's okay, a few bytes more.
827
0:42:30,92 --> 0:42:34,4
This is not the place where we
should save it, right?
828
0:42:34,4 --> 0:42:40,2
This is this complexity, extra
complexity, which is like, okay,
829
0:42:40,2 --> 0:42:43,48
I need to redirect this frustration
to proper place.
830
0:42:44,06 --> 0:42:47,32
Michael: Yeah, by the way it's
64 megabytes default
831
0:42:47,32 --> 0:42:47,78
maintenance_work_mem.
832
0:42:47,78 --> 0:42:48,5498
I didn't realize it was
833
0:42:48,5498 --> 0:42:48,68
Nikolay: that low.
834
0:42:48,68 --> 0:42:50,24
Postgres, yeah, Postgres.
835
0:42:50,28 --> 0:42:50,78
Yeah.
836
0:42:51,38 --> 0:42:52,58
Michael: All right, awesome.
837
0:42:52,66 --> 0:42:55,94
And actually, the last thing I
wanted to say, so as a little
838
0:42:56,32 --> 0:43:2,44
summary, if people have less than
8 vCPUs, maybe leave, you can
839
0:43:2,44 --> 0:43:6,02
probably leave the workers in place,
but still change the thresholds
840
0:43:6,02 --> 0:43:8,94
and it's just those 3 thresholds
will get you like 90% of the
841
0:43:8,94 --> 0:43:9,82
way there probably.
842
0:43:10,64 --> 0:43:11,82
I think most of...
843
0:43:13,28 --> 0:43:16,4
Reduce, you said down to 1% I think
that makes a lot of sense.
844
0:43:16,4 --> 0:43:19,94
I've generally advised people to
like 5 or 2% as like a starting
845
0:43:19,94 --> 0:43:22,12
point but 1% makes a lot of sense.
846
0:43:22,12 --> 0:43:25,24
It's a bit more, but I think it
847
0:43:25,24 --> 0:43:28,06
Nikolay: won't save you from large
tables It won't save you from
848
0:43:28,06 --> 0:43:33,62
this problem of local degradation
for particular rows It's just
849
0:43:33,62 --> 0:43:37,3
like maybe you need to think about
it additionally, but overall
850
0:43:37,3 --> 0:43:40,44
it's like good, very rough tuning
for
851
0:43:40,44 --> 0:43:40,52
Michael: all the teams.
852
0:43:40,52 --> 0:43:41,26
Yeah, absolutely.
853
0:43:41,28 --> 0:43:44,02
I think that'll get a lot of people
a lot further.
854
0:43:44,28 --> 0:43:46,32
Most providers let you set that
globally.
855
0:43:46,32 --> 0:43:49,84
I did come across 1 recently that
only lets you change these
856
0:43:49,84 --> 0:43:54,52
things at a table level, at which
point my advice would be focus
857
0:43:54,52 --> 0:43:57,18
on your important tables and just
change a few of those.
858
0:43:57,18 --> 0:43:58,82
But that was only 1 provider.
859
0:43:59,64 --> 0:44:0,62
Nikolay: Or just migrate.
860
0:44:1,22 --> 0:44:2,54
Michael: Or migrate, yeah.
861
0:44:3,82 --> 0:44:5,92
That small task of migrating database.
862
0:44:6,56 --> 0:44:8,6
But yeah, so that sounds wise.
863
0:44:8,6 --> 0:44:13,98
And then, yeah, memory tuning,
make sure it's not using
864
0:44:13,98 --> 0:44:15,62
maintenance_work_mem if you've upped that.
865
0:44:15,62 --> 0:44:16,02
Smart advice.
866
0:44:16,02 --> 0:44:18,34
Nikolay: Yeah, there are other
parameters, but it's like already
867
0:44:18,34 --> 0:44:19,52
deeper things.
868
0:44:20,42 --> 0:44:21,8
Michael: Yeah, sounds good.
869
0:44:22,8 --> 0:44:28,34
Nikolay: My simple rough tuning
list, raise number of workers.
870
0:44:29,06 --> 0:44:33,22
This requires restart, unfortunately,
then make visits more frequent,
871
0:44:33,26 --> 0:44:38,04
decreasing scale factors to 1%,
for example, roughly, and give
872
0:44:38,04 --> 0:44:42,56
more power, unless it's already
done by provider, raising, for
873
0:44:42,56 --> 0:44:44,12
example, raising cost_limit.
874
0:44:44,14 --> 0:44:46,2
Oh yeah, cost_limit, right?
875
0:44:46,4 --> 0:44:49,74
And default settings, as I said,
Postgres default settings, because
876
0:44:49,74 --> 0:44:51,14
not providers default settings.
877
0:44:51,14 --> 0:44:55,26
So it's roughly 80 MB/s for disk reads.
878
0:44:55,68 --> 0:44:58,94
Think how much you want, like maybe
just raise it, maybe sometimes
879
0:44:58,94 --> 0:45:2,14
4 or 5 times, depending on disk
capacity.
880
0:45:2,66 --> 0:45:4,46
It's very important to understand
that.
881
0:45:5,46 --> 0:45:9,96
And finally, autovacuum_work_mem,
set it explicitly, minus 1 sucks in all
882
0:45:9,96 --> 0:45:10,46
senses.
883
0:45:10,64 --> 0:45:12,6
It's just very hard to deal with.
884
0:45:13,66 --> 0:45:14,02
I like
885
0:45:14,02 --> 0:45:14,34
Michael: that.
886
0:45:14,34 --> 0:45:17,2
I like setting it explicitly, even
if you plan to keep it the
887
0:45:17,2 --> 0:45:18,6
same as your maintenance_work_mem
now.
888
0:45:18,6 --> 0:45:22,32
Nikolay: Yes, like freeze it before
upgrading to 17 for example.
889
0:45:22,44 --> 0:45:25,22
Or before touching number of autovacuum
workers.
890
0:45:26,2 --> 0:45:30,06
Just make it explicit so to simplify
math analysis including
891
0:45:30,06 --> 0:45:34,34
with AI so it won't jump additional
like mind hop.
892
0:45:34,9 --> 0:45:37,74
Michael: And just avoiding that
future change where somebody
893
0:45:37,74 --> 0:45:40,2
wants to increase maintenance_work_mem
and doesn't think
894
0:45:40,2 --> 0:45:40,32
Nikolay: at
895
0:45:40,32 --> 0:45:42,88
Michael: that moment about
autovacuuming.
896
0:45:43,18 --> 0:45:44,94
Nikolay: Because these are 2 separate
things.
897
0:45:45,06 --> 0:45:47,22
They operational, they are very
separate.
898
0:45:47,54 --> 0:45:50,42
Indexing and vacuuming, autovacuuming.
899
0:45:50,74 --> 0:45:51,98
Yeah, and that's it.
900
0:45:51,98 --> 0:45:54,56
These 4 areas for rough tuning,
it's enough.
901
0:45:55,64 --> 0:46:0,4
It should become bloat situation
much better, but there are also
902
0:46:0,4 --> 0:46:0,9
blockers.
903
0:46:0,92 --> 0:46:5,28
If You can tune a lot, tune everything
perfectly, but if you
904
0:46:5,28 --> 0:46:10,94
have some xmin horizon blocker,
and we have episode about xmin horizon,
905
0:46:11,74 --> 0:46:13,02
then it won't help.
906
0:46:13,48 --> 0:46:15,04
Bloat will accumulate anyway.
907
0:46:15,56 --> 0:46:16,06
Michael: Yeah.
908
0:46:17,38 --> 0:46:17,88
Great.
909
0:46:18,18 --> 0:46:18,74
All right.
910
0:46:18,74 --> 0:46:19,24
Nikolay: Good.
911
0:46:19,4 --> 0:46:19,9
Yeah.
912
0:46:20,66 --> 0:46:21,34
Michael: Nice one, Nik.
913
0:46:21,34 --> 0:46:22,32
Thanks so much.
914
0:46:22,76 --> 0:46:24,06
Nikolay: Yeah, I hope it was helpful.
915
0:46:24,06 --> 0:46:25,12
See you next time.
916
0:46:25,3 --> 0:46:26,04
Michael: See you next time.
0:0:4,96 --> 0:0:7,8999996
Nikolay: Everyone who is running
Postgres has autovacuum, and
2
0:0:7,8999996 --> 0:0:12,0199995
most of people heard about autovacuum
and vacuuming and bloat
3
0:0:12,04 --> 0:0:13,48
and this garbage collection.
4
0:0:14,28 --> 0:0:22,08
But a lot of databases grow with
problems being unnoticed and
5
0:0:22,08 --> 0:0:25,08
they start tuning autovacuum
too late.
6
0:0:25,64 --> 0:0:30,04
So this topic today is brought
by you Michael, right?
7
0:0:30,06 --> 0:0:30,72
Hi Michael.
8
0:0:31,24 --> 0:0:31,98
Michael: Hi Nik.
9
0:0:32,84 --> 0:0:36,1
Nikolay: And we definitely had
this topic discussed in the past
10
0:0:36,1 --> 0:0:40,96
in terms of like vacuum and bloat,
but we never discussed the
11
0:0:40,96 --> 0:0:44,54
vacuum itself and how to tune it
properly and what are the best
12
0:0:44,54 --> 0:0:45,04
practices.
13
0:0:46,02 --> 0:0:48,059998
And yeah, I'm glad that you brought
it.
14
0:0:48,059998 --> 0:0:49,22
Let's talk about this.
15
0:0:49,81 --> 0:0:51,14
Michael: Sounds good.
16
0:0:51,14 --> 0:0:51,38
Yeah.
17
0:0:51,38 --> 0:0:54,14
I'm looking forward to hearing
your views on this kind of from
18
0:0:54,14 --> 0:0:57,62
a seeing lots and lots of different
clients perspective because
19
0:0:57,62 --> 0:1:1,82
I get the impression dealing with
people less frequently that
20
0:1:2,68 --> 0:1:6,66
Often it's left really late before
people start tuning or to
21
0:1:6,66 --> 0:1:10,46
vacuum and when I say late a startup
will grow to relatively
22
0:1:10,52 --> 0:1:15,72
significant size before touching
those parameters And I often
23
0:1:15,72 --> 0:1:20,64
think they could have avoided quite
a few headaches and got into
24
0:1:20,76 --> 0:1:26,06
issues slower, if that makes sense,
by just changing a few settings
25
0:1:26,28 --> 0:1:27,1
much earlier.
26
0:1:27,38 --> 0:1:31,2
So yeah, I was keen to get your
thoughts on If you see the same
27
0:1:31,2 --> 0:1:34,9
and also like, when would you advise
people like startup life's
28
0:1:34,9 --> 0:1:37,8
busy, when would you advise people
looking at this kind of thing?
29
0:1:38,04 --> 0:1:38,4
Nikolay: Yeah.
30
0:1:38,4 --> 0:1:43,74
First of all, every single client
which comes to us, we talk
31
0:1:43,74 --> 0:1:47,04
about autovacuum tuning on any
platform.
32
0:1:47,04 --> 0:1:47,7
Doesn't matter.
33
0:1:47,7 --> 0:1:49,4
Self-managed, any managed service.
34
0:1:49,4 --> 0:1:53,4
We always touch this topic and
always like in hundred percent
35
0:1:53,4 --> 0:1:56,26
of cases there is something that
should be done there.
36
0:1:56,78 --> 0:1:59,18
Which means your point is absolutely
right.
37
0:1:59,18 --> 0:2:3,16
It should be done earlier because
when people come to us for
38
0:2:3,16 --> 0:2:7,42
help it's already, they experience
already some problems, some
39
0:2:7,42 --> 0:2:9,7
troubles, right, and this is a
reactive approach.
40
0:2:10,38 --> 0:2:13,22
Michael: And just to clarify, when
you say 100 percent, do you
41
0:2:13,22 --> 0:2:17,84
mean some percentage have done
loads of tuning and still have
42
0:2:17,84 --> 0:2:20,38
issues and some percentage have
done nothing at all.
43
0:2:20,38 --> 0:2:22,26
What's the kind of distribution
like?
44
0:2:22,26 --> 0:2:23,4
Nikolay: It's hard to say.
45
0:2:23,4 --> 0:2:26,48
Actually I checked how many clusters
we observed lately.
46
0:2:26,48 --> 0:2:32,08
It was like 140 or something where
we used thorough like comprehensive
47
0:2:32,08 --> 0:2:35,68
health analysis and tuning and
recommendations and work closely
48
0:2:35,68 --> 0:2:36,48
and so on.
49
0:2:36,68 --> 0:2:43,48
So I'd say 0% have an ideal picture
in terms of how autovacuum
50
0:2:43,48 --> 0:2:44,12
is tuned.
51
0:2:45,04 --> 0:2:49,06
Most customers running on managed
services, especially RDS, have,
52
0:2:49,06 --> 0:2:51,72
let me say it, half-ass tuned
autovacuum.
53
0:2:53,5 --> 0:2:58,52
This is new term we can use here
because this is like, it amazes
54
0:2:58,52 --> 0:2:59,7
me why it's so.
55
0:2:59,7 --> 0:3:1,9
We can dive into details soon.
56
0:3:2,38 --> 0:3:8,36
And only few, like literally that's
a several, I saw they have
57
0:3:8,36 --> 0:3:12,94
very well tuned autovacuum and
we just shift focus to why it's
58
0:3:12,94 --> 0:3:16,4
still not enough and what we should
do with specific pieces of
59
0:3:16,4 --> 0:3:16,9
workload.
60
0:3:17,62 --> 0:3:18,96
Michael: Sure, makes sense.
61
0:3:19,2 --> 0:3:21,6
Nikolay: Local tuning already,
what to do about it.
62
0:3:21,6 --> 0:3:26,08
And in most cases there we also
involve, we focus on specific
63
0:3:26,16 --> 0:3:30,04
workload, but also we go, of course,
beyond just autovacuum
64
0:3:30,04 --> 0:3:34,08
tuning, because usually this is
like some pathological workload
65
0:3:34,12 --> 0:3:38,62
or some, there are some problems
which are not conflicting, how
66
0:3:38,62 --> 0:3:41,94
to say, like they are blocking
autovacuum work, right?
67
0:3:41,98 --> 0:3:42,48
Yes.
68
0:3:42,98 --> 0:3:48,22
Before we dive into details, maybe
let's just explain to wider
69
0:3:48,22 --> 0:3:53,22
audience what autovacuum is, because
I think many still misunderstand
70
0:3:53,3 --> 0:3:53,8
it.
71
0:3:53,94 --> 0:3:59,82
Recently I talked to, you know,
like our focus is fast growing
72
0:3:59,82 --> 0:4:3,38
startups and I talked to technical
founders quite often.
73
0:4:4,28 --> 0:4:6,42
These guys are super smart.
74
0:4:6,42 --> 0:4:9,1
Technically they understand, they
definitely understand throughput,
75
0:4:9,14 --> 0:4:10,76
latency, all the numbers and so
on.
76
0:4:10,76 --> 0:4:15,98
But I see they just didn't have
time to dive into autovacuum,
77
0:4:15,98 --> 0:4:16,64
what it is.
78
0:4:16,64 --> 0:4:20,82
They heard bloat issue, MVCC, Postgres
is very widely criticized,
79
0:4:21,18 --> 0:4:21,6
right?
80
0:4:21,6 --> 0:4:24,72
But what autovacuum is and what to
do about it, what they need
81
0:4:24,72 --> 0:4:28,98
to have, it's like, it's always
a good topic to discuss and dive
82
0:4:28,98 --> 0:4:29,48
into.
83
0:4:29,5 --> 0:4:33,42
So my simple explanation, autovacuum
is just garbage collection,
84
0:4:33,42 --> 0:4:34,3
first of all.
85
0:4:35,66 --> 0:4:40,32
It has a few more jobs, but the
main job, original job, is garbage
86
0:4:40,32 --> 0:4:40,82
collection.
87
0:4:41,18 --> 0:4:48,14
When you have updates, deletes,
or failed inserts, by the way,
88
0:4:48,14 --> 0:4:52,6
the third part is usually forgotten,
but failed inserts, all
89
0:4:52,6 --> 0:4:56,68
of them produce successful updates,
successful deletes, and failed
90
0:4:56,68 --> 0:4:58,34
inserts, rolled back inserts.
91
0:4:58,86 --> 0:5:5,44
They all produce dead row versions
called tuples, right?
92
0:5:6,22 --> 0:5:8,16
Michael: Probably also rolled back
updates.
93
0:5:10,08 --> 0:5:11,36
Nikolay: Oh yes, you're right.
94
0:5:11,48 --> 0:5:11,98
Yeah.
95
0:5:12,44 --> 0:5:19,08
Successful deletes, rolled back
inserts, or any updates.
96
0:5:19,62 --> 0:5:20,12
Yeah.
97
0:5:20,42 --> 0:5:24,86
Besides HOT updates, which are
nuances, right?
98
0:5:25,08 --> 0:5:25,68
Even HOT
99
0:5:25,68 --> 0:5:26,68
Michael: updates, yeah.
100
0:5:26,88 --> 0:5:29,44
Nikolay: If we want to be thorough,
like we are destroying my
101
0:5:29,44 --> 0:5:31,54
intention to provide simple explanation.
102
0:5:31,84 --> 0:5:33,5
Let's keep it short.
103
0:5:33,9 --> 0:5:36,36
So it's first of all garbage collections.
104
0:5:37,9 --> 0:5:41,94
So if, especially for guys who
run Postgres on machines with a
105
0:5:41,94 --> 0:5:48,74
lot of cores, like typical like
Intel machine 96 cores or 48
106
0:5:48,86 --> 0:5:51,72
or like AMD hundreds of cores,
right?
107
0:5:53,16 --> 0:5:55,9
Michael: They- We have very, we
have a very different definition
108
0:5:55,9 --> 0:5:57,54
of what typical is for-
109
0:5:57,7 --> 0:5:59,54
Nikolay: Well, typical big, large
database.
110
0:6:0,08 --> 0:6:0,9
Michael: Sure, sure.
111
0:6:1,06 --> 0:6:4,44
Nikolay: So it's, it amazes me,
like I, I saw, I told you, I
112
0:6:4,44 --> 0:6:9,48
saw Postgres clusters achieving
10, 20 terabytes with default
113
0:6:9,52 --> 0:6:10,58
autovacuum settings.
114
0:6:11,0 --> 0:6:14,32
Somehow surviving, already having
5 replicas.
115
0:6:14,76 --> 0:6:15,3
It's insane.
116
0:6:15,3 --> 0:6:18,48
Michael: This is what I meant in
terms of like, should people
117
0:6:18,66 --> 0:6:20,6
be doing it earlier or is it okay?
118
0:6:20,74 --> 0:6:21,35
There's a certain argument.
119
0:6:21,35 --> 0:6:21,54
Nikolay: It's not
120
0:6:21,54 --> 0:6:22,38
Michael: okay, no.
121
0:6:22,38 --> 0:6:26,7
Yeah, I think I agree, but as you
say, they've somehow got by
122
0:6:26,92 --> 0:6:28,54
even to that large extent.
123
0:6:28,74 --> 0:6:33,42
But I've also seen smaller systems
really struggling because
124
0:6:33,42 --> 0:6:34,84
autovacuum hasn't been tuned.
125
0:6:34,84 --> 0:6:38,12
So far fewer, like maybe not even
a terabyte, but struggling
126
0:6:38,12 --> 0:6:39,58
because of a certain workload.
127
0:6:40,24 --> 0:6:42,94
So yeah, it's not just size, right?
128
0:6:43,26 --> 0:6:47,12
Nikolay: It can be a table of 2
gigabytes in size, but it's mostly
129
0:6:47,12 --> 0:6:48,3
bloated, like 99.9%.
130
0:6:49,14 --> 0:6:52,32
I saw it many times, especially
with queue-like workloads.
131
0:6:52,38 --> 0:6:55,52
And then it can suffer, small database,
but it suffers from the
132
0:6:55,52 --> 0:6:58,7
fact that autovacuum is not tuned
and maybe something is blocking
133
0:6:58,7 --> 0:6:59,2
it.
134
0:6:59,34 --> 0:7:1,4
Garbage collection job is blocking
it.
135
0:7:1,4 --> 0:7:3,74
So we need to combine both things
here.
136
0:7:3,74 --> 0:7:6,86
But my point is, autovacuum is
just garbage collection.
137
0:7:7,48 --> 0:7:11,4
If you tune Postgres, or maybe
your provider tuned, for example,
138
0:7:11,4 --> 0:7:15,9
to have bigger shared_buffers,
bigger cache, right, and a work_mem
139
0:7:16,24 --> 0:7:19,24
for sort and join operations and
so on.
140
0:7:19,24 --> 0:7:22,36
If it's already tuned and max_connections
has increased, maybe
141
0:7:22,36 --> 0:7:25,62
a pooler is in front of it, like
you tuned it to handle workload.
142
0:7:26,72 --> 0:7:31,6
Why the heck garbage collection
remains untuned?
143
0:7:31,72 --> 0:7:34,54
It should be tuned together with
everything else, right?
144
0:7:34,54 --> 0:7:36,18
So it should be.
145
0:7:36,4 --> 0:7:39,2
But we see it's often lagging in
tuning.
146
0:7:40,24 --> 0:7:43,9
And it can be a local workload
on small database already suffering,
147
0:7:43,9 --> 0:7:48,4
or it can be a big cluster and
garbage collection mostly default.
148
0:7:48,76 --> 0:7:50,2
autovacuum is mostly default.
149
0:7:50,34 --> 0:7:53,76
But that being said, we should
mention that there are a few more
150
0:7:53,76 --> 0:7:55,3
jobs that the vacuum has.
151
0:7:55,72 --> 0:7:56,76
Maintenance statistics.
152
0:7:57,74 --> 0:7:58,14
Yeah?
153
0:7:58,14 --> 0:7:58,62
Do you want to
154
0:7:58,62 --> 0:8:0,02
Michael: stick to the vacuum ones
first?
155
0:8:0,02 --> 0:8:3,7
Because I think the name autovacuum
is quite a good name in
156
0:8:3,7 --> 0:8:9,38
that it's all of the jobs that
vacuum does but automated But
157
0:8:9,38 --> 0:8:13,7
with 1 addition, which is there
is also an auto-analyze
158
0:8:13,7 --> 0:8:15,72
feature Right, which is what you're
just about to talk about
159
0:8:15,72 --> 0:8:18,8
in terms of statistics, but I feel
like the other vacuum jobs
160
0:8:18,8 --> 0:8:22,5
are worth—do you think of it like
as garbage collection, statistics,
161
0:8:22,54 --> 0:8:23,95
and then the other vacuum jobs?
162
0:8:23,95 --> 0:8:25,64
Nikolay: — It's just easier to
memorize.
163
0:8:25,84 --> 0:8:29,36
Statistics also should be maintained
up to date.
164
0:8:30,02 --> 0:8:33,22
If it's lagging, it may affect
performance, might affect performance.
165
0:8:33,66 --> 0:8:36,44
But you're right, there are also
a couple of more jobs.
166
0:8:36,46 --> 0:8:37,62
Transaction ID wraparound.
167
0:8:38,22 --> 0:8:43,44
If you have a lot of transactions
per day, we know there are
168
0:8:43,44 --> 0:8:45,92
sometimes some like 1000000000
per day.
169
0:8:45,92 --> 0:8:46,64
It's a lot.
170
0:8:46,64 --> 0:8:50,14
In this case, churn is high and
int4 is not enough.
171
0:8:50,14 --> 0:8:51,94
Half of int4 is not enough.
172
0:8:52,36 --> 0:8:55,38
transaction ID wraparound prevention
should be very frequent
173
0:8:55,38 --> 0:8:58,22
in each tuple, in each row version.
174
0:8:58,98 --> 0:9:2,66
And also there is Another very
important job, especially for
175
0:9:2,66 --> 0:9:6,3
performance, it's maintaining visibility
maps.
176
0:9:7,12 --> 0:9:11,26
It's a bitmap with 2 bits for each
page.
177
0:9:11,28 --> 0:9:13,68
Page is 8 kibibytes, right?
178
0:9:13,68 --> 0:9:18,28
And 2 bits, is the whole page fully
visible, All visible?
179
0:9:18,5 --> 0:9:20,94
Means all tuples are visible to
all transactions.
180
0:9:21,18 --> 0:9:23,64
And second is all frozen.
181
0:9:24,34 --> 0:9:26,0
Yeah, just previous topic.
182
0:9:26,0 --> 0:9:28,54
Transaction ID wraparound prevention.
183
0:9:28,6 --> 0:9:32,54
So not to visit this page again
if we know that all the tuples
184
0:9:32,54 --> 0:9:35,58
are in the past, they're already
marked frozen, so they're definitely
185
0:9:35,58 --> 0:9:40,52
in the past, even if their xmin,
xmax look like they are in the
186
0:9:40,52 --> 0:9:41,02
future.
187
0:9:41,6 --> 0:9:42,46
This is freezing.
188
0:9:42,54 --> 0:9:43,4
It marks like...
189
0:9:44,16 --> 0:9:47,86
All frozen bit means like it's
a whole page in the past.
190
0:9:47,86 --> 0:9:49,78
The next vacuum will just skip
it.
191
0:9:49,92 --> 0:9:51,58
That's optimization as well, right?
192
0:9:51,58 --> 0:9:56,66
So for more frequent vacuuming,
not to do the same job once again,
193
0:9:57,26 --> 0:9:57,76
right?
194
0:9:58,14 --> 0:10:0,72
Michael: I want to come back to
that, but before we do, The all
195
0:10:0,72 --> 0:10:4,26
visible is really important for
index only scan performance,
196
0:10:4,34 --> 0:10:4,84
right?
197
0:10:5,46 --> 0:10:14,1
So if an index only scan can know
that every single tuple on
198
0:10:14,1 --> 0:10:19,18
that page is visible to all transactions
then it can serve the
199
0:10:20,02 --> 0:10:23,3
result it finds in the index because
it knows it can't have changed.
200
0:10:23,42 --> 0:10:27,72
So that's a really neat optimization
without having to do what
201
0:10:27,72 --> 0:10:28,94
it calls a heap fetch.
202
0:10:28,94 --> 0:10:31,56
So it's like fetching the data
from the table instead of from
203
0:10:31,56 --> 0:10:32,2
the index.
204
0:10:32,2 --> 0:10:34,86
So if you ever if you see an index
only scan that ends up with
205
0:10:34,86 --> 0:10:38,92
a lot of heap fetches that's because
Postgres couldn't...
206
0:10:39,38 --> 0:10:43,14
Yeah it might it might be that
information was in the index but
207
0:10:43,14 --> 0:10:46,8
because it Postgres didn't know
for sure that it hadn't changed
208
0:10:46,8 --> 0:10:48,66
it still went and got it from the
heap.
209
0:10:48,66 --> 0:10:51,04
So it might be the exact same information
that it already had
210
0:10:51,04 --> 0:10:53,6
from the index, but there's this
inefficiency if vacuum hasn't
211
0:10:53,6 --> 0:10:54,76
run recently enough.
212
0:10:54,76 --> 0:10:58,62
And it only takes, because it's
that bit 0 or 1, it only takes
213
0:10:58,62 --> 0:11:2,88
1 tuple on the page to have changed
for any of the tuples on
214
0:11:2,88 --> 0:11:6,36
that page to lose out on index
only scans.
215
0:11:6,58 --> 0:11:9,34
Nikolay: I think if information
is not in the index, you mean
216
0:11:9,34 --> 0:11:12,9
if we select columns which are
not part of index definition,
217
0:11:12,94 --> 0:11:15,62
it will be index scan immediately,
not index only scan.
218
0:11:15,62 --> 0:11:16,52
Michael: Yeah, of course.
219
0:11:16,52 --> 0:11:19,1
Nikolay: And index only scan already
means that information is
220
0:11:19,1 --> 0:11:19,6
present.
221
0:11:19,9 --> 0:11:25,54
Information means values, but what
is never present in indexes
222
0:11:26,32 --> 0:11:27,7
is visibility information.
223
0:11:27,7 --> 0:11:29,16
This xmin, xmax.
224
0:11:29,88 --> 0:11:35,32
So For that we need heap, but if
visibility map bit says for
225
0:11:35,32 --> 0:11:38,0
this page it's all visible, this
can be skipped.
226
0:11:38,24 --> 0:11:42,26
So if the fetch's number goes lower,
ideally it should be 0,
227
0:11:42,26 --> 0:11:45,26
then it's a perfect situation,
it's a true index-only scan.
228
0:11:45,3 --> 0:11:49,4
If it's high, it approaches the
performance of index scan, which
229
0:11:49,4 --> 0:11:51,26
is like always consulting heap.
230
0:11:52,28 --> 0:11:55,52
Yeah, naming should be better here,
but my position on naming,
231
0:11:55,52 --> 0:11:59,78
I'm always like, index scan could
be renamed to something which
232
0:11:59,78 --> 0:12:3,58
would be explicitly mentioning
that heap is always consulted.
233
0:12:4,46 --> 0:12:6,36
Anyway, this is a different topic.
234
0:12:6,7 --> 0:12:11,4
I think we covered quite well what
autovacuum does, and again,
235
0:12:11,4 --> 0:12:13,74
the main job is just garbage collection.
236
0:12:14,06 --> 0:12:19,92
Also, I wanted to mention, autovacuum
is improving a lot from
237
0:12:19,92 --> 0:12:20,94
release to release.
238
0:12:21,42 --> 0:12:23,4
And it's enabled by default, of
course.
239
0:12:24,64 --> 0:12:27,02
It should be disabled only by experts.
240
0:12:27,12 --> 0:12:32,58
For example, PgQ, Skype engineers
decided to disable autovacuum
241
0:12:32,68 --> 0:12:34,44
for queue partitions.
242
0:12:35,32 --> 0:12:38,8
And it's also disabled in PgQue tool,
which is built on top of
243
0:12:38,8 --> 0:12:39,3
PgQ.
244
0:12:39,52 --> 0:12:40,82
Name is awful, right?
245
0:12:43,14 --> 0:12:47,54
So anyway, there autovacuum is
disabled, but normally it should
246
0:12:47,54 --> 0:12:50,0
be never disabled, and it's enabled
by default.
247
0:12:50,28 --> 0:12:52,08
And it's done, drop, and so on.
248
0:12:52,58 --> 0:12:57,26
So it's just a garbage collection
plus additional features and
249
0:12:57,26 --> 0:13:1,92
it's improving from release to
release and Funny fact I recently
250
0:13:2,02 --> 0:13:6,58
purchased some Chinese modern auto
vacuum for home with washing
251
0:13:6,58 --> 0:13:6,98
feature.
252
0:13:6,98 --> 0:13:10,28
It's very similar, like advancement,
like I had a few years ago,
253
0:13:10,28 --> 0:13:13,44
I had a couple of them and they
were now there, like so many
254
0:13:13,44 --> 0:13:15,6
features, so it became much smarter.
255
0:13:15,86 --> 0:13:17,78
And they have multiple functions.
256
0:13:18,28 --> 0:13:20,46
So I enjoy how it works really.
257
0:13:20,92 --> 0:13:22,98
But it requires some tuning as
well.
258
0:13:23,6 --> 0:13:26,08
Michael: Yeah, I was gonna say,
Bruce brought this up in our
259
0:13:26,08 --> 0:13:27,16
episode with him, didn't he?
260
0:13:27,16 --> 0:13:30,82
He said people complain about vacuum
and bloat with Postgres
261
0:13:31,4 --> 0:13:34,12
and MVCC, but he's saying, which
version are you complaining
262
0:13:34,12 --> 0:13:34,44
about?
263
0:13:34,44 --> 0:13:36,68
Because it is continually getting
better.
264
0:13:36,82 --> 0:13:42,9
But I would say that some of the
defaults are still very conservative,
265
0:13:43,3 --> 0:13:47,12
or maybe make sense at smaller
table sizes.
266
0:13:47,46 --> 0:13:51,22
And they do have scale factors
built in, but they make less and
267
0:13:51,22 --> 0:13:54,52
less sense I think as tables get
bigger, some of them.
268
0:13:54,96 --> 0:13:59,34
Nikolay: So my position on defaults,
they are all BS defaults.
269
0:14:1,56 --> 0:14:8,5
They are like for, I call it Postgres,
kitchen kettle Postgres,
270
0:14:8,64 --> 0:14:13,2
which should have, I don't know,
like 1 gigabyte memory and some
271
0:14:13,2 --> 0:14:16,08
Raspberry Pi or something, a smart
pod or something.
272
0:14:16,08 --> 0:14:16,98
This is it.
273
0:14:17,22 --> 0:14:22,04
For them it's okay, but for any
even like small cluster with
274
0:14:22,04 --> 0:14:28,08
8 cores, 16 gig of memory, it's
not enough at all.
275
0:14:28,26 --> 0:14:32,02
And the settings can be split to
3 categories for simplicity.
276
0:14:32,86 --> 0:14:34,78
Number of workers, which requires
restart.
277
0:14:34,78 --> 0:14:37,8
The only thing which requires restarted
number is number of workers,
278
0:14:37,8 --> 0:14:39,18
which is 3 by default.
279
0:14:39,52 --> 0:14:41,96
If you have 8 cores, 3 maybe is
okay.
280
0:14:41,96 --> 0:14:42,68
It's okay.
281
0:14:42,88 --> 0:14:53,46
If you have 32, 64, 48, 96 cores,
3 is not enough, but we see
282
0:14:53,46 --> 0:14:54,44
it all the time.
283
0:14:54,6 --> 0:14:57,54
People come to us, 96 cores, 3
workers.
284
0:14:58,38 --> 0:14:59,44
This is 1 thing.
285
0:14:59,48 --> 0:15:0,92
Michael: You say it's not enough.
286
0:15:1,84 --> 0:15:4,9
I think you're right in the sense
it's not a sensible default.
287
0:15:4,9 --> 0:15:8,14
Like why not give it more in case
it needs it?
288
0:15:8,14 --> 0:15:8,64
Nikolay: Right.
289
0:15:9,14 --> 0:15:12,04
Michael: But as you said, sometimes
people come to you and they've
290
0:15:12,04 --> 0:15:15,92
only had 3 workers the whole time
and somehow it's not fallen
291
0:15:15,92 --> 0:15:16,42
over.
292
0:15:18,72 --> 0:15:21,48
Nikolay: It's grinding through
challenges.
293
0:15:21,53 --> 0:15:22,03
Yeah.
294
0:15:22,08 --> 0:15:26,82
Like super bloated tables, super
bloated indexes, and it's a
295
0:15:26,82 --> 0:15:30,68
lot of dirt to clean, which is
great for us.
296
0:15:30,68 --> 0:15:32,54
We have opportunity to help them.
297
0:15:32,64 --> 0:15:35,86
Instead of framing, oh, how bad
it is, I actually have it, and
298
0:15:35,86 --> 0:15:37,52
it's actually our product strategy.
299
0:15:38,16 --> 0:15:41,52
We frame it, oh, great, we can
help you really quickly, really
300
0:15:41,52 --> 0:15:42,02
quickly.
301
0:15:42,04 --> 0:15:43,94
Either way, we have low-hanging
fruit.
302
0:15:43,94 --> 0:15:44,68
Let's go.
303
0:15:45,06 --> 0:15:47,8
With our tooling and methodologies,
it's super simple.
304
0:15:47,8 --> 0:15:52,36
This low-hanging fruit, let's go,
and your database will fill
305
0:15:52,36 --> 0:15:54,12
and breathe quite soon.
306
0:15:54,28 --> 0:15:55,14
Much better.
307
0:15:55,24 --> 0:15:59,24
You can even consider downgrading
or postponing upgrade for a
308
0:15:59,24 --> 0:16:0,74
couple of years after this.
309
0:16:0,74 --> 0:16:1,24
Yeah.
310
0:16:1,38 --> 0:16:2,42
And this is great.
311
0:16:2,78 --> 0:16:3,94
Yeah, this is 1 thing.
312
0:16:3,94 --> 0:16:6,02
And this is super important thing,
we just discussed.
313
0:16:6,02 --> 0:16:10,92
This is how garbage collection
works and updates, deletes, and
314
0:16:10,92 --> 0:16:11,82
sometimes inserts.
315
0:16:11,82 --> 0:16:13,44
They do just part of the job.
316
0:16:14,28 --> 0:16:14,78
Right?
317
0:16:14,82 --> 0:16:20,98
And these poor autovacuum workers
need to do the rest of the
318
0:16:20,98 --> 0:16:21,48
job.
319
0:16:22,36 --> 0:16:23,6
Michael: The tidying up afterwards,
320
0:16:23,64 --> 0:16:24,14
Nikolay: yeah.
321
0:16:24,24 --> 0:16:28,16
You have 1,000 max_connections,
meaning you have up to 1,000
322
0:16:28,32 --> 0:16:34,22
back-end workers which produce
all those dead tuples.
323
0:16:34,94 --> 0:16:37,54
And only 3 that should catch up
with them.
324
0:16:37,54 --> 0:16:38,56
It's nonsense, right?
325
0:16:38,56 --> 0:16:40,1
It feels like it's nonsense.
326
0:16:40,28 --> 0:16:42,1
So it should be tuned.
327
0:16:42,1 --> 0:16:46,4
And simple rule, like we say, like
actually let's consider like
328
0:16:46,4 --> 0:16:51,94
25% of vCPU count, But we should
do it very properly, thinking
329
0:16:51,94 --> 0:16:54,22
about memory management and so
on.
330
0:16:54,78 --> 0:16:58,78
I know there is opposition to this
view, but this is my position.
331
0:16:58,78 --> 0:17:1,64
It's a simple case, just let's
give more workers, especially
332
0:17:1,64 --> 0:17:2,58
if you have partitioning.
333
0:17:3,68 --> 0:17:10,08
Because, fun fact, a worker processing
a table, if it's a huge
334
0:17:10,08 --> 0:17:13,38
table, it will be processing it
sequentially, your table and
335
0:17:13,38 --> 0:17:14,92
its indexes, and that's it.
336
0:17:14,92 --> 0:17:18,34
If it's a partitioned table, it
can be distributed.
337
0:17:18,4 --> 0:17:21,42
Each partition can be, you can
parallelize this, right?
338
0:17:21,6 --> 0:17:24,98
So it makes sense to have more
workers if you have more partitions.
339
0:17:25,6 --> 0:17:28,62
And it's great to have partitions
and more workers together.
340
0:17:28,62 --> 0:17:29,78
This is the best situation.
341
0:17:30,18 --> 0:17:31,74
And 2 more categories.
342
0:17:32,22 --> 0:17:34,66
1 defines frequency of revisiting.
343
0:17:35,82 --> 0:17:40,46
Frequency, how frequent workers
come to do stuff.
344
0:17:40,84 --> 0:17:45,04
And another defines how fast they
can throughput, basically,
345
0:17:45,04 --> 0:17:46,04
or throttling.
346
0:17:46,38 --> 0:17:47,42
I think
347
0:17:47,42 --> 0:17:49,66
Michael: throttling's the better
way of thinking about it, yeah.
348
0:17:49,66 --> 0:17:50,82
Nikolay: Throttling, yeah, limiting.
349
0:17:51,22 --> 0:17:53,22
It's cost_limit and cost_delay.
350
0:17:53,32 --> 0:17:56,6
And how often they visit defines
by scale factors and threshold,
351
0:17:56,6 --> 0:17:59,84
but I'm okay to think about only
scale factors, actually.
352
0:18:0,52 --> 0:18:2,22
At first glance, it's enough.
353
0:18:2,86 --> 0:18:6,02
So we have 3 scale factors today,
right?
354
0:18:6,02 --> 0:18:10,22
Or maybe there is also in Postgres
18, there is
355
0:18:10,58 --> 0:18:12,22
autovacuum_vacuum_max_threshold.
356
0:18:12,88 --> 0:18:17,22
This is a new stuff in Postgres
18, which changes the picture.
357
0:18:17,82 --> 0:18:23,22
So usually we talked about only
scale factor and threshold.
358
0:18:23,22 --> 0:18:28,68
Scale factor by default, 3 scale
factors, but the basic 1 is
359
0:18:28,78 --> 0:18:31,5
autovacuum_vacuum_scale_factor,
right?
360
0:18:31,98 --> 0:18:34,34
And it is either 10 or 20 percent.
361
0:18:34,54 --> 0:18:37,08
So I think 20 percent, right?
362
0:18:37,36 --> 0:18:40,76
Michael: Yeah, so I suppose because
the threshold by default
363
0:18:40,76 --> 0:18:43,04
is 0.2, right, so 20 percent.
364
0:18:43,04 --> 0:18:45,2
Let's say you've got 1000000000
rows in the table.
365
0:18:45,2 --> 0:18:49,5
It doesn't wait to get to 200 million,
it starts at 100 million.
366
0:18:49,9 --> 0:18:53,04
Nikolay: Yeah, so we don't allow
more than 100 million, which
367
0:18:53,04 --> 0:18:54,04
is a huge number.
368
0:18:54,38 --> 0:18:55,68
Maybe huge, maybe not.
369
0:18:55,68 --> 0:18:57,98
100 million dead tuples in the
table.
370
0:18:58,08 --> 0:18:59,94
Michael: It's quite a lot though,
yeah.
371
0:19:0,2 --> 0:19:4,8
Nikolay: Yeah, so the basic is
the vacuum scale factor.
372
0:19:5,86 --> 0:19:7,06
This is the first thing.
373
0:19:7,06 --> 0:19:10,88
And it's 20% by default, which
means you need to accumulate 20%
374
0:19:11,12 --> 0:19:15,04
of dead tuples in the table before
it starts garbage collection.
375
0:19:15,32 --> 0:19:17,6
When I just say this, I had recent
experiences.
376
0:19:18,42 --> 0:19:21,76
When I said this to some startup
CTO who which is growing and
377
0:19:21,76 --> 0:19:26,5
so on he like, oh We don't have
garbage collection before 20%
378
0:19:26,64 --> 0:19:30,9
of dirt accumulated This is
379
0:19:32,68 --> 0:19:35,2
Michael: Of course when when things
are small, it's not a big
380
0:19:35,2 --> 0:19:35,6
deal.
381
0:19:35,6 --> 0:19:39,16
But when things get big, this is
just a huge number.
382
0:19:39,16 --> 0:19:40,36
And it's not just...
383
0:19:41,04 --> 0:19:41,7
Nikolay: Yeah, it's...
384
0:19:41,94 --> 0:19:46,96
Let's say you have like almost
terabyte size table in terms of
385
0:19:46,96 --> 0:19:52,1
size, billion rows unpartitioned,
which is common, I see this.
386
0:19:53,0 --> 0:19:58,66
20% means 200 million rows, dead
tuples, right?
387
0:19:58,66 --> 0:20:2,54
Which is by the way above that
threshold introduced in Postgres
388
0:20:2,56 --> 0:20:3,06
18.
389
0:20:4,4 --> 0:20:5,26
So, it's like, wow.
390
0:20:5,34 --> 0:20:7,74
Michael: But it's not just storage,
right?
391
0:20:7,74 --> 0:20:12,02
It's also polluting caches and
indexes.
392
0:20:12,34 --> 0:20:13,12
It's everything.
393
0:20:13,12 --> 0:20:14,6
Nikolay: Oh yes, oh yes.
394
0:20:14,6 --> 0:20:15,36
This is big point.
395
0:20:15,36 --> 0:20:18,82
And actually, let me add 1 important
notice here.
396
0:20:19,7 --> 0:20:23,94
Usually, it's not a big deal for
smaller tables.
397
0:20:24,52 --> 0:20:26,9
But in some cases, we see local...
398
0:20:27,98 --> 0:20:31,86
So if, for example, 1 row updated
many times, thousands of times.
399
0:20:32,36 --> 0:20:36,14
For 1 logical row, you have many
versions.
400
0:20:37,9 --> 0:20:44,74
And globally, like table is big,
but for this not lucky row,
401
0:20:45,3 --> 0:20:49,88
You have so many versions and they
can be, might be scattered
402
0:20:49,9 --> 0:20:51,0
among many pages.
403
0:20:51,94 --> 0:20:56,74
So, they are sitting there as data
tuples and for this specific
404
0:20:56,8 --> 0:20:59,18
query select where id equals something.
405
0:21:0,58 --> 0:21:4,16
This means that all of them need
to be fetched to be checked
406
0:21:4,16 --> 0:21:7,54
in terms of visibility for this
transaction and it degrades for
407
0:21:7,54 --> 0:21:10,08
a particular ID, like local degradation.
408
0:21:11,08 --> 0:21:15,88
Lots of queries are fine, but this
unlucky because it had a lot
409
0:21:15,88 --> 0:21:17,82
of updates or something, right?
410
0:21:18,08 --> 0:21:19,92
It became really degraded.
411
0:21:19,92 --> 0:21:21,82
And it's like, what's happening
here?
412
0:21:21,82 --> 0:21:25,92
This is where p99s or something
are good to have because average
413
0:21:25,92 --> 0:21:29,1
will hide it, average latency and
so on.
414
0:21:30,06 --> 0:21:34,4
And this means you should be vacuuming
more frequently, even
415
0:21:34,4 --> 0:21:35,46
on smaller tables.
416
0:21:36,28 --> 0:21:41,82
So this local degradation due to
dead tuple for particular logical
417
0:21:41,82 --> 0:21:44,62
rows, dead tuple count is high.
418
0:21:45,6 --> 0:21:47,78
So it's happening, and it's happening
silently.
419
0:21:47,9 --> 0:21:48,78
That's the problem.
420
0:21:48,92 --> 0:21:52,8
And tooling, which is like lacking
p99s and so on, is not helping
421
0:21:52,8 --> 0:21:53,72
us to understand.
422
0:21:53,8 --> 0:21:58,56
That's why still logging of slow
queries helps, and auto_explain
423
0:21:58,84 --> 0:22:5,28
helps to catch these like edge
cases and start analyzing why
424
0:22:5,28 --> 0:22:6,08
it's happening.
425
0:22:6,22 --> 0:22:9,94
The next day you select the same
row, maybe it's already vacuumed
426
0:22:9,96 --> 0:22:11,46
and degradation has gone.
427
0:22:12,98 --> 0:22:18,96
But in that moment, if you go back
in time and select it, you
428
0:22:18,96 --> 0:22:20,24
see so many buffers.
429
0:22:20,74 --> 0:22:23,68
This particular query, it's very
like it's primary key lookup,
430
0:22:23,68 --> 0:22:25,14
but too many buffers somehow.
431
0:22:25,14 --> 0:22:25,82
That's why.
432
0:22:26,14 --> 0:22:29,8
So it's important to feel it because
it's really like subtle
433
0:22:29,8 --> 0:22:30,14
problem.
434
0:22:30,14 --> 0:22:33,06
It's hard to catch it if you don't
know where to look at.
435
0:22:33,74 --> 0:22:34,24
Yeah.
436
0:22:34,54 --> 0:22:35,38
And you're right.
437
0:22:35,38 --> 0:22:36,36
So scale factors.
438
0:22:36,58 --> 0:22:39,66
And since Postgres 13, there is
also autovacuum_vacuum_insert_scale_factor,
439
0:22:39,66 --> 0:22:42,54
and there is also
scale factor for analyzing.
440
0:22:43,52 --> 0:22:44,9
For insert, it's really great.
441
0:22:44,9 --> 0:22:49,94
I remember Darafei, the guy who,
from Belarus, I think, he introduced
442
0:22:49,94 --> 0:22:50,14
it.
443
0:22:50,14 --> 0:22:52,12
It was so obvious, why didn't we
have it?
444
0:22:52,12 --> 0:22:55,84
We insert a lot with double table
in size, but vacuum doesn't
445
0:22:55,84 --> 0:22:56,34
come.
446
0:22:56,4 --> 0:23:0,04
And we need vacuum not to clean
up the tuples after successful
447
0:23:0,08 --> 0:23:3,66
insert, but to rebuild visibility
maps, first of all.
448
0:23:4,12 --> 0:23:8,46
And yeah, it is great because if
you have select count or something,
449
0:23:8,46 --> 0:23:11,76
you want index-only scan to be
with low heap fetches, as you
450
0:23:11,76 --> 0:23:12,26
mentioned.
451
0:23:12,44 --> 0:23:15,84
So anyway, there are these scale
factors, And it's enough at
452
0:23:15,84 --> 0:23:17,54
first glance to look only at them.
453
0:23:17,72 --> 0:23:21,64
Yes, you can go deeper and think
about thresholds and how additional
454
0:23:21,72 --> 0:23:24,78
tuning, but scale factors is already
enough.
455
0:23:25,34 --> 0:23:30,22
You want them to be really low
in OLTP workloads, just 1%.
456
0:23:31,32 --> 0:23:35,08
Sometimes 2%, sometimes 1%, I see
people choose, but 1% is is
457
0:23:35,08 --> 0:23:35,96
simple rule.
458
0:23:36,66 --> 0:23:40,58
Set it to 1 percent for all scale
factors and benefit.
459
0:23:40,92 --> 0:23:43,9
Michael: And to give people an
idea of how drastic a change that
460
0:23:43,9 --> 0:23:48,3
is, these scale factors are 20
percent for the vacuum threshold,
461
0:23:48,52 --> 0:23:52,04
10 percent for the analyze threshold,
and I think 20% also for
462
0:23:52,04 --> 0:23:53,48
the insert scale factor.
463
0:23:53,48 --> 0:23:53,88
Nikolay: Yes.
464
0:23:53,88 --> 0:23:54,34
So
465
0:23:54,34 --> 0:23:58,74
Michael: dropping from 20 to 1
might feel like a huge change,
466
0:23:58,74 --> 0:24:2,44
it is quite a huge change, But
you're not repeating the same
467
0:24:2,44 --> 0:24:2,98
work, right?
468
0:24:2,98 --> 0:24:5,42
Like it's not, there's a tiny bit
of repetition.
469
0:24:6,2 --> 0:24:10,84
Yeah, it's, this is a slight difference
to analyze, isn't it,
470
0:24:10,84 --> 0:24:14,62
in that if you run vacuum twice
in quick succession on the same
471
0:24:14,62 --> 0:24:17,8
table, It's not doing all of the
same work again.
472
0:24:17,8 --> 0:24:19,12
It's done a lot of the cleanup.
473
0:24:19,12 --> 0:24:20,7
It's like tidying a room.
474
0:24:20,74 --> 0:24:21,4
Nikolay: Some work
475
0:24:21,54 --> 0:24:21,82
Michael: can
476
0:24:21,82 --> 0:24:22,82
Nikolay: be done again.
477
0:24:22,82 --> 0:24:25,92
For example, it's very nuanced
here.
478
0:24:25,92 --> 0:24:26,92
It's super interesting.
479
0:24:26,98 --> 0:24:29,8
Like you mentioned, it's not only
about data storage.
480
0:24:29,8 --> 0:24:32,56
It's polluting memory, WAL.
481
0:24:32,78 --> 0:24:34,84
WAL means replication, WAL backups.
482
0:24:35,5 --> 0:24:36,64
It's polluting everything.
483
0:24:36,76 --> 0:24:40,14
And memory is super, memory is
expensive these days, right?
484
0:24:42,04 --> 0:24:45,1
So we should optimize, not about
data storage, we should think
485
0:24:45,1 --> 0:24:49,46
about how many pages we need to
keep in this working set.
486
0:24:49,74 --> 0:24:55,58
But the ideal situation when you
raise the workers, make a vacuum
487
0:24:55,58 --> 0:24:59,62
to visit us frequently with lowering
scale factors, all of them
488
0:24:59,62 --> 0:25:2,5
to say 1% is very rough rule here.
489
0:25:2,94 --> 0:25:7,08
But also partition quite well,
because in this case some partitions,
490
0:25:7,2 --> 0:25:11,26
especially if it's historic data,
they will be processed with
491
0:25:11,26 --> 0:25:15,52
marked all visible, all frozen,
and very rarely those pages will
492
0:25:15,52 --> 0:25:16,2
be touched.
493
0:25:17,52 --> 0:25:21,24
So vacuuming will be like a breeze,
like skipping, right?
494
0:25:21,34 --> 0:25:27,0
Unlike if it's a huge, messy heap
with terabyte in size or so,
495
0:25:27,34 --> 0:25:30,6
and any page can be touched at
any given time.
496
0:25:31,1 --> 0:25:33,58
It means it will be need to process
again.
497
0:25:34,08 --> 0:25:38,24
Of course it means that if you
have infrequent vacuuming of a
498
0:25:38,24 --> 0:25:43,26
huge table, of course you're doing
work less, because maybe this
499
0:25:43,26 --> 0:25:46,28
page was visited multiple times
before it was vacuumed.
500
0:25:47,02 --> 0:25:51,6
And if you start vacuuming frequently
and between 2 processing
501
0:25:51,7 --> 0:25:56,82
these pages are revisited by some
rates, then it needs to be
502
0:25:56,82 --> 0:25:57,76
vacuumed again.
503
0:25:58,18 --> 0:26:2,96
So it's multiple processing of
the same page versus a single
504
0:26:2,96 --> 0:26:3,34
processing.
505
0:26:3,34 --> 0:26:7,12
So we cannot say it will be, but
it's highly optimized.
506
0:26:7,12 --> 0:26:8,34
Vacuum is highly optimized.
507
0:26:9,02 --> 0:26:12,9
But if you have a huge table, not
partition, maybe it will be
508
0:26:12,9 --> 0:26:17,16
like frequency, high frequency
vacuuming will cost you some extra,
509
0:26:17,16 --> 0:26:18,58
but it's worth it usually.
510
0:26:18,94 --> 0:26:21,38
So there are nuances here and trade-offs,
of course.
511
0:26:21,58 --> 0:26:27,42
But usually in OLTP, we very strongly
recommend to lower down
512
0:26:27,44 --> 0:26:30,26
scale factors so vacuuming happens
more frequently.
513
0:26:30,78 --> 0:26:35,2
And the fact is that if you're
on managed service, I see it's
514
0:26:35,2 --> 0:26:36,0
quite common.
515
0:26:36,66 --> 0:26:37,86
This is a big problem.
516
0:26:38,26 --> 0:26:39,9
RDS included, for example.
517
0:26:40,4 --> 0:26:43,26
They don't care about this somehow
and they keep defaults.
518
0:26:44,5 --> 0:26:48,58
I would like to hear their reasoning
why they don't proactively
519
0:26:48,8 --> 0:26:50,3
tune it for the customers.
520
0:26:51,5 --> 0:26:52,96
And because I
521
0:26:52,96 --> 0:26:54,92
Michael: mean, I mean, I mean,
I'm just makes, because they're
522
0:26:54,92 --> 0:26:55,92
a scale factor, right?
523
0:26:55,92 --> 0:26:57,72
They can make sense at any scale,
right?
524
0:26:57,72 --> 0:27:1,32
Like it, it's fine when you're
small, These are inexpensive things
525
0:27:1,32 --> 0:27:3,94
to run on small tables, and it
works when it's big.
526
0:27:4,12 --> 0:27:7,54
There's no reason not to tune it
from the start for all customers.
527
0:27:7,78 --> 0:27:11,38
You don't have to be careful about
which instance size.
528
0:27:11,38 --> 0:27:14,96
Nikolay: And I don't complain,
because as I said, I enjoy when
529
0:27:14,96 --> 0:27:16,08
I see the problem.
530
0:27:16,08 --> 0:27:20,28
And I'm excited to help and have
low-hanging fruit and see
531
0:27:20,28 --> 0:27:22,54
how health next day is much better.
532
0:27:22,72 --> 0:27:25,96
But of course we need also automated
reindexing, we need the
533
0:27:25,96 --> 0:27:28,38
pg_repack to be used and so on.
534
0:27:28,86 --> 0:27:32,7
By the way, we mentioned that Postgres
19 will have...
535
0:27:33,4 --> 0:27:33,54
Yeah.
536
0:27:33,54 --> 0:27:34,62
Yeah, it will have...
537
0:27:36,28 --> 0:27:37,8
Michael: REPACK and REPACK CONCURRENTLY.
538
0:27:38,68 --> 0:27:39,86
Nikolay: That's awesome.
539
0:27:39,96 --> 0:27:43,84
And we should somehow revisit this
topic, maybe inviting the
540
0:27:43,84 --> 0:27:45,6
guy who made it, right?
541
0:27:45,9 --> 0:27:47,01
Michael: Yeah, I think it was...
542
0:27:47,01 --> 0:27:47,38
Antonín, right?
543
0:27:47,38 --> 0:27:48,48
Yeah, Antonín was...
544
0:27:48,48 --> 0:27:51,92
We had him on, didn't we, to talk
about pg_squeeze, which inspired
545
0:27:52,04 --> 0:27:52,42
the work.
546
0:27:52,42 --> 0:27:56,88
Nikolay: Remember in the very end
of the episode, I learned about
547
0:27:56,88 --> 0:27:59,68
these plans to make VACUUM FULL
concurrently basically, which
548
0:27:59,68 --> 0:28:2,06
is like became REPACK CONCURRENTLY.
549
0:28:2,24 --> 0:28:5,8
I couldn't believe, I had like
doubts, is it like, but here we
550
0:28:5,8 --> 0:28:10,84
go, like this is happening a year
later, it's planned to be released,
551
0:28:10,84 --> 0:28:13,66
I hope it won't be reverted, it's
a super important feature to
552
0:28:13,66 --> 0:28:15,58
have, it's interesting how out
of the box.
553
0:28:15,58 --> 0:28:20,02
Michael: I have to admit when I,
yeah, I saw that REPACK, they
554
0:28:20,02 --> 0:28:24,28
introduced effectively a rename
of VACUUM FULL to REPACK and that
555
0:28:24,28 --> 0:28:26,98
was going to make 19 but it didn't
have a concurrently option
556
0:28:26,98 --> 0:28:29,6
and I was like, oh, that's such
a shame but it makes sense.
557
0:28:29,6 --> 0:28:30,76
Nikolay: Another year of waiting.
558
0:28:31,68 --> 0:28:34,28
Michael: And then about a week
later, REPACK CONCURRENTLY gets
559
0:28:34,28 --> 0:28:35,2
committed as well.
560
0:28:35,2 --> 0:28:36,22
So yeah, that was great.
561
0:28:36,22 --> 0:28:40,32
Nikolay: It's yeah, it was a mood
swing for me as well.
562
0:28:40,32 --> 0:28:41,38
It was like, oh no.
563
0:28:41,38 --> 0:28:43,14
Oh, yeah.
564
0:28:43,14 --> 0:28:45,42
So anyway, back to scale factors.
565
0:28:45,66 --> 0:28:51,54
This is probably 1 of the most
important to lower scale factors
566
0:28:51,54 --> 0:28:55,46
for OLTP workloads and benefit
from more frequent vacuuming
567
0:28:56,6 --> 0:28:58,24
and analyzing as well, right?
568
0:28:58,26 --> 0:29:0,72
Michael: Just a question, is there
any stage that people are
569
0:29:0,72 --> 0:29:2,54
at where you wouldn't recommend
this.
570
0:29:2,64 --> 0:29:5,38
I was thinking when should people
be thinking about these things
571
0:29:5,38 --> 0:29:8,6
but I think those 2 are such simple
or those 3 let's say are
572
0:29:8,6 --> 0:29:11,96
such simple settings to change
you could change them from the
573
0:29:11,96 --> 0:29:14,18
start and never think about it
again like
574
0:29:14,18 --> 0:29:14,8
Nikolay: globally I
575
0:29:14,8 --> 0:29:15,52
Michael: was thinking.
576
0:29:15,72 --> 0:29:20,34
Nikolay: This is complex and this
is complex thing in terms of
577
0:29:20,74 --> 0:29:24,98
we cannot talk about autovacuum
tuning completely without analyzing
578
0:29:25,38 --> 0:29:28,58
what's blocking the work.
579
0:29:28,78 --> 0:29:29,52
Michael: If anything.
580
0:29:30,34 --> 0:29:33,28
Nikolay: Yes and that's why I'm
like we recently developed a
581
0:29:33,28 --> 0:29:37,2
dashboard for xmin horizon analysis
because we we probably need
582
0:29:37,2 --> 0:29:41,98
to revisit it once again in terms
of long transactions versus
583
0:29:42,42 --> 0:29:47,16
pure xmin horizon blocker analysis
and autovacuum throughput
584
0:29:47,16 --> 0:29:50,46
analysis and again like this I
cannot recommend enough Laurenz
585
0:29:50,46 --> 0:29:54,26
Albe recent blog post about how
he monitors autovacuum.
586
0:29:55,68 --> 0:29:58,94
Combining with what, how we monitor
autovacuum, I think it's
587
0:29:58,94 --> 0:30:3,82
much like we leveled up monitoring
of autovacuum blockers basically,
588
0:30:3,82 --> 0:30:4,04
right?
589
0:30:4,04 --> 0:30:8,42
So xmin horizon, there are 5 reasons
why it can be blocked.
590
0:30:9,52 --> 0:30:14,6
And if you keep those problems
unresolved for hours, or sometimes
591
0:30:14,6 --> 0:30:19,08
dozens of hours, tuning autovacuum
to run more frequently, especially
592
0:30:19,08 --> 0:30:23,86
if you reduce also autovacuum_naptime, how
long it sleeps between runs,
593
0:30:24,16 --> 0:30:25,18
and raised workers.
594
0:30:25,84 --> 0:30:28,62
And also, some problems might happen.
595
0:30:28,62 --> 0:30:32,06
For example, it might start consuming
too much resources just
596
0:30:32,06 --> 0:30:33,14
trying to do something.
597
0:30:33,14 --> 0:30:34,48
It cannot do something.
598
0:30:34,7 --> 0:30:38,22
And also, logging can be, you can
have observer effect.
599
0:30:38,8 --> 0:30:41,82
If there is a, like it tries to
do something, it cannot, but
600
0:30:41,82 --> 0:30:43,78
it reports and many workers report.
601
0:30:43,78 --> 0:30:47,92
And if you, at extreme, you have
log_autovacuum_min_duration
602
0:30:48,04 --> 0:30:51,3
set to 0, meaning all attempts
are logged.
603
0:30:51,42 --> 0:30:55,44
In this case, if you have 25 workers,
for example, and they cannot
604
0:30:55,44 --> 0:30:59,7
do, and they autovacuum_naptime 1 second,
it's a storm of logs.
605
0:30:59,72 --> 0:31:1,96
This is 1 problem I can definitely
imagine.
606
0:31:1,96 --> 0:31:3,06
Michael: You mean 1 millisecond?
607
0:31:3,84 --> 0:31:6,6
Nikolay: No, by default autovacuum_naptime
is 30 seconds.
608
0:31:7,2 --> 0:31:9,94
Michael: What am I thinking of
that's 2 milliseconds by default?
609
0:31:10,2 --> 0:31:11,48
Nikolay: Oh, actually I was wrong.
610
0:31:11,48 --> 0:31:14,28
I'm looking at it right now, it's
60, 1 minute.
611
0:31:15,48 --> 0:31:20,58
autovacuum_naptime is by default 1 minute,
which is quite long in my opinion,
612
0:31:20,9 --> 0:31:25,58
so we usually say let's choose
a few seconds, but I admit aggressive
613
0:31:25,68 --> 0:31:30,06
tuning without resolution of xmin horizon
blockers might lead
614
0:31:30,06 --> 0:31:33,66
to storm of logging and resource
utilization as well.
615
0:31:33,7 --> 0:31:37,08
So this is what I can think of
from top of my head.
616
0:31:37,54 --> 0:31:40,76
Michael: Yeah, so sorry, I was
thinking of cost, there's a cost
617
0:31:40,76 --> 0:31:41,26
delay.
618
0:31:41,28 --> 0:31:43,94
Nikolay: Right, this is the last
thing we haven't touched.
619
0:31:43,94 --> 0:31:47,16
So as I said, There are like throughput
in terms of number of
620
0:31:47,16 --> 0:31:50,68
workers, there is frequency, how
often vacuum and analyzing happens,
621
0:31:50,68 --> 0:31:54,22
and also the remaining piece, big
piece is throttling.
622
0:31:54,28 --> 0:31:56,26
You said we should say throttling,
right?
623
0:31:56,26 --> 0:31:57,42
So 2 parameters.
624
0:31:58,48 --> 0:32:0,88
And in Postgres, who is responsible
for naming?
625
0:32:1,64 --> 0:32:8,32
So there is an attempt to save
on some defaults or something.
626
0:32:8,32 --> 0:32:11,42
There is some parameters that have
relationships.
627
0:32:13,66 --> 0:32:14,98
Inheritance, right?
628
0:32:15,04 --> 0:32:17,74
So there are 2 parameters,
cost_delay and cost_limit.
629
0:32:18,2 --> 0:32:21,6
There are vacuum_cost_delay,
vacuum_cost_limit, this pair.
630
0:32:21,88 --> 0:32:25,14
And by default, I think cost_delay
is 0, means it's unthrottled.
631
0:32:25,24 --> 0:32:27,34
If you run vacuum manually, it's
unthrottled.
632
0:32:28,26 --> 0:32:32,6
It tries to go full speed, usually
bounded by I/O, disk.
633
0:32:33,06 --> 0:32:33,56
Right?
634
0:32:34,7 --> 0:32:37,66
And there is also autovacuum_vacuum_cost_delay,
635
0:32:37,66 --> 0:32:40,08
autovacuum_vacuum_cost_limit, 2 parameters.
636
0:32:40,08 --> 0:32:45,2
1 of which I think
autovacuum_vacuum_cost_limit is set to minus
637
0:32:45,2 --> 0:32:50,02
1, which means it inherits from
vacuum_cost_limit, which is set
638
0:32:50,02 --> 0:32:52,7
to 2 milliseconds, right?
639
0:32:52,7 --> 0:32:56,8
It was 200 milliseconds and then
it was, or 20 milliseconds in
640
0:32:56,8 --> 0:32:58,04
the past before Postgres.
641
0:32:59,18 --> 0:33:1,62
Michael: Yeah, the delay is, I've
just looked it up:
642
0:33:1,62 --> 0:33:3,46
autovacuum_vacuum_cost_delay is
643
0:33:3,46 --> 0:33:3,98
Nikolay: 2 milliseconds.
644
0:33:4,14 --> 0:33:6,04
Yeah, I confused everything, I
see.
645
0:33:6,26 --> 0:33:10,84
So autovacuum_vacuum_cost_delay
is 2 milliseconds and it was
646
0:33:10,92 --> 0:33:15,44
before Postgres 12 it was 30, so
it became 2 in Postgres 12 which
647
0:33:15,44 --> 0:33:16,12
is great.
648
0:33:16,62 --> 0:33:20,88
And autovacuum_vacuum_cost_limit
is minus 1 means that it inherits
649
0:33:20,92 --> 0:33:25,3
from vacuum_cost_limit Which is
by default 200
650
0:33:26,54 --> 0:33:30,3
Michael: Which is like an arbitrary
unit of like work right and
651
0:33:30,3 --> 0:33:33,22
there's some various things that
make up, yeah.
652
0:33:33,34 --> 0:33:37,94
Nikolay: Yeah, I your CPU cycles,
there is some math.
653
0:33:38,36 --> 0:33:42,8
What I don't like about acquisition
of EDB, of SecondQuadrant
654
0:33:42,8 --> 0:33:45,64
by EDB, they just killed the blog.
655
0:33:45,78 --> 0:33:47,06
Blog was brilliant.
656
0:33:47,22 --> 0:33:50,78
And they had a great blog post
about some math.
657
0:33:50,8 --> 0:33:54,9
If you think only about the I/O part,
all defaults before Postgres
658
0:33:54,9 --> 0:33:59,2
12 yielded to 8 MB/s of reads.
659
0:34:0,06 --> 0:34:4,78
So with 120 milliseconds, it was
roughly 8 mb of reads.
660
0:34:4,94 --> 0:34:10,32
So bumping 20 milliseconds to 2
milliseconds, I remember it was
661
0:34:10,32 --> 0:34:14,28
first considered to raise cost
limit, but then decided to reduce
662
0:34:14,38 --> 0:34:17,66
frequency of this
throttling, right?
663
0:34:17,66 --> 0:34:20,1
Because it makes things smoother,
right?
664
0:34:21,74 --> 0:34:25,18
So going down from 20 milliseconds
to 2 milliseconds and maintaining
665
0:34:25,38 --> 0:34:29,55
the cost_limit 200, inherited from
vacuum_cost_limit.
666
0:34:29,55 --> 0:34:32,96
I don't like this, just put straightforward
defaults.
667
0:34:32,96 --> 0:34:33,98
It doesn't hurt.
668
0:34:34,12 --> 0:34:39,52
Minus 1 makes life of humans much
harder, much harder, right?
669
0:34:39,52 --> 0:34:44,02
Like it's, okay, anyway, maybe
I should just propose it.
670
0:34:44,02 --> 0:34:44,92
Maybe it wasn't proposed.
671
0:34:44,92 --> 0:34:45,92
Maybe it was proposed.
672
0:34:46,42 --> 0:34:47,02
I don't know.
673
0:34:47,02 --> 0:34:50,74
It's My battle over dozens of,
over decades already.
674
0:34:50,74 --> 0:34:55,52
This is happening decades, this
suffering from memorizing what
675
0:34:55,52 --> 0:34:56,52
minus 1 means.
676
0:34:56,52 --> 0:34:58,22
We forgot actually memory management.
677
0:34:58,52 --> 0:34:59,48
Fourth piece, right?
678
0:34:59,54 --> 0:35:1,26
There is minus 1 there as well.
679
0:35:1,28 --> 0:35:5,2
autovacuum_work_mem is minus 1
by default, which means you need
680
0:35:5,2 --> 0:35:8,16
to go and consult and there is
big interesting trick happened
681
0:35:8,16 --> 0:35:10,22
in Postgres 17, separate story.
682
0:35:10,44 --> 0:35:10,84
So that's
683
0:35:10,84 --> 0:35:12,38
Michael: maintenance_work_mem,
right?
684
0:35:12,84 --> 0:35:14,28
Nikolay: Yeah, maintenance_work_mem.
685
0:35:14,34 --> 0:35:17,28
If we have time, we can talk about
that as well and dive into
686
0:35:17,28 --> 0:35:18,04
it a little bit.
687
0:35:18,04 --> 0:35:22,7
So, minus 1 for
autovacuum_vacuum_cost_limit inherited 200,
688
0:35:23,2 --> 0:35:27,04
this like arbitrary cost, not arbitrary
actually, but some cost
689
0:35:27,04 --> 0:35:28,28
like 2 milliseconds.
690
0:35:28,78 --> 0:35:31,8
Since Postgres 12, meaning in all
current versions, it means by
691
0:35:31,8 --> 0:35:37,8
default that can just take reads
of 80 MB/s,
692
0:35:38,44 --> 0:35:41,92
roughly, which is not enough in
modern systems.
693
0:35:42,26 --> 0:35:46,88
Ah, and it's shared among all workers,
unless you start tuning
694
0:35:46,88 --> 0:35:50,68
a table level, which makes things
much more complex because then
695
0:35:50,68 --> 0:35:53,9
quotas with throttling becomes
local for this table, for this
696
0:35:53,9 --> 0:35:56,54
worker which is processing specific
table.
697
0:35:56,76 --> 0:35:58,26
I prefer not to go there.
698
0:35:58,26 --> 0:36:1,66
We can have a separate episode
for table level analysis.
699
0:36:2,84 --> 0:36:4,36
Tuning, table level tuning.
700
0:36:4,36 --> 0:36:9,62
So big picture is like by default
it has only 80 MB/s
701
0:36:9,62 --> 0:36:15,06
of reads and if you
have powerful, even EBS volume
702
0:36:15,06 --> 0:36:21,34
which I don't know it's a nitro,
old nitro architecture so it
703
0:36:21,34 --> 0:36:25,08
definitely NVMe, like it has
good throughput.
704
0:36:25,96 --> 0:36:27,9
80 is tiny among all workers.
705
0:36:27,9 --> 0:36:30,26
Again, this is garbage collection
for everything.
706
0:36:30,76 --> 0:36:34,68
So it should have several hundred
megabytes per second at least.
707
0:36:34,78 --> 0:36:38,66
But the good thing is, for example,
RDS fixes this, especially
708
0:36:38,72 --> 0:36:42,24
on Aurora we see enormous quota.
709
0:36:42,78 --> 0:36:46,36
Throttling there is quite good
in terms of like it has a lot
710
0:36:46,36 --> 0:36:47,14
of power.
711
0:36:47,72 --> 0:36:53,1
But in many other cases, we see
it needs attention and we need
712
0:36:53,1 --> 0:36:59,22
to give more like, how to say,
work capacity because otherwise
713
0:36:59,22 --> 0:37:1,7
it's too slow And that's not good.
714
0:37:4,3 --> 0:37:6,4
Michael: It never catches up, if
that makes sense.
715
0:37:8,16 --> 0:37:9,36
Nikolay: It's a kind of situation.
716
0:37:9,52 --> 0:37:13,18
You see all the workers you allocated,
they're always busy.
717
0:37:13,18 --> 0:37:16,2
This is number 1, how you can understand
that something is not
718
0:37:16,2 --> 0:37:16,7
okay.
719
0:37:17,02 --> 0:37:20,14
And second, we have a special report,
we have a query, I have
720
0:37:20,14 --> 0:37:23,1
a blog post about that, and we
also have it in our monitoring,
721
0:37:23,72 --> 0:37:27,98
like a queue or line of tables
which sit there and should be
722
0:37:27,98 --> 0:37:30,4
already processed but not processed
yet.
723
0:37:30,4 --> 0:37:34,98
And this, like, basically a wait
line for tables.
724
0:37:35,28 --> 0:37:38,88
And I think Laurenz also has in
his blog post a slightly different
725
0:37:38,88 --> 0:37:39,38
analysis.
726
0:37:40,08 --> 0:37:41,88
But the idea is the same.
727
0:37:41,88 --> 0:37:43,5
How bad is it, the picture?
728
0:37:44,22 --> 0:37:46,24
It should be done already, but
not yet done.
729
0:37:46,24 --> 0:37:49,34
This is how you also feel this
situation happening.
730
0:37:50,98 --> 0:37:54,94
Michael: From the other side of
things, I saw a good post recently
731
0:37:54,94 --> 0:38:1,74
by Jeremy Schneider about the risk
of completely removing throttling.
732
0:38:2,08 --> 0:38:5,72
So he wrote a good post recently
about an issue they encountered
733
0:38:5,92 --> 0:38:6,16
once.
734
0:38:6,16 --> 0:38:7,7
I think they reduced the...
735
0:38:9,24 --> 0:38:10,34
Nikolay: I haven't seen it.
736
0:38:11,76 --> 0:38:13,48
Sometimes people put to Cron.
737
0:38:13,78 --> 0:38:16,58
We haven't touched this specific
cases related to MultiXact
738
0:38:16,92 --> 0:38:20,58
member situation when people have
this approaching and they need
739
0:38:20,58 --> 0:38:21,84
to vacuum separately.
740
0:38:22,34 --> 0:38:25,68
Switching of indexes because index
vacuuming because for that
741
0:38:25,68 --> 0:38:29,34
problem you don't need, and this
is actually another job to clean
742
0:38:29,34 --> 0:38:30,54
up those things.
743
0:38:30,92 --> 0:38:34,2
You don't need indexes to be involved
and this slows down the
744
0:38:34,2 --> 0:38:35,88
whole thing if you have many indexes.
745
0:38:35,98 --> 0:38:41,68
So anyway, I wonder, I need to
look at that, but, and when you
746
0:38:41,68 --> 0:38:45,66
do manual vacuuming it's unthrottled,
as I said, because
747
0:38:45,66 --> 0:38:46,98
vacuum_cost_delay is 0.
748
0:38:47,12 --> 0:38:48,48
So it's not checking at all.
749
0:38:48,48 --> 0:38:49,22
Let's go.
750
0:38:49,74 --> 0:38:52,48
Michael: But I think that's, isn't
that because every now and
751
0:38:52,48 --> 0:38:56,26
again, you want to run a manual
vacuum as like an emergency procedure?
752
0:38:56,42 --> 0:38:56,92
Like,
753
0:38:57,16 --> 0:38:58,24
Nikolay: yeah, it makes sense.
754
0:38:58,24 --> 0:38:58,86
I agree.
755
0:38:58,94 --> 0:39:3,58
But if it's throttled and it's
unthrottled, Actually, this is
756
0:39:3,58 --> 0:39:4,64
super interesting for me.
757
0:39:4,64 --> 0:39:7,74
In the past, I had problems with
unthrottled vacuum, but it was
758
0:39:7,74 --> 0:39:13,66
when we had some enterprise disks
and self-hosted Postgres and
759
0:39:13,66 --> 0:39:16,76
our capacity was like 400 megabytes
per second.
760
0:39:17,02 --> 0:39:22,42
I also am very curious right now
in Postgres 18 with AIO and
761
0:39:22,42 --> 0:39:26,12
so on, like how a single worker
might behave.
762
0:39:26,12 --> 0:39:29,54
Remember I told you I was super
impressed to see the pg_basebackup,
763
0:39:29,54 --> 0:39:33,04
which is single threaded
and I expected 100 megabytes
764
0:39:33,04 --> 0:39:34,78
of reads from it.
765
0:39:34,94 --> 0:39:37,96
Suddenly it amazed me, approaching
like gigabyte per second of
766
0:39:37,96 --> 0:39:39,78
reads in Postgres 18.
767
0:39:40,44 --> 0:39:44,68
So maybe a vacuum also, I'm not
sure, like this I haven't visited.
768
0:39:44,68 --> 0:39:45,36
So- Yeah,
769
0:39:45,36 --> 0:39:48,54
Michael: I think it was me that
suggested it might be AIO related.
770
0:39:49,22 --> 0:39:51,88
Nikolay: Yeah, but let me correct
myself.
771
0:39:51,88 --> 0:39:54,36
So there is fourth piece memory,
super important.
772
0:39:54,8 --> 0:39:58,0
And if we don't think about it,
it might bite badly, especially
773
0:39:58,08 --> 0:39:59,16
if we raise workers.
774
0:39:59,16 --> 0:40:2,4
So all our clients, we say, okay,
we raised workers, but we're
775
0:40:2,4 --> 0:40:7,76
jumping from say Postgres 15 to
17, you must limit memory for
776
0:40:7,76 --> 0:40:11,76
autovacuum in advance because
it's by default minus 1 means
777
0:40:11,76 --> 0:40:14,8
it takes the value from maintenance_work_mem.
778
0:40:14,8 --> 0:40:19,24
And maintenance_work_mem people
usually raise quite quickly thinking
779
0:40:19,24 --> 0:40:21,94
they will have much faster index
creation.
780
0:40:21,94 --> 0:40:23,94
So they put 2 gigabytes or so.
781
0:40:24,06 --> 0:40:28,94
Now I think like 25 workers, 2
gigabytes is already a lot, right?
782
0:40:28,98 --> 0:40:32,48
And the problem is like before
Postgres 17, you might not notice
783
0:40:32,48 --> 0:40:37,36
it because autovacuum workers
suddenly limit themselves with
784
0:40:37,36 --> 0:40:41,68
1 gigabyte and then suddenly jump
to no obvious limit anymore.
785
0:40:41,82 --> 0:40:44,96
No 1 gigabyte limit anymore for
autovacuum workers.
786
0:40:44,96 --> 0:40:49,04
And If you have 4 gigabytes, I
saw 8 gigabytes, like these things,
787
0:40:49,04 --> 0:40:49,54
right?
788
0:40:49,54 --> 0:40:52,16
And many workers, it's huge memory
consumption.
789
0:40:52,92 --> 0:40:56,12
Michael: Or risk, like not necessarily,
but there's the risk
790
0:40:56,12 --> 0:40:57,8
that they could take up that much,
right?
791
0:40:57,8 --> 0:40:59,54
It's not pre-allocated or anything.
792
0:40:59,54 --> 0:41:1,66
It's just that's the budget they
have.
793
0:41:1,66 --> 0:41:5,64
Nikolay: It can influence and it
can increase risks of out of
794
0:41:5,64 --> 0:41:6,14
memory.
795
0:41:6,4 --> 0:41:6,5
—
796
0:41:6,5 --> 0:41:7,36
Michael: Yeah, yeah, yeah.
797
0:41:7,36 --> 0:41:8,04
— OOM killer.
798
0:41:8,68 --> 0:41:8,8
Nikolay: —
799
0:41:8,8 --> 0:41:12,6
Michael: So, but then you can set,
yeah, great.
800
0:41:12,66 --> 0:41:15,78
But then you can set the autovacuum_work_mem.
801
0:41:16,08 --> 0:41:17,74
I've forgotten the exact name of
it.
802
0:41:17,74 --> 0:41:20,58
Nikolay: — Yeah, I found like half
a gigabyte, some math should
803
0:41:20,58 --> 0:41:24,86
be done there, and we usually like,
we have it, like some formulas.
804
0:41:25,26 --> 0:41:30,06
So usually half a gigabyte, even
maybe lower, and it will be
805
0:41:30,06 --> 0:41:31,42
okay, right?
806
0:41:31,46 --> 0:41:34,54
It's interesting topic, but yeah,
so usually for maintenance
807
0:41:34,54 --> 0:41:39,32
work, again, I wish like this minus
1 is killing me, like decayed
808
0:41:39,32 --> 0:41:39,72
already.
809
0:41:39,72 --> 0:41:45,14
Like why we don't put explicit
value right away?
810
0:41:45,42 --> 0:41:49,24
Why this like I need to go in some
maze and remember.
811
0:41:49,94 --> 0:41:55,68
It took me many years to settle
in terms of these, like, relationship
812
0:41:55,8 --> 0:41:58,16
between vacuum and autovacuum
settings.
813
0:41:58,98 --> 0:42:2,64
And for non-expert who is not working
with Postgres settings
814
0:42:2,64 --> 0:42:5,28
every day, it's impossible to memorize.
815
0:42:5,74 --> 0:42:6,24
Right?
816
0:42:6,46 --> 0:42:7,12
It's super tricky.
817
0:42:7,12 --> 0:42:9,66
Michael: So you would have hard-coded
values for each even if
818
0:42:9,66 --> 0:42:10,92
they start with the same value?
819
0:42:10,92 --> 0:42:11,78
Nikolay: Doesn't hurt.
820
0:42:12,04 --> 0:42:15,02
Yeah, so if we have maintenance_work_mem by default, I don't know,
821
0:42:15,02 --> 0:42:18,7
what is it, like 128 megabytes
or so, like maybe more.
822
0:42:18,94 --> 0:42:19,84
Just copy paste.
823
0:42:19,84 --> 0:42:23,18
This is not the place where we
should save on copy pasting.
824
0:42:23,6 --> 0:42:26,42
We shouldn't save like few bytes.
825
0:42:26,98 --> 0:42:28,82
Minus 1 is 2 bytes, right?
826
0:42:29,06 --> 0:42:30,92
128, it's okay, a few bytes more.
827
0:42:30,92 --> 0:42:34,4
This is not the place where we
should save it, right?
828
0:42:34,4 --> 0:42:40,2
This is this complexity, extra
complexity, which is like, okay,
829
0:42:40,2 --> 0:42:43,48
I need to redirect this frustration
to proper place.
830
0:42:44,06 --> 0:42:47,32
Michael: Yeah, by the way it's
64 megabytes default
831
0:42:47,32 --> 0:42:47,78
maintenance_work_mem.
832
0:42:47,78 --> 0:42:48,5498
I didn't realize it was
833
0:42:48,5498 --> 0:42:48,68
Nikolay: that low.
834
0:42:48,68 --> 0:42:50,24
Postgres, yeah, Postgres.
835
0:42:50,28 --> 0:42:50,78
Yeah.
836
0:42:51,38 --> 0:42:52,58
Michael: All right, awesome.
837
0:42:52,66 --> 0:42:55,94
And actually, the last thing I
wanted to say, so as a little
838
0:42:56,32 --> 0:43:2,44
summary, if people have less than
8 vCPUs, maybe leave, you can
839
0:43:2,44 --> 0:43:6,02
probably leave the workers in place,
but still change the thresholds
840
0:43:6,02 --> 0:43:8,94
and it's just those 3 thresholds
will get you like 90% of the
841
0:43:8,94 --> 0:43:9,82
way there probably.
842
0:43:10,64 --> 0:43:11,82
I think most of...
843
0:43:13,28 --> 0:43:16,4
Reduce, you said down to 1% I think
that makes a lot of sense.
844
0:43:16,4 --> 0:43:19,94
I've generally advised people to
like 5 or 2% as like a starting
845
0:43:19,94 --> 0:43:22,12
point but 1% makes a lot of sense.
846
0:43:22,12 --> 0:43:25,24
It's a bit more, but I think it
847
0:43:25,24 --> 0:43:28,06
Nikolay: won't save you from large
tables It won't save you from
848
0:43:28,06 --> 0:43:33,62
this problem of local degradation
for particular rows It's just
849
0:43:33,62 --> 0:43:37,3
like maybe you need to think about
it additionally, but overall
850
0:43:37,3 --> 0:43:40,44
it's like good, very rough tuning
for
851
0:43:40,44 --> 0:43:40,52
Michael: all the teams.
852
0:43:40,52 --> 0:43:41,26
Yeah, absolutely.
853
0:43:41,28 --> 0:43:44,02
I think that'll get a lot of people
a lot further.
854
0:43:44,28 --> 0:43:46,32
Most providers let you set that
globally.
855
0:43:46,32 --> 0:43:49,84
I did come across 1 recently that
only lets you change these
856
0:43:49,84 --> 0:43:54,52
things at a table level, at which
point my advice would be focus
857
0:43:54,52 --> 0:43:57,18
on your important tables and just
change a few of those.
858
0:43:57,18 --> 0:43:58,82
But that was only 1 provider.
859
0:43:59,64 --> 0:44:0,62
Nikolay: Or just migrate.
860
0:44:1,22 --> 0:44:2,54
Michael: Or migrate, yeah.
861
0:44:3,82 --> 0:44:5,92
That small task of migrating database.
862
0:44:6,56 --> 0:44:8,6
But yeah, so that sounds wise.
863
0:44:8,6 --> 0:44:13,98
And then, yeah, memory tuning,
make sure it's not using
864
0:44:13,98 --> 0:44:15,62
maintenance_work_mem if you've upped that.
865
0:44:15,62 --> 0:44:16,02
Smart advice.
866
0:44:16,02 --> 0:44:18,34
Nikolay: Yeah, there are other
parameters, but it's like already
867
0:44:18,34 --> 0:44:19,52
deeper things.
868
0:44:20,42 --> 0:44:21,8
Michael: Yeah, sounds good.
869
0:44:22,8 --> 0:44:28,34
Nikolay: My simple rough tuning
list, raise number of workers.
870
0:44:29,06 --> 0:44:33,22
This requires restart, unfortunately,
then make visits more frequent,
871
0:44:33,26 --> 0:44:38,04
decreasing scale factors to 1%,
for example, roughly, and give
872
0:44:38,04 --> 0:44:42,56
more power, unless it's already
done by provider, raising, for
873
0:44:42,56 --> 0:44:44,12
example, raising cost_limit.
874
0:44:44,14 --> 0:44:46,2
Oh yeah, cost_limit, right?
875
0:44:46,4 --> 0:44:49,74
And default settings, as I said,
Postgres default settings, because
876
0:44:49,74 --> 0:44:51,14
not providers default settings.
877
0:44:51,14 --> 0:44:55,26
So it's roughly 80 MB/s for disk reads.
878
0:44:55,68 --> 0:44:58,94
Think how much you want, like maybe
just raise it, maybe sometimes
879
0:44:58,94 --> 0:45:2,14
4 or 5 times, depending on disk
capacity.
880
0:45:2,66 --> 0:45:4,46
It's very important to understand
that.
881
0:45:5,46 --> 0:45:9,96
And finally, autovacuum_work_mem,
set it explicitly, minus 1 sucks in all
882
0:45:9,96 --> 0:45:10,46
senses.
883
0:45:10,64 --> 0:45:12,6
It's just very hard to deal with.
884
0:45:13,66 --> 0:45:14,02
I like
885
0:45:14,02 --> 0:45:14,34
Michael: that.
886
0:45:14,34 --> 0:45:17,2
I like setting it explicitly, even
if you plan to keep it the
887
0:45:17,2 --> 0:45:18,6
same as your maintenance_work_mem
now.
888
0:45:18,6 --> 0:45:22,32
Nikolay: Yes, like freeze it before
upgrading to 17 for example.
889
0:45:22,44 --> 0:45:25,22
Or before touching number of autovacuum
workers.
890
0:45:26,2 --> 0:45:30,06
Just make it explicit so to simplify
math analysis including
891
0:45:30,06 --> 0:45:34,34
with AI so it won't jump additional
like mind hop.
892
0:45:34,9 --> 0:45:37,74
Michael: And just avoiding that
future change where somebody
893
0:45:37,74 --> 0:45:40,2
wants to increase maintenance_work_mem
and doesn't think
894
0:45:40,2 --> 0:45:40,32
Nikolay: at
895
0:45:40,32 --> 0:45:42,88
Michael: that moment about
autovacuuming.
896
0:45:43,18 --> 0:45:44,94
Nikolay: Because these are 2 separate
things.
897
0:45:45,06 --> 0:45:47,22
They operational, they are very
separate.
898
0:45:47,54 --> 0:45:50,42
Indexing and vacuuming, autovacuuming.
899
0:45:50,74 --> 0:45:51,98
Yeah, and that's it.
900
0:45:51,98 --> 0:45:54,56
These 4 areas for rough tuning,
it's enough.
901
0:45:55,64 --> 0:46:0,4
It should become bloat situation
much better, but there are also
902
0:46:0,4 --> 0:46:0,9
blockers.
903
0:46:0,92 --> 0:46:5,28
If You can tune a lot, tune everything
perfectly, but if you
904
0:46:5,28 --> 0:46:10,94
have some xmin horizon blocker,
and we have episode about xmin horizon,
905
0:46:11,74 --> 0:46:13,02
then it won't help.
906
0:46:13,48 --> 0:46:15,04
Bloat will accumulate anyway.
907
0:46:15,56 --> 0:46:16,06
Michael: Yeah.
908
0:46:17,38 --> 0:46:17,88
Great.
909
0:46:18,18 --> 0:46:18,74
All right.
910
0:46:18,74 --> 0:46:19,24
Nikolay: Good.
911
0:46:19,4 --> 0:46:19,9
Yeah.
912
0:46:20,66 --> 0:46:21,34
Michael: Nice one, Nik.
913
0:46:21,34 --> 0:46:22,32
Thanks so much.
914
0:46:22,76 --> 0:46:24,06
Nikolay: Yeah, I hope it was helpful.
915
0:46:24,06 --> 0:46:25,12
See you next time.
916
0:46:25,3 --> 0:46:26,04
Michael: See you next time.