views:

381

answers:

3

I am writing web application using ASP.NET MVC + NHibernate + Postres stack. I wonder if images uploaded should be stored in database as binary blobs or on filesystem (and reference only in db). One advantage of db storage I can think of is easy backup/recovery of all data without reverting to filesystem copy tools. On the other hand I suspect that filesystem access may be faster (but is it especially when dealing with many concurrent requests?) What are your suggestions?

A: 

It depends. Do you value being able to directly link to an image, or do you want to always use server side resources to call the DB, and then write the binary data for the image?

Tejs
+2  A: 

I'd do both- ensure the images are stored in the database so that all data is centralised for easy backup, but cache the data externally too, so that repeated requests for large images don't thrash the buffer cache of the database. Done properly, you can bring in new frontend web servers that will transparently populate their local image cache from the database after starting up.

Having a centralised store for the images is also useful for ensuring that you send good Last-Modified and ETag HTTP response headers for images in a system with multiple web servers, as those headers can be made from database contents rather than taken from the local cache objects.

Just an implementation note for PostgreSQL specifically: you can set the "storage mode" of the column containing your image data to "external": this will stop PostgreSQL trying to compress the image data (using zlib, which isn't likely to provide any benefit) and will make it store the image data in an auxiliary TOAST table, providing better performance if you're just querying the image metadata. See the "SET STORAGE" clause of the ALTER TABLE command, e.g.:

ALTER TABLE media.image ALTER COLUMN content SET STORAGE EXTERNAL
araqnid
+1  A: 

We utilize storage of originals in database for backup, but generated scaled down images that is cached on filesystem on the webservers.

However, we try to avoid any roundtrips to the database if possible, because it generates huge load since one page usually invokes several image-request per page-view.

One note on storing blobs in database, I suggest that you stor the actual blob-columns in a dedicated table, with a one-to-one mapping to your entity / entities. This will ease backups, aswell as alteration of your tables. When a table grows big, any changes will take "forever" to complete and locking is a big problem to, even during backup.

If you have all info about the images (except the binary data) selecting that data won't be affected unless you need the binary data (which you rarely need since it will be cached in file-system).

Just my two cents.

jishi
Different databases have different approaches to storing blobs: postgresql will automatically store large bytea values out-of-line in a separate "toast" table, so there's no need to do this explicitly.
araqnid
In fact, for storing image data it's probably advisable to use "alter table ... alter column ... set storage external" to force out-of-line storage all the time and disable compression.
araqnid
Hm, thats strange because we use postgres and I have problem with table-locking when altering tables and backing it up.
jishi
@jishi altering a table will typically need an exclusive lock on the table object itself. the worst case is some sort of alter table or update statement that touches every row, which would have to duplicate all the table data. so storing a bytea in a separate one-to-one table makes sense if the data associated with it changes often.
araqnid