Re: High Frequency Inserts to Postgres Database vs Writing to a File

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Jay Manni wrote:

The data in the stream is in the form of variable length records with clearly defined fields ? so it can be stored in a database or in a file. The only caveat is that the rate of records coming in the stream could be several 1000 records a second.


There's a few limits to be concerned about here, some physical, some
related to your application design. A few thousand records is possible
with either the right software design or some hardware assist. The wall
where it gets increasingly difficult to keep up is closer to 10K/second,
presuming your records aren't particularly wide.

Some background: when you commit a record in PostgreSQL, by default
that transaction doesn't complete until data has been physically written
to disk. If you take a typical 7200 RPM disk, that spins 120
times/second, meaning that even under the best possible conditions there
can only be 120 commits per second to physical disk.

However, that physical commit can contain more than one record. Here
are the common ways to increase the number of records you can insert per
second:

1) Batch up inserts. Turn off any auto-commit behavior in your client,
insert a bunch of records, issue one COMMIT.
Typical popular batch sizes are in the 100-1000 records/commit range.
If individual records aren't very wide, you can easily get a huge
speedup here. Hard to estimate how much this will help in your case
without knowing more about that width and the speed of your underlying
disks; more on that below.

2) Have multiple clients committing at once. Typically I see this give
at most about a 5X speedup, so on a slow disk with single record commits
you might hit 600/s instead of 120/s if you had 10 clients going at once.

3) Use a RAID controller with a battery-backed cache. This will hold
multiple disk commits in its cache and dump them onto disk in larger
chunks transparently, with only a small risk of corruption if there's an
extended power outage longer than the battery lasts. Typically I'll see
this increase commit rate to the 1000-10,000 commits/second range, again
depending on underlying disk speed and row size. This approach really
reduces the worst-case behavior disks can get into, which is where you
keep seeking between two spots writing small bits at each one.

4) Turn off synchronous_commit. This lets you adjust the rate at which
records get committed into larger chunks without touching your
application or hardware. It does introduce the possibility you might
lose some records if there's a crash in the middle of loading or
changing things. Adjusting the commit period here upwards makes this
case look similar to (1), you're basically committing in larger chunks
but the app just doesn't know it.

Basically, (2) alone is probably not enough to reach 1,000 per second.
But (1) or (3) is, as is (4) if you can take the potential data
integrity issues if there's a crash. If your batchs get bigger via any
of these techniques, what should end up happening is that you push the
bottleneck to somewhere else, like disk write or seek speed. Which of
those you'll run into depends on how interleaved these writes are with
application reads and the total disk bandwidth.

To close, here's a quick example showing the sort of analysis you should
be doing to better estimate here. Imagine you're trying to write 10,000
records/second. Each record is 100 bytes wide. That works out to be
almost 1MB/s of steady disk writes. In the real world, a single cheap
disk can't do much better than this if those writes involve heavy
seeking around the disk. And that's happens in a database, because at a
minimum you need to write to both the main database area and the
write-ahead log. If your records are 1,000 records wide instead, you
might hit the upper limit of your disk seeking capability at only
1,000/second.

Whereas if you have an app that's just writing to a file, you wouldn't
necessarily expect that to regularly seek elsewhere. That means it's
much likely that you'd hit >10MB/s on writes rather than the 1-2MB/s
worst-case behavior when seeking. Of course, as you've already noted,
you end up paying penalties on reporting instead if you do that. The
best you can do here is to try and measure your application and
estimate/simulate larger volume, then see what happens if you apply one
or more of these techniques.

--
Greg Smith greg@xxxxxxxxxxxxxxx Baltimore, MD

--
Sent via pgsql-performance mailing list (pgsql-performance@xxxxxxxxxxxxxx)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-performance

[Postgresql General]     [Postgresql PHP]     [PHP Users]     [PHP Home]     [PHP on Windows]     [Kernel Newbies]     [PHP Classes]     [PHP Books]     [PHP Databases]     [Yosemite]

  Powered by Linux