我可以通过将一个大表分成许多小表来优化我的数据库吗?

时间:2010-11-07 11:13:42

标签: mysql optimization split

假设我有一个包含三列的大表:“user_name”,“user_property”,“value_of_property”。 Lat也假设我有很多用户(比如10万)和很多属性(比方说10 000)。然后表格将是巨大的(10亿行)。

当我从表中提取信息时,我总是需要有关特定用户的信息。所以,我使用,例如where user_name='Albert Gates'。因此,每次mysql服务器需要分析10亿行时,找到包含“Albert Gates”作为user_name的那些行。

将大表分成许多与固定用户相对应的小表是不明智的?

4 个答案:

答案 0 :(得分:5)

不,我认为这不是一个好主意。更好的方法是user_name列上的add an index - 或者(user_name, user_property)上的另一个索引,用于查找单个属性。然后数据库不需要扫描所有行 - 它只需要在索引中找到存储在B-Tree中的相应条目,这样可以在很短的时间内轻松找到记录。 / p>

如果您的应用程序即使在正确编制索引后仍然很慢,那么partition最大的表格有时是个好主意。

您可以考虑的另一件事是规范化您的数据库,以便user_name存储在一个单独的表中,并在其位置使用整数foriegn键。这可以降低存储要求并可以提高性能。这同样适用于user_property

答案 1 :(得分:3)

您应该规范化您的设计,如下所示:

drop table if exists users;
create table users
(
user_id int unsigned not null auto_increment primary key,
username varbinary(32) unique not null
)
engine=innodb;

drop table if exists properties;
create table properties
(
property_id smallint unsigned not null auto_increment primary key,
name varchar(255) unique not null
)
engine=innodb;

drop table if exists user_property_values;
create table user_property_values
(
user_id int unsigned not null,
property_id smallint unsigned not null,
value varchar(255) not null,
primary key (user_id, property_id),
key (property_id)
)
engine=innodb;

insert into users (username) values ('f00'),('bar'),('alpha'),('beta');

insert into properties (name) values ('age'),('gender');

insert into user_property_values values 
(1,1,'30'),(1,2,'Male'),
(2,1,'24'),(2,2,'Female'),
(3,1,'18'),
(4,1,'26'),(4,2,'Male');

从性能角度来看,innodb聚集索引在这个类似的例子(COLD run)中有奇效:

select count(*) from product
count(*)
========
1,000,000 (1M)

select count(*) from category
count(*)
========
250,000 (500K)

select count(*) from product_category
count(*)
========
125,431,192 (125M)

select
 c.*,
 p.*
from
 product_category pc
inner join category c on pc.cat_id = c.cat_id
inner join product p on pc.prod_id = p.prod_id
where
 pc.cat_id = 1001;
0:00:00.030: Query OK (0.03 secs)

答案 2 :(得分:2)

正确索引数据库将是提高性能的第一种方法。我曾经有一个查询花了半个小时(在一个大型数据集上,但也是如此)。然后我们发现表没有索引。索引后,查询花费的时间不到10秒。

答案 3 :(得分:1)

为什么需要具有此表结构。我的基本问题是,每次要使用它时,您都必须将数据转换为属性值。这在我看来是不好的 - 因为无论如何,将数字存储为文本是疯狂的。例如,你将如何获得必填字段?或者需要基于其他字段的约束的字段?例如开始和结束日期?

为什么不简单地将属性作为字段而不是多对多关系?

有1张平台。当您的业务规则开始显示应该对属性进行分组时,您可以考虑将它们移出到其他表中,并与users表有几个1:0-1的关系。但这不是规范化,并且由于额外的连接会稍微降低性能(但是表名的自我记录性质将极大地帮助任何开发人员)

我经常看到databqase性能被完全阉割的一种方法是使用泛型

Id,属性类型,属性名称,属性值表。

这是非常懒惰但非常灵活但完全杀死了性能。事实上,在性能不好的新工作中,我实际上会问他们是否有一个具有这种结构的表 - 它总是成为数据库的中心点而且速度很慢。关系数据库设计的关键在于提前确定关系。这只是一种旨在以巨大的应用速度成本加速开发的技术。它还非常依赖应用程序层中的业务逻辑来表现 - 这根本不是防御性的。最终你会发现你想在关键关系中使用属性,导致连接上的所有类型的转换,这进一步降低了性能。

如果数据与实体的关系为1:1,那么它应该是同一个表中的一个字段。如果你的表格超过30个字段,那么考虑将它们移动到另一个表中,但不要将其称为规范化,因为它不是。这是一种技术,可以帮助开发人员以牺牲性能为代价将字段组合在一起,以帮助理解。

我不知道mysql是否有等价但sqlserver 2008有稀疏列 - 空值不占用空间。 SParse column datatypes

我不是说EAV方法总是错误的,但我认为使用关系数据库来实现这种方法可能不是最佳选择。