PostgreSQL – Designing a Product Attribute System Without EAV

database-designpostgresql

I'm working on building an attribute system for products. The issue that I'm running into is that various products can have very different attribute requirements.

Some E-commerce websites such as Magento use an EAV system. That's something that I'd like to avoid due to performance issues, database cleanliness/complexity/control.

So far I'm leaning towards using a variety of tables. For example I might have a table of attributes that pertain to medical devices and then a different table that is for toys and games. Any attributes that are generic would just fall into the actual product table. If I do choose to go with this option, then I suppose my product table would have a column which represents which attribute table is used.

I'm not actually a Database Administrator, so I don't really know what's best. I hope that someone is able to give me some insights into a good implementation or acknowledge that my current thought process is in the right direction.

Thank you

Best Answer

As a horse_with_no_name suggested, I would also go with hstore if you are using PostgreSQL becuase I think its the easiest to morph back to regular table structure if you decide you need that.

There are a couple of features that make hstore pretty nice for your problem:

1) Indexing is pretty fast

2) You can query hstore column with something like

SELECT p.product_name, properties->'color' As color, properties->'size'::numeric As size
     FROM products;

So makes it good for reporting simply by wrapping your different product lines in a view

3) The main downside with hstore is keeping track of properties specific to a particular product type, however you can easily compensate for this with PostgreSQL type system

as demonstrated here: https://stackoverflow.com/questions/16092890/how-can-i-translate-a-postgresql-hstore-column-into-a-row

So you can define say a properties type for shoes called CREATE TYPE shoe_properties(color text, size numeric);

or just use a lookup table of property types and their corresponding data types for editing purposes. Then if you decide later you really want to go with the separate table for properties approach, your job would be simple by just creating a typed table from your type and using popular_record to morph your hstore into a row for insert into table.