Обсуждение: how do you manage postgres 9's postgres process's memory

Поиск
Список
Период
Сортировка

how do you manage postgres 9's postgres process's memory

От
Keith Gabryelski
Дата:
I've noticed my postgres processes have been increasing their memory usage.
this seems to happen because my clients applications are using connection pooling and
until one of the clients forces a connection reset the postgres process does not
release its memory.

I'd love to understand how to manage (constrain) postgres process's memory usage.

as further information:
the clients, in question, are doing exactly one insert statement (with rows
that are around 200 bytes each). there are about 100 inserts (across many clients)
happening per second.

the server is a 16GB ram, 4-processor x64 bit centos machine -- memory grows
(in the worse case) 1G every four hours as long as the connections are kept
open -- it can be as little as 1G every 10 hours.

there can be up to (about) 750 connections to the machine -- and even though
the postgres processes seem to have an upper limit of 500mb (although it's
tough to tell)

here is an example of one process's growth over time --

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
postgres 20533  0.0  0.3 647388 52216 ?        Ss   17:54   0:01 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 7 18:28
postgres 20533  0.0  0.4 663532 71028 ?        Ss   17:54   0:01 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 7 18:58
postgres 20533  0.0  0.4 663532 77084 ?        Ss   17:54   0:02 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 7 19:44
postgres 20533  0.0  0.5 663532 89636 ?        Ss   17:55   0:03 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 7 21:14
postgres 20533  0.0  0.6 663532 99728 ?        Ss   17:55   0:04 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 7 21:35
postgres 20533  0.0  0.7 663532 113876 ?       Ss   17:55   0:06 postgres: postgres mydb 10.252.11.16(39174) idle in transaction   --> Feb 7 22:27
postgres 20533  0.0  0.8 663532 129856 ?       Ss   17:55   0:08 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 7 23:12
postgres 20533  0.0  0.8 663532 138704 ?       Ss   17:55   0:09 postgres: postgres mydb 10.252.11.16(39174) idle in transaction   --> Feb 7 23:49
postgres 20533  0.0  0.9 663532 143232 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 01:36
postgres 20533  0.0  0.9 663532 143232 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 03:46
postgres 20533  0.0  0.9 663532 143232 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 04:03
postgres 20533  0.0  0.9 663532 143260 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 04:11
postgres 20533  0.0  0.9 663532 143260 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 04:21
postgres 20533  0.0  0.9 663532 143260 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 04:39
postgres 20533  0.0  0.9 663532 143260 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 04:48
postgres 20533  0.0  0.9 663532 143364 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 10:18
postgres 20533  0.0  0.9 663532 144164 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 11:08
postgres 20533  0.0  0.9 663532 144328 ?       Ss   Feb07   0:10 postgres: postgres mydb 10.252.11.16(39174) idle                  --> Feb 8 11:56

as you can see -- even 100 connections is going to top out this machines memory if memory stopped at this point (it doesn't -- it continues to grow)

how can I control postgres 9's use of memory.  thank you.

listen_addresses = '*'
max_connections = 1000
shared_buffers = 512MB
work_mem = 256MB
maintenance_work_mem = 1024MB
max_stack_depth = 9MB
effective_io_concurrency = 4
synchronous_commit = off
full_page_writes = on
commit_delay = 10
commit_siblings = 2
checkpoint_segments = 128
checkpoint_timeout = 10min
checkpoint_completion_target = 0.9
checkpoint_warning = 30s
max_wal_senders = 0
wal_keep_segments = 128
effective_cache_size = 1024MB
log_destination = 'stderr'
logging_collector = on
log_directory = 'pg_log'
log_filename = 'postgresql-%a.log'
log_truncate_on_rotation = on
log_rotation_age = 1d
log_rotation_size = 0
datestyle = 'iso, mdy'
lc_messages = 'C'
lc_monetary = 'C'
lc_numeric = 'C'
lc_time = 'C'
default_text_search_config = 'pg_catalog.english'

Re: how do you manage postgres 9's postgres process's memory

От
"Kevin Grittner"
Дата:
Keith Gabryelski <keith@fluentmobile.com> wrote:

> here is an example of one process's growth over time --
>
> USER       PID %CPU %MEM    VSZ   RSS
> postgres 20533  0.0  0.3 647388 52216
> [...]
> postgres 20533  0.0  0.9 663532 144328

Let's get the non-problem out of the way first.  RSS includes shared
memory.  Each process will basically be showing how much of the same
256MB shared memory segment it has touched, which will tend to
increase over time without having *anything* to do overall memory
usage.  Ignore this.  It is not a problem.

> the server is a 16GB ram, 4-processor x64 bit centos machine

> there can be up to (about) 750 connections to the machine

> work_mem = 256MB

Now this, on the other hand, is a potential problem.  Each
connection which is running a query might reserve one or more
work_mem allocations.  256MB * 750 = 187.5GB.  You have 16GB.
Now you describe your workload as heavy inserts, so perhaps this
isn't (currently) happening to you, but it's certainly something you
want to watch.

You didn't describe your storage environment, but let's assume that
your effective_io_concurrency is on target.  The benchmarking I've
done of throughput and latency (response time) have shown best
performance at about ((2 * cores) + effective spindle count).  You
have four cores and (apparently) four "effective spindles" (which is
a complex topic in itself).  So, if your environment performs like
mine, you will see your best performance if you funnel those 750
client-side connections down to about 12 database connections, with
requests queued by the pooler when all 12 connections are busy.
With tens of thousands of concurrent clients hitting our web site,
we were able to improve throughput and response time by cutting our
connection pool from 60 connections to 30.  (Of course, this is on a
much larger system than you describe.)

General comments on your config:

> max_connections = 1000

Far too high; you need to use your connection pooler better, or use
a better connection pooler.

> shared_buffers = 512MB

Not insane, but possibly a little on the low side.

> maintenance_work_mem = 1024MB

OK

> max_stack_depth = 9MB

I've never adjusted this.  I'm a bit curious why you did.

> synchronous_commit = off

So you're OK with not necessarily having all transactions which were
successfully committed represented in the database if there is a
crash?  (That's not rhetorical -- for some applications that's OK;
others, not so much.)

> commit_delay = 10
> commit_siblings = 2

Have you confirmed, through testing with your real workload, that
these settings are helping?  (I can see where they might, but
sometimes people adjust these without testing and actually make
things worse.)

> effective_cache_size = 1024MB

On a 16GB machine, that's probably too low to get the best plans on
some complex queries.  I'd probably be using something in the
neighborhood of 14GB.  For the insert load it won't make any
difference; but when it comes to querying all that data, it might.

One setting you didn't override which almost certainly would help
your insert performance is wal_buffers.  Try setting that to 16MB.

-Kevin

Re: how do you manage postgres 9's postgres process's memory

От
Keith Gabryelski
Дата:


On Sun, Feb 13, 2011 at 9:57 AM, Kevin Grittner <Kevin.Grittner@wicourts.gov> wrote:
Keith Gabryelski <keith@fluentmobile.com> wrote:

> here is an example of one process's growth over time --
>
> USER       PID %CPU %MEM    VSZ   RSS
> postgres 20533  0.0  0.3 647388 52216
> [...]
> postgres 20533  0.0  0.9 663532 144328

Let's get the non-problem out of the way first.  RSS includes shared
memory.  Each process will basically be showing how much of the same
256MB shared memory segment it has touched, which will tend to
increase over time without having *anything* to do overall memory
usage.  Ignore this.  It is not a problem.


Yes, RSS includes shared memory -- the numbers I show you might
not be exactly related to total memory used but we can see from
historical graphs of used memory and from the machine crash
when used memory reached 16GB that this is certainly a problem.

please correct me further if I'm missing something -- but I can see
the postgres processes growing and the used memory growing
until I reset the connection by hand.
 
Is there anyway I can control the postgres's process's use of memory.

> the server is a 16GB ram, 4-processor x64 bit centos machine

> there can be up to (about) 750 connections to the machine

> work_mem = 256MB

Now this, on the other hand, is a potential problem.  Each
connection which is running a query might reserve one or more
work_mem allocations.  256MB * 750 = 187.5GB.  You have 16GB.
Now you describe your workload as heavy inserts, so perhaps this
isn't (currently) happening to you, but it's certainly something you
want to watch.

there are a small number of clients that connect and do interesting
queries -- they do not amount to a potential problem.  I'm not
worried about work_mem for the insert clients (which seem to be
the problem) because work_mem is not considered during these
simple inserts.
 

You didn't describe your storage environment, but let's assume that
your effective_io_concurrency is on target.  The benchmarking I've
done of throughput and latency (response time) have shown best
performance at about ((2 * cores) + effective spindle count).  You
have four cores and (apparently) four "effective spindles" (which is
a complex topic in itself).  So, if your environment performs like
mine, you will see your best performance if you funnel those 750
client-side connections down to about 12 database connections, with
requests queued by the pooler when all 12 connections are busy.
With tens of thousands of concurrent clients hitting our web site,
we were able to improve throughput and response time by cutting our
connection pool from 60 connections to 30.  (Of course, this is on a
much larger system than you describe.)

interesting.  can you point me to something that will help me understand
this performance and how I can apply it to my situation?
 
General comments on your config:

> max_connections = 1000

Far too high; you need to use your connection pooler better, or use
a better connection pooler. 

> shared_buffers = 512MB

Not insane, but possibly a little on the low side.

probably -- but it's difficult to understand what this number actually does
for my system and its influence on postgres.
 

> maintenance_work_mem = 1024MB

OK

> max_stack_depth = 9MB

I've never adjusted this.  I'm a bit curious why you did.


followed the instructions: the value of ulimit -s minus 1MB. it probably doesn't matter.
 
> synchronous_commit = off

So you're OK with not necessarily having all transactions which were
successfully committed represented in the database if there is a
crash?  (That's not rhetorical -- for some applications that's OK;
others, not so much.)


yes.  i'm ok with this.
 
> commit_delay = 10
> commit_siblings = 2

Have you confirmed, through testing with your real workload, that
these settings are helping?  (I can see where they might, but
sometimes people adjust these without testing and actually make
things worse.)

yes. i've tested this.
 
> effective_cache_size = 1024MB

On a 16GB machine, that's probably too low to get the best plans on
some complex queries.  I'd probably be using something in the
neighborhood of 14GB.  For the insert load it won't make any
difference; but when it comes to querying all that data, it might.

i'll consider this.  thank you.
 
One setting you didn't override which almost certainly would help
your insert performance is wal_buffers.  Try setting that to 16MB.

good point, thank you. 
-Kevin

if I understand your position, though -- it is: reduce the number of concurrent
connections to increase the overal throughput of inserts on the table (because
they'll be less collisions on table locks??).  this reduction in connections
will reduce the maximum total memory used by them (but, still that is
just avoiding the inevitable, right -- if postgres processes can grow
larger than total memory, i'll still have a problem with 30 postgres processes
as I do with 750 postgres processes).

thank you for your response, any pointers for me to educate myself on these
things is greatly appreciated (a book?, google fu, web links?)

Pax, Keith

Re: how do you manage postgres 9's postgres process's memory

От
"Benjamin Krajmalnik"
Дата:

Keith,

there are 2 excellent books.  I purchased them a few weeks ago as I was about to migrate all of my infrastructure to new hardware, and they have been invaluable.  Simon, Hannu, and Greg did an awesome job.

I ordered some massive servers, and in the course of benchmarking them following their instructions it exposed apparent hardware issues – so the 2 massive servers as well as one of the smaller ones got shipped back to the supplier for them to check it out.  Had I assumed the servers were performing as the specs on paper indicated, I would have been in serious trouble a few months down the line as we would have reached limitations we were not aware of.  Needless to say, I am still anxious to get the working hardware, since it has put a huge monkey wrench in  our plans, but the info in the books (especially the performance tuning one) saved my behind in ways I could not have imagined.  Not only that, going through that exercise of benchmarking allowed me to extend some of the lessons learned to our current production servers, so we are running much smoother now until we finally migrate over.

 

Every person lurking in these lists would do themselves a huge service getting these books.

 

http://www.2ndquadrant.com/books/

 

 

From: pgsql-admin-owner@postgresql.org [mailto:pgsql-admin-owner@postgresql.org] On Behalf Of Keith Gabryelski
Sent: Sunday, February 13, 2011 10:15 AM
To: Kevin Grittner
Cc: pgsql-admin@postgresql.org
Subject: Re: [ADMIN] how do you manage postgres 9's postgres process's memory

 

 

On Sun, Feb 13, 2011 at 9:57 AM, Kevin Grittner <Kevin.Grittner@wicourts.gov> wrote:

Keith Gabryelski <keith@fluentmobile.com> wrote:

> here is an example of one process's growth over time --
>
> USER       PID %CPU %MEM    VSZ   RSS

> postgres 20533  0.0  0.3 647388 52216

> [...]

> postgres 20533  0.0  0.9 663532 144328

Let's get the non-problem out of the way first.  RSS includes shared
memory.  Each process will basically be showing how much of the same
256MB shared memory segment it has touched, which will tend to
increase over time without having *anything* to do overall memory
usage.  Ignore this.  It is not a problem.

 

 

Yes, RSS includes shared memory -- the numbers I show you might

not be exactly related to total memory used but we can see from

historical graphs of used memory and from the machine crash

when used memory reached 16GB that this is certainly a problem.

 

please correct me further if I'm missing something -- but I can see

the postgres processes growing and the used memory growing

until I reset the connection by hand.

 

Is there anyway I can control the postgres's process's use of memory.

 

> the server is a 16GB ram, 4-processor x64 bit centos machine

> there can be up to (about) 750 connections to the machine

> work_mem = 256MB

Now this, on the other hand, is a potential problem.  Each
connection which is running a query might reserve one or more
work_mem allocations.  256MB * 750 = 187.5GB.  You have 16GB.
Now you describe your workload as heavy inserts, so perhaps this
isn't (currently) happening to you, but it's certainly something you
want to watch.

 

there are a small number of clients that connect and do interesting

queries -- they do not amount to a potential problem.  I'm not

worried about work_mem for the insert clients (which seem to be

the problem) because work_mem is not considered during these

simple inserts.

 


You didn't describe your storage environment, but let's assume that
your effective_io_concurrency is on target.  The benchmarking I've
done of throughput and latency (response time) have shown best
performance at about ((2 * cores) + effective spindle count).  You
have four cores and (apparently) four "effective spindles" (which is
a complex topic in itself).  So, if your environment performs like
mine, you will see your best performance if you funnel those 750
client-side connections down to about 12 database connections, with
requests queued by the pooler when all 12 connections are busy.
With tens of thousands of concurrent clients hitting our web site,
we were able to improve throughput and response time by cutting our
connection pool from 60 connections to 30.  (Of course, this is on a
much larger system than you describe.)

interesting.  can you point me to something that will help me understand

this performance and how I can apply it to my situation?

 

General comments on your config:

> max_connections = 1000

Far too high; you need to use your connection pooler better, or use
a better connection pooler. 


> shared_buffers = 512MB

Not insane, but possibly a little on the low side.

 

probably -- but it's difficult to understand what this number actually does

for my system and its influence on postgres.

 


> maintenance_work_mem = 1024MB

OK

> max_stack_depth = 9MB

I've never adjusted this.  I'm a bit curious why you did.

 

followed the instructions: the value of ulimit -s minus 1MB. it probably doesn't matter.

 

> synchronous_commit = off

So you're OK with not necessarily having all transactions which were
successfully committed represented in the database if there is a
crash?  (That's not rhetorical -- for some applications that's OK;
others, not so much.)

 

 

yes.  i'm ok with this.

 

> commit_delay = 10
> commit_siblings = 2

Have you confirmed, through testing with your real workload, that
these settings are helping?  (I can see where they might, but
sometimes people adjust these without testing and actually make
things worse.)

yes. i've tested this.

 

> effective_cache_size = 1024MB

On a 16GB machine, that's probably too low to get the best plans on
some complex queries.  I'd probably be using something in the
neighborhood of 14GB.  For the insert load it won't make any
difference; but when it comes to querying all that data, it might.

i'll consider this.  thank you.

 

One setting you didn't override which almost certainly would help
your insert performance is wal_buffers.  Try setting that to 16MB.

good point, thank you. 

-Kevin

 

if I understand your position, though -- it is: reduce the number of concurrent

connections to increase the overal throughput of inserts on the table (because

they'll be less collisions on table locks??).  this reduction in connections

will reduce the maximum total memory used by them (but, still that is

just avoiding the inevitable, right -- if postgres processes can grow

larger than total memory, i'll still have a problem with 30 postgres processes

as I do with 750 postgres processes).

 

thank you for your response, any pointers for me to educate myself on these

things is greatly appreciated (a book?, google fu, web links?)

 

Pax, Keith

Re: how do you manage postgres 9's postgres process's memory

От
Greg Smith
Дата:
Benjamin Krajmalnik wrote:

I ordered some massive servers, and in the course of benchmarking them following their instructions it exposed apparent hardware issues – so the 2 massive servers as well as one of the smaller ones got shipped back to the supplier for them to check it out.  Had I assumed the servers were performing as the specs on paper indicated, I would have been in serious trouble a few months down the line as we would have reached limitations we were not aware of.


As a general statistic on this topic, about 1 out of every 3 servers I come across has a serious problem of this sort.  Maybe half of those are just software misconfiguration that can be fixed before deployment, the rest are more serious issues.  Nobody should every trust their hardware vendors to get things right, everyone's production schedules are just too tight nowadays relative to how complicated systems are.  Benchmarking yourself is the only reasonable defense against this very common problem.

-- 
Greg Smith   2ndQuadrant US    greg@2ndQuadrant.com   Baltimore, MD
PostgreSQL Training, Services, and 24x7 Support  www.2ndQuadrant.us
"PostgreSQL 9.0 High Performance": http://www.2ndQuadrant.com/books

Re: how do you manage postgres 9's postgres process's memory

От
"Kevin Grittner"
Дата:
Keith Gabryelski <keith@fluentmobile.com> wrote:

> any pointers for me to educate myself on these things is greatly
> appreciated (a book?, google fu, web links?)

http://www.postgresql.org/docs/books/

http://wiki.postgresql.org/wiki/Tuning_Your_PostgreSQL_Server

-Kevin