我们的应用程序将为每个用户创建动态表单。
我们正在考虑两种方法
a)我们将所有用户表单数据存储在单个表中作为键值对,然后使用pivot table technique获取数据并进行过滤,但我认为可能是非常庞大的资源消耗
b)为每个表单用户创建适合其设计的创建/设计表,这里我们没有透视,我们获得了mysql的所有好处,而且我们不会有超过几个表的连接
我们主要关心的是可扩展性,在场景'a'中,如果表增长非常大(如果我考虑甚至1000个用户注册,这显然会发生),如果明天我们的表随着我们的流量增长而计划'b'我们可能会有使用mysql集群,但集群有表限制,因为我在这里阅读http://dev.mysql.com/doc/refman/5.0/en/mysql-cluster-limitations-database-objects.html
更新
一个新的想法让我们感到震惊,为什么不创建一个适合单个表单元素(文本字段,文本区域等)的单个表(作为键,值),使用基于表单的连接(连接数=字段数)用户创建的定义我们可以创建一个水平数据,而无需调整您对这个想法的所有想法。
2011年4月9日更新
我们测试了针对联接的旋转
场景 - 我们有一个包含7个字段的表单,数据存储为(单个表单插入的示例数据)
------------------------------ | Key | Value | ------------------------------ | Key1 | Value1 | | Key2 | Value2 | | Key3 | Value3 | | Key4 | Value4 | | Key5 | Value5 | | Key6 | Value6 | | Key7 | Value7 | ------------------------------
对于数据透视查询,将70000行转换为10000个表单插入需要0.92秒 对于加入,花了17.63秒(woof .....)来显示这些10000个表单插入
我的表
CREATE TABLE IF NOT EXISTS `vet` ( `id` int(11) NOT NULL, `form_id` int(11) NOT NULL, `key` varchar(255) NOT NULL, `value` varchar(255) NOT NULL, KEY `id` (`id`), KEY `form_id` (`form_id`) ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
透视查询
SELECT id, GROUP_CONCAT(if(`key` = 'k1', value, NULL)) as 'key1', GROUP_CONCAT(if(`key` = 'k2', value, NULL)) as 'key2', GROUP_CONCAT(if(`key` = 'k3', value, NULL)) as 'key3', GROUP_CONCAT(if(`key` = 'k4', value, NULL)) as 'key4', GROUP_CONCAT(if(`key` = 'k5', value, NULL)) as 'key5', GROUP_CONCAT(if(`key` = 'k6', value, NULL)) as 'key6', GROUP_CONCAT(if(`key` = 'k7', value, NULL)) as 'key7' FROM vet WHERE form_id = 2 GROUP BY id
加入查询
SELECT v.id, v1.value as key1, v2.value as key2, v3.value as key3, v4.value as key4, v5.value as key5, v6.value as key6, v7.value as key7 FROM vet v LEFT JOIN vet v1 ON v1.id = v.id AND v1.`key` = "k1" LEFT JOIN vet v2 ON v2.id = v.id AND v2.`key` = "k2" LEFT JOIN vet v3 ON v3.id = v.id AND v3.`key` = "k3" LEFT JOIN vet v4 ON v4.id = v.id AND v4.`key` = "k4" LEFT JOIN vet v5 ON v5.id = v.id AND v5.`key` = "k5" LEFT JOIN vet v6 ON v6.id = v.id AND v6.`key` = "k6" LEFT JOIN vet v7 ON v7.id = v.id AND v7.`key` = "k7" WHERE v.form_id = 2 GROUP BY v.id
我认为我们现在会坚持转向,如果差异很大,也请查看我的疑问。
请建议哪种解决方案更好或是否有其他更好的解决方案
SUDESH
答案 0 :(得分:1)
我建议使用一个数据库进行设计。然后,您总是可以在需要时使用分片进行水平缩放。
答案 1 :(得分:1)
您不希望为用户创建的每个表单创建新表 但是,您也不希望将所有数据存储在一个大表中 最好将东西存放在几张桌子中,这样你就不会重复这些东西了。
首先是一个包含用户数据的表:
Table user
id: integer autoincrement primary key
username: varchar(255)
other user data
Then a table that links the user to the form data (but does not actually hold any form data
Table UserForm
id: integer autoincrement primary key
user_id: integer index
... other fields for fixed data that always occurs only once in each form.
Then the table with the Form data
Table FormProperties
id: integer autoincrement primary key
UserForm_id: integer index
PropertyName: varchar(255)
PropertyValue: varchar(255)
Now when you want to access data from a form you use a query like
Table UserForm
id: integer autoincrement primary key
user_id: integer index
... other fields for fixed data that always occurs only once in each form.
这样您就不会存储冗余数据。 请注意,如果您永远不需要唯一访问单个属性,则可以在属性表中删除唯一ID。
不要担心MySQL集群,只需从带有MySAM表的vanilla MySQL(5.x)开始,如果这还不够快,那么你就可以开始考虑技巧了,但是在100万以下的记录中我不会打扰。
答案 2 :(得分:0)
很容易理解拥有许多小型数据库的问题: - 当索引和表很小时,磁盘和内存的使用效率低下 - 当#databases>时,mysql服务器的扩展性很差100和#tables> 10000 - 管理/管理噩梦 但有一些优点: - 隔离客户提供更好的安全性 - 转储/加载/锁定/更改单个客户的表而不影响其他客户 - 更易于管理多个版本和自定义架构添加
有一个大型数据库,带有分片,声音很好但有缺点: - 所有客户都被锁定在同一架构中,必须立即进行升级 - 个别客户的安全性差 - 需要修改代码来管理分片 - 一旦建立,很难更改碎片 - “坏邻居”效应:一个过度活跃的客户会影响分片中邻居的SLA 它的主要优点是它可以很好地扩展。
完全披露:我在ParElastic工作。但我真诚地相信,我们的虚拟多租户数据库可以解决这个问题: - 每个客户都可以看到他们自己的数据库的完整,孤立的实例 - 为其数据库提供独立的管理命令 - 覆盖范围内的可扩展分片,以在用户之间和内部分发数据 - 每个客户架构管理支持滚动升级和自定义扩展 - 使用普通SQL的安全,跨客户查询
如果您有兴趣,可以在https://aws.amazon.com/marketplace(搜索“parelastic”)中免费下载预先打包的ParElastic环境。或者查看http://parelastic.com。