Storing Images in PostgreSQL

Viewed 228258

Alright, so I'm working on an application which will use a Linux back-end running PostgreSQL to serve up images to a Windows box with the front end written in C#.NET, though the front-end should hardly matter. My question is:

  • What is the best way to deal with storing images in Postgres?

The images are around 4-6 megapixels each, and we're storing upwards of 3000. It might also be good to note: this is not a web application, there will at most be about two front-ends accessing the database at once.

8 Answers

Re jcoby's answer:

bytea being a "normal" column also means the value being read completely into memory when you fetch it. Blobs, in contrast, you can stream into stdout. That helps in reducing the server memory footprint. Especially, when you store 4-6 MPix images.

No problem with backing up blobs. pg_dump provides "-b" option to include the large objects into the backup.

So, I prefer using pg_lo_*, you may guess.

Re Kris Erickson's answer:

I'd say the opposite :). When images are not the only data you store, don't store them on the file system unless you absolutely have to. It's such a benefit to be always sure about your data consistency, and to have the data "in one piece" (the DB). BTW, PostgreSQL is great in preserving consistency.

However, true, reality is often too performance-demanding ;-), and it pushes you to serve the binary files from the file system. But even then I tend to use the DB as the "master" storage for binaries, with all the other relations consistently linked, while providing some file system-based caching mechanism for performance optimization.

In the database, there are two options:

  • bytea. Stores the data in a column, exported as part of a backup. Uses standard database functions to save and retrieve. Recommended for your needs.
  • blobs. Stores the data externally, not normally exported as part of a backup. Requires special database functions to save and retrieve.

I've used bytea columns with great success in the past storing 10+gb of images with thousands of rows. PG's TOAST functionality pretty much negates any advantage that blobs have. You'll need to include metadata columns in either case for filename, content-type, dimensions, etc.

Update from 10 years later In 2008 the hard drives you would run a database on would have much different characteristics and much higher cost than the disks you would store files on. These days there are much better solutions for storing files that didn't exist 10 years ago and I would revoke this advice and advise readers to look at some of the other answers in this thread.

Original

Don't store in images in the database unless you absolutely have to. I understand that this is not a web application, but if there isn't a shared file location that you can point to save the location of the file in the database.

//linuxserver/images/imagexxx.jpg

then perhaps you can quickly set up a webserver and store the web urls in the database (as well as the local path). While databases can handle LOB's and 3000 images (4-6 Megapixels, assuming 500K an image) 1.5 Gigs isn't a lot of space file systems are much better designed for storing large files than a database is.

Try this. I've use the Large Object Binary (LOB) format for storing generated PDF documents, some of which were 10+ MB in size, in a database and it worked wonderfully.

If your images are small, consider storing them as base64 in a plain text field.

The reason is that while base64 has an overhead of 33%, with compression that mostly goes away. (See What is the space overhead of Base64 encoding?) Your database will be bigger, but the packets your webserver sends to the client won't be. In html, you can inline base64 in an <img src=""> tag, which can possibly simplify your app because you won't have to serve up the images as binary in a separate browser fetch. Handling images as text also simplifies things when you have to send/receive json, which doesn't handle binary very well.

Yes, I understand you could store the binary in the database and convert it to/from text on the way in and out of the database, but sometimes ORMs make that a hassle. It can be simpler just to treat it as straight text just like all your other fields.

This is definitely the right way to handle thumbnails.

(OP's images are not small, so this is not really an answer to his question.)

2022 Answer

The most common pattern now is to only store a reference to the image in your database, and store the image itself in a filesystem (i.e. S3 bucket).

The benefit is that your database backups are smaller, there's no longer a single point of failure, load can now be distributed away from the database, and cloud storage buckets are often cheaper than database storage.

The negative is that you have to manage images in two locations - delete one image and your app needs to keep track and delete it from the other.

Related