The LinkedIn MySQL DB Development group posed a questions on how to handle images. Naturally, the argument always goes: Should images be deployed in the database or the file system? I believe they should be stored in the database because the cost and time associated is too high with regard to managing files, a file naming schema, and backing up the file system discretely from the database.

Since there’s a significant difference between the backup of transactional data and image data, they should be placed in different databases. The imagedb database is where you would place the images and large text descriptions, as shown in the MySQL Workbench ERD:

The imagedb ERD splits the foreign key references back to the system_user table, which contains the individual user credentials. The system_user table serves as the Access Control List (ACL) for the application.

Until I get a chance to write the code for this model, you can refer to the generic PHP/MySQL solution from several years back (its code source was last tested with PHP 5.3). As always, I hope this helps.

Martin (?), I did acknowledge that there are two schools of thought. Obviously, you’re in one and I’m in the other. As to the owner of the schema, doesn’t ownership depend on whether you’ve a small application with a narrow use case (like a hosted customer) or a large application with several use cases?

To my opinion, File is not a relational data. Relational database is a wrong place to store non-relational data including files. filesystem is the right place for that.

There are many reasons a DBA should oppose it.

1. Every write operation to RDBMS will result in write into 3-4 places. Transaction logs (Redo info) and Rollback segment (Undo info) and final tablespace files etc and associated flushes also.
Do you think 3-4 times overhead is worth for storing a file?

2. IO is the major bottleneck in any RDBMS and any small hit will have tremendous impact on overall performance of databases.

3. If images are stored in filesystem of the application server, there is performance hit on database. Any slow down of database will affect the complete application.

I’d agree that some files are better suited to the application server, like those that display as icon images as part of your company’s generic graphics on webpage layouts. However, there are other images like those that are tied to catalog materials. Images tied to catalog materials are low write frequency, which means they have a nominal impact on transaction logs. Putting them in a separate database also lets you manage their transaction logs separately. Also, a large text or binary file can be considered as a non-key data attribute.

Queries against these types of catalog images are directly linked to records. When you query the records you have two options, call another local function to read a mime-type and binary stream from the database, or return a URL value.

A local function would return a mime-type header and converted binary stream to the browser, and the browser would render the image. If you return a URL, the browser determines the mime-type by reading the file type of the image to sets a header before reading the image from the file system. The physical location of the files are disclosed in primary read of the HTML source to the browser because images are read through separate asynchronous threads. This discloses either relative or absolute path information on the location of files to potential hackers, which means the location of images unrelated to the transaction. The trade off is the physical IO against the OS versus the physical IO against the database server, and I doubt there’s much difference between the two.

The blobs are going to end up being stored off page, and you are going to do extra IO. The overflow pages are allocated in rather big chunks and lots of space is wasted by blobs.

There are many technical reasons why you don’t want to store blobs in the database.

Use a filesystem with transactional writes, like ZFS and updates points to blobs on the filesystem. This gives you scaleable storage for binary data (which is what a distributed filesystem is for) while allowing you to manage metadata in the RDBMS.

This is essentially what Oracle would called a BFILE (a pointer to a binary file).

Justin, I like your solution and agree with it. Notwithstanding, sometimes implementing the ZFS file system isn’t an available option as a solution in organizations. When choosing the file system is a possibility, the downside is you still need a convention for file names.

In that case, you would drop the imagedb database and mime_type table but keep the image and description tables with a couple changes. You’d drop the mime_type and item_image columns from the image table.

My opinion is that it is not a good idea to store the images in the database. You may be better served by computing a SHA hash of your image, use that as the filename and then store the SHA hash in the database.
If ease of back-ups is your worry, a trivial solution would be to store those files in a subdir under the database data dir and modify Xtrabackup wrapper script to tar up that dir after xtrabackup has done its thing.

Regarding the ownership: Whoever pays for the development of the schema is the owner.

Regarding BLOBs in a DB. Think mail servers. There’s a reason why almost all storage of mails is outside of a RDBMS (generally not specific to MySQL). Write hits being only one if them.

Creating a (cryptographic) checksum of the file and using that as the path is well established (mail spools, storage deduplication for free — also helps the OS cache,…)

The thing that freaks me out is the extremely tight coupling between mass storage (images, files, BLOBs,…) and the meta data. How would you separate those? I do have a lot of binaries in the inventory(100s of 1000s) and I like to be able to nicely separate inventory and data at least to be able to scale the inventory independent of the files. How would you do that?

The one reason to use BLOBs inside of a DB is not a technical one but rather to be able to create an atomic backup if all the inventory you have (Think: compliance).

Then again with a fully qualified URI (http, file, s3,…) you can simply move data around implement another provider and let your customers use whatever they already have and there’s no need for them to migrate and no need for you to pay for the bandwith or additional capacity required to serve the images.

But I’m getting carried away…I guess you are right. Let’s agree to disagree[×]

Oh and I do like my nick. That’s why I put it in the name field, after all we are simply brabbling over technical details without either of us knowing enough about each others past experiences or current requirements.

[×]: I keep the right to change my mind or past decisions at any time without further notice

Neither database nor filesystem is always the right choice. Pick whichever is best for your use case. We have people storing video in chunks in the server for video on demand services, others storing images and whatever else.

If the images are integral to your application you get the usual database benefits, like transactional guarantees and the reliability of replication along with easy use of the standard database scaling out solutions.

If you’re doing a packaged, hosted application, do you really want to try to get a hosting service to give you great filesystem access when you can instead ask for a straightforward database server that they’ve done ten thousand times already? In such cases using the database by default can make life a lot easier for your customers, even if you provide other options.

Try not to store the images in your main database server. This is bulk storage and can be very well suited to large SATA drives rather than SSD or 15K SCSI. It can be on the same hardware, but not great to be in the same mysqld. It is possible to combine the bulk storage with OLTP on the same mysqld but you’ll probably find that the best tunings are different and that you’re better off splitting them.

It’s perhaps also worth knowing that back in 2004 we removed the article text from Wikipedia’s main tables and eventually even off the main database servers, instead storing them in multi-revision combined compressed blobs on SATA drive sets, still stored in MySQL on those.

Character things also may not be best in the database server and your use case matters here as well. Bulk textual information, whether it’s varchar or text, is not something you want to have in very frequently updated or accessed tables, it does nasty things to your cache hit rates and to the sizes of the rows that you have to read. storing a name and address in a customer record is a common poor choice. Most of the customer references will be joins to do things like getting order summary information, not items that need their address.

The specific use cases matter. Don’t get religious, consider each case and pick whichever way makes most sense for the task at hand. First thing to do is probably to ask whether the database features matter to your use case. If they do, that’d be a good argument for picking the database over the filesystem. But maybe not a sufficient one, consider the rest of the situation as well.