<p>What is a recommended architecture for providing storage for a dynamic logical database schema?</p>

<p>To clarify: Where a system is required to provide storage for a model whose schema may be extended or altered by its users once in production, what are some good technologies, database models or storage engines that will allow this? </p>

<p>A few possibilities to illustrate:</p>

<ul>
<li>Creating/altering database objects via dynamically generated DML</li>
<li>Creating tables with large numbers of sparse physical columns and using only those required for the 'overlaid' logical schema</li>
<li>Creating a 'long, narrow' table that stores dynamic column values as rows that then need to be pivoted to create a 'short, wide' rowset containing all the values for a specific entity</li>
<li>Using a BigTable/SimpleDB PropertyBag type system</li>
</ul>

<p>Any answers based on real world experience would be greatly appreciated</p>

[{'answer_id': 66397, 'author': 'Mike Becatti', 'author_id': 6617, 'author_profile': 'https://Stackoverflow.com/users/6617', 'pm_score': 4, 'selected': False, 'text': '<p>A strongly typed xml field in MSSQL has worked for us.  </p>\n'}, {'answer_id': 66442, 'author': 'Sklivvz', 'author_id': 7028, 'author_profile': 'https://Stackoverflow.com/users/7028', 'pm_score': 3, 'selected': False, 'text': "<p>The whole point of having a relational DB is keeping your data safe and consistent. The moment you allow users to alter the schema, there goes your data integrity...</p>\n\n<p><del>If your need is to store heterogeneous data, for example like a CMS scenario, I would suggest storing XML validated by an XSD in a row. Of course you lose performance and easy search capabilities, but it's a good trade off IMHO.</del></p>\n\n<p>Since it's 2016, forget XML! Use JSON to store the non-relational data bag, with an appropriately typed column as backend. You shouldn't normally need to query by value <em>inside the bag</em>, which will be slow even though many contemporary SQL databases understand JSON natively.</p>\n"}, {'answer_id': 66458, 'author': 'Daniel Spiewak', 'author_id': 9815, 'author_profile': 'https://Stackoverflow.com/users/9815', 'pm_score': 2, 'selected': False, 'text': '<p>Sounds to me like what you really want is some sort of "meta-schema", a database schema which is capable of describing a flexible schema for storing the actual data.  Dynamic schema changes are touchy and not something you want to mess with, especially not if users are allowed to make the change.</p>\n\n<p>You\'re not going to find a database which is more suited to this task than any other, so your best bet is just to select one based on other criteria.  For example, what platform are you using to host the DB?  What language is the app written in?  etc</p>\n\n<p>To clarify what I mean by "meta-schema":</p>\n\n<pre><code>CREATE TABLE data (\n    id INTEGER NOT NULL AUTO_INCREMENT,\n    key VARCHAR(255),\n    data TEXT,\n\n    PRIMARY KEY (id)\n);\n</code></pre>\n\n<p>This is a very simple example, you would likely have something more specific to your needs (and hopefully a little easier to work with), but it does serve to illustrate my point.  You should consider the database schema itself to be immutable at the application level; any structural changes should be reflected in the data (that-is, the instantiation of that schema).</p>\n'}, {'answer_id': 66473, 'author': 'Danimal', 'author_id': 2757, 'author_profile': 'https://Stackoverflow.com/users/2757', 'pm_score': 0, 'selected': False, 'text': "<p>In the past I've chosen option C -- <i>Creating a 'long, narrow' table that stores dynamic column values as rows that then need to be pivoted to create a 'short, wide' rowset containing all the values for a specific entity.</i>. However, I was using an ORM, and that REALLY made things painful. I can't think of how you'd do it in, say, LinqToSql. I guess I'd have to create a Hashtable to reference the fields.</p>\n\n<p>@Skliwz: I'm guessing he's more interested in allowing users to create user-defined fields.</p>\n"}, {'answer_id': 66484, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>I know that models indicated in the question are used in production systems all over. A rather large one is in use at a large university/teaching institution that I work for. They specifically use the long narrow table approach to map data gathered by many varied data acquisition systems. </p>\n\n<p>Also, Google recently released their internal data sharing protocol, protocol buffer, as open source via their code site. A database system modeled on this approach would be quite interesting.</p>\n\n<p>Check the following:</p>\n\n<p><a href="http://en.wikipedia.org/wiki/Entity-Attribute-Value_model" rel="nofollow noreferrer">Entity-attribute-value model</a></p>\n\n<p><a href="http://code.google.com/p/protobuf/" rel="nofollow noreferrer">Google Protocol Buffer</a></p>\n'}, {'answer_id': 66499, 'author': 'longneck', 'author_id': 8250, 'author_profile': 'https://Stackoverflow.com/users/8250', 'pm_score': -1, 'selected': False, 'text': '<p>sql already provides a way to change your schema: the ALTER command.</p>\n\n<p>simply have a table that lists the fields that users are not allowed to change, and write a nice interface for ALTER.</p>\n'}, {'answer_id': 67189, 'author': 'Thevs', 'author_id': 8559, 'author_profile': 'https://Stackoverflow.com/users/8559', 'pm_score': 3, 'selected': False, 'text': '<p>I did it ones in a real project:</p>\n\n<p>The database consisted of one table with one field which was an array of 50. It had a \'word\' index set on it. All the data was typeless so the \'word index\' worked as expected. Numeric fields were represented as characters and the actual sorting had been done at client side. (It still possible to have several array fields for each data type if needed).</p>\n\n<p>The logical data schema for logical tables was held within the same database with different table row \'type\' (the first array element). It also supported simple versioning in copy-on-write style using same \'type\' field.</p>\n\n<p>Advantages:</p>\n\n<ol>\n<li>You can rearrange and add/delete your columns dynamically, no need for dump/reload of database. Any new column data may be set to initial value (virtually) in zero time. </li>\n<li>Fragmentation is minimal, since all records and tables are same size, sometimes it gives better performance.</li>\n<li>All table schema is virtual. Any logical schema stucture is possible (even recursive, or object-oriented).</li>\n<li>It is good for "write-once, read-mostly, no-delete/mark-as-deleted" data (most Web apps actually are like that).</li>\n</ol>\n\n<p>Disadvantages:</p>\n\n<ol>\n<li>Indexing only by full words, no abbreviation,</li>\n<li>Complex queries are possible, but with slight performance degradation.</li>\n<li>Depends on whether your preferred database system supports arrays and word indexes (it was inplemented in PROGRESS RDBMS).</li>\n<li>Relational model is only in programmer\'s mind (i.e. only at run-time).</li>\n</ol>\n\n<p>And now I\'m thinking the next step could be - to implement such a database on the file system level. That might be relatively easy.</p>\n'}, {'answer_id': 68138, 'author': 'Matt Rogish', 'author_id': 2590, 'author_profile': 'https://Stackoverflow.com/users/2590', 'pm_score': 5, 'selected': False, 'text': '<p>What you are proposing is not new. Plenty of people have tried it... most have found that they chase "infinite" flexibility and instead end up with much, much less than that. It\'s the "roach motel" of database designs -- data goes in, but it\'s almost impossible to get it out. Try and conceptualize writing the code for ANY sort of constraint and you\'ll see what I mean.</p>\n\n<p>The end result typically is a system that is MUCH more difficult to debug, maintain, and full of data consistency problems. This is not <em>always</em> the case, but more often than not, that is how it ends up. Mostly because the programmer(s) don\'t see this train wreck coming and fail to defensively code against it. Also, often ends up the case that the "infinite" flexibility really isn\'t that necessary; it\'s a very bad "smell" when the dev team gets a spec that says "Gosh I have no clue what sort of data they are going to put here, so let \'em put WHATEVER"... and the end users are just fine having pre-defined attribute types that they can use (code up a generic phone #, and let them create any # of them -- this is trivial in a nicely normalized system and maintains flexibility and integrity!)</p>\n\n<p>If you have a very good development team and are <strong>intimately aware</strong> of the problems you\'ll have to overcome with this design, you can successfully code up a well designed, not terribly buggy system. Most of the time. </p>\n\n<p>Why start out with the odds stacked so much against you, though?</p>\n\n<p>Don\'t believe me? Google "One True Lookup Table" or "single table design". Some good results:\n<a href="http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10678084117056" rel="noreferrer">http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10678084117056</a></p>\n\n<p><a href="http://thedailywtf.com/Comments/Tom_Kyte_on_The_Ultimate_Extensibility.aspx?pg=3" rel="noreferrer">http://thedailywtf.com/Comments/Tom_Kyte_on_The_Ultimate_Extensibility.aspx?pg=3</a></p>\n\n<p><a href="http://www.dbazine.com/ofinterest/oi-articles/celko22" rel="noreferrer">http://www.dbazine.com/ofinterest/oi-articles/celko22</a></p>\n\n<p><a href="http://thedailywtf.com/Comments/The_Inner-Platform_Effect.aspx?pg=2" rel="noreferrer">http://thedailywtf.com/Comments/The_Inner-Platform_Effect.aspx?pg=2</a></p>\n'}, {'answer_id': 73547, 'author': 'AJ.', 'author_id': 7211, 'author_profile': 'https://Stackoverflow.com/users/7211', 'pm_score': 2, 'selected': False, 'text': '<h2>Create 2 databases</h2>\n<ul>\n<li>DB1 contains static tables, and represents the &quot;real&quot; state of the data.</li>\n<li>DB2 is free for users to do with as they wish - they (or you) will have to write code to populate their odd-shaped tables from DB1.</li>\n</ul>\n'}, {'answer_id': 1764969, 'author': 'Josh Yeager', 'author_id': 52080, 'author_profile': 'https://Stackoverflow.com/users/52080', 'pm_score': 4, 'selected': False, 'text': "<p>Like some others have said, don't do this unless you have no other choice. One case where this is required is if you are selling an off-the-shelf product that must allow users to record custom data. My company's product falls into this category.</p>\n\n<p>If you do need to allow your customers to do this, here are a few tips:<br>\n - Create a <strong>robust</strong> administrative tool to perform the schema changes, and do not allow these changes to be made any other way.<br>\n - Make it an administrative feature; don't allow normal users to access it.<br>\n - Log every detail about every schema change. This will help you debug problems, and it will also give you CYA data if a customer does something stupid.  </p>\n\n<p>If you can do those things successfully (especially the first one), then any of the architectures you mentioned will work. My preference is to dynamically change the database objects, because that allows you to take advantage of your DBMS's query features when you access the data stored in the custom fields. The other three options require you load large chunks of data and then do most of your data processing in code.</p>\n"}, {'answer_id': 3799240, 'author': 'clyfe', 'author_id': 283608, 'author_profile': 'https://Stackoverflow.com/users/283608', 'pm_score': 3, 'selected': False, 'text': '<p>I have a similar requirement and decided to use the schema-less <a href="http://en.wikipedia.org/wiki/MongoDB" rel="noreferrer">MongoDB</a>.  </p>\n\n<blockquote>\n  <p>MongoDB (from "humongous") is an open source, scalable, high-performance, schema-free, document-oriented database written in the C++ programming language. (Wikipedia)</p>\n</blockquote>\n\n<p>Highlights:</p>\n\n<ul>\n<li>has rich query functionality (maybe the closest to SQL DBs)</li>\n<li>production ready (foursquare, sourceforge use it)</li>\n</ul>\n\n<p>Lowdarks (stuff you need to understand, so you can use mongo correctly):</p>\n\n<ul>\n<li>no transactions (actually it has transactions but only on atomic operations)</li>\n<li>this stuff here: <a href="http://ethangunderson.com/blog/two-reasons-to-not-use-mongodb/" rel="noreferrer">http://ethangunderson.com/blog/two-reasons-to-not-use-mongodb/</a></li>\n<li>durability .. mostly ACID related stuff</li>\n</ul>\n'}, {'answer_id': 7445786, 'author': 'kamal', 'author_id': 948970, 'author_profile': 'https://Stackoverflow.com/users/948970', 'pm_score': 2, 'selected': False, 'text': '<p>EAV approach i  believe is the best approach, but comes with a heavy cost</p>\n'}, {'answer_id': 22207828, 'author': 'Oliver Konig', 'author_id': 2290188, 'author_profile': 'https://Stackoverflow.com/users/2290188', 'pm_score': 2, 'selected': False, 'text': '<p>I know it\'s an old topic, but I guess that it never loses actuality.\nI\'m developing something like that right now.\nHere is my approach.\nI use a server setting with a MySQL, Apache, PHP, and Zend Framework 2 as application framework, but it should work as well with any other settings.</p>\n\n<p>Here is a simple implementation guide, you can evolve it yourself further from this.</p>\n\n<p>You would need to implement your own query language interpreter, because the effective SQL would be too complicated.</p>\n\n<p>Example:</p>\n\n<pre><code>select id, password from user where email_address = "xyz@xyz.com"\n</code></pre>\n\n<p>The physical database layout:</p>\n\n<p>Table \'specs\': (should be cached in your data access layer)</p>\n\n<ul>\n<li>id: int </li>\n<li>parent_id: int </li>\n<li>name: varchar(255) </li>\n</ul>\n\n<p>Table \'items\': </p>\n\n<ul>\n<li>id: int </li>\n<li>parent_id: int </li>\n<li>spec_id: int  </li>\n<li>data: varchar(20000) </li>\n</ul>\n\n<p>Contents of table \'specs\':</p>\n\n<ul>\n<li>1, 0, \'user\'</li>\n<li>2, 1, \'email_address\'</li>\n<li>3, 1, \'password\'</li>\n</ul>\n\n<p>Contents of table \'items\':</p>\n\n<ul>\n<li>1, 0, 1, \'\'</li>\n<li>2, 1, 2, \'xyz@xyz.com\'</li>\n<li>3, 1, 3, \'my password\'</li>\n</ul>\n\n<p>The translation of the example in our own query language:</p>\n\n<pre><code>select id, password from user where email_address = "xyz@xyz.com"\n</code></pre>\n\n<p>to standard SQL would look like this:</p>\n\n<pre><code>select \n    parent_id, -- user id\n    data -- password\nfrom \n    items \nwhere \n    spec_id = 3 -- make sure this is a \'password\' item\n    and \n    parent_id in \n    ( -- get the \'user\' item to which this \'password\' item belongs\n        select \n            id \n        from \n            items \n        where \n            spec_id = 1 -- make sure this is a \'user\' item\n            and \n            id in \n            ( -- fetch all item id\'s with the desired \'email_address\' child item\n                select \n                    parent_id -- id of the parent item of the \'email_address\' item\n                from \n                    items \n                where \n                    spec_id = 2 -- make sure this is a \'email_address\' item\n                    and\n                    data = "xyz@xyz.com" -- with the desired data value\n            )\n    )\n</code></pre>\n\n<p>You will need to have the specs table cached in an associative array or hashtable or something similar to get the spec_id\'s from the spec names. Otherwise you would need to insert some more SQL overhead to get the spec_id\'s from the names, like in this snippet:</p>\n\n<p>Bad example, don\'t use this, avoid this, cache the specs table instead!</p>\n\n<pre><code>select \n    parent_id, \n    data \nfrom \n    items \nwhere \n    spec_id = (select id from specs where name = "password") \n    and \n    parent_id in (\n        select \n            id \n        from \n            items \n        where \n            spec_id = (select id from specs where name = "user") \n            and \n            id in (\n                select \n                    parent_id \n                from \n                    items \n                where \n                    spec_id = (select id from specs where name = "email_address") \n                    and \n                    data = "xyz@xyz.com"\n            )\n    )\n</code></pre>\n\n<p>I hope you get the idea and can determine for yourself whether that approach is feasible for you.</p>\n\n<p>Enjoy! :-)</p>\n'}, {'answer_id': 44865271, 'author': 'Oren', 'author_id': 1898831, 'author_profile': 'https://Stackoverflow.com/users/1898831', 'pm_score': 0, 'selected': False, 'text': '<p>ElasticSearch. You should consider it especially if you\'re dealing with datasets that you can partition by date, you can use JSON for your data, and are not fixed on using SQL for retrieving the data. </p>\n\n<p>ES infers your schema for any new JSON fields you send, either automatically, with hints, or manually which you can define/change by one HTTP command ("mappings").\nAlthough it does not support SQL, it has some great lookup capabilities and even aggregations. </p>\n'}, {'answer_id': 46202802, 'author': 'FloverOwe', 'author_id': 6885037, 'author_profile': 'https://Stackoverflow.com/users/6885037', 'pm_score': 1, 'selected': False, 'text': '<p>Over at the c2.com wiki, the idea of <a href="https://wiki.c2.com/?DynamicRelational" rel="nofollow noreferrer">"Dynamic Relational"</a> was explored. You DON\'T need a DBA: columns and tables are Create-On-Write, unless you start adding constraints to make it act more like a traditional RDBMS: as a project matures, you can incrementally "lock it down". </p>\n\n<p>Conceptually you can think of each row as an XML statement. For example, an employee record could be represented as:</p>\n\n<pre><code>&lt;employee lastname="Li" firstname="Joe" salary="120000" id="318"/&gt;\n</code></pre>\n\n<p>This does <em>not</em> imply it has to be implemented as XML, it\'s just a handy conceptualization. If you ask for a non-existing column, such as "SELECT madeUpColumn ...", it\'s treated as blank or null (unless added constraints forbid such). And it\'s possible to use <strong>SQL</strong>, although one has to be careful about comparisons because of the implied type model. But other than type handling, users of a Dynamic Relational system would feel right at home because they can leverage most of their existing RDBMS knowledge. Now, if somebody would just build it...</p>\n'}, {'answer_id': 63710622, 'author': 'sgoldberg', 'author_id': 1043598, 'author_profile': 'https://Stackoverflow.com/users/1043598', 'pm_score': 0, 'selected': False, 'text': '<p>I know this is a super old post, and much has changed in the last 11 years, but thought I would added this as it might be helpful to future readers. One of the reason\'s why my co-founders and I created HarperDB is to natively accomplish Dynamic schema in a single, unduplicated data set while providing full index capability.  You can read more about it here:<br />\n<a href="https://harperdb.io/blog/dynamic-schema-the-harperdb-way/" rel="nofollow noreferrer">https://harperdb.io/blog/dynamic-schema-the-harperdb-way/</a></p>\n'}]
['https://Stackoverflow.com/questions/66385', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/6199/']