Mysql一个大数据库或小许多表

时间:2011-04-07 17:30:59

标签: mysql scalability

我们的应用程序将为每个用户创建动态表单。

我们正在考虑两种方法

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

3 个答案:

答案 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