Chr*_*eld 5 mysql database-design partitioning database-partitioning
我们有一个带有20多个列的表的应用程序,这些列都是可搜索的.为所有这些列构建索引会使写入查询变得非常缓慢; 任何真正有用的索引通常必须跨越多列,增加所需的索引数量.
但是,对于这些搜索中的95%,只需搜索这些行中的一小部分,而且数量相当少 - 比如50,000行.
因此,我们考虑使用mySQL分区表 - 有一个列基本上isActive
就是我们将两个分区划分的列.大多数搜索查询都将运行isActive=1
.然后,大多数查询将针对小型50,000行分区运行,并且在没有其他索引的情况下快速运行.
唯一的问题是isActive=1
没有固定的行; 即它不是基于行的日期或任何固定的那样; 我们需要isActive
根据该行中数据的使用情况进行更新.据我所知,这不是问题; 在UPDATE查询期间,数据只会从一个分区移动到另一个分区.
我们有一个PK
对id
的,虽然该行; 我不确定这是不是一个问题; 手册似乎暗示分区必须基于任何主键.这对我们来说将是一个巨大的问题,因为主键ID没有依据是否行isActive
.
我不是MySQL专家.我的重点是Oracle,但我一直在使用分区多年,我发现你的建议用途非常合适,但不是主流对分区的理解.
暂且不谈索引合并.假设您的活动行有点分散,并且与非活动行数的比率为1:20.假设您的页面大小为8Kb,每个块大约需要20行.如果您获得非常均匀的isactive记录分布,那么每个块几乎会有1个.读取表中的每个块/页面的全表扫描将比使用索引查找相同的行要快得多.
所以我们说它们集中而不是均匀分散.即使它们集中在20%的页面甚至10%的页面中,即使在这些情况下,全表扫描也可以执行索引.
所以现在包括索引合并.如果在扫描ISactive的索引之后并且您没有访问该表但是将这些结果加入到另一个索引的结果中,并且最终结果集将产生读数,例如,小于块的5%.然后是,并且isactive和索引合并的索引可能是一个解决方案.
需要注意的是,MySQL中索引连接的实现存在很多限制.确保这适用于您的情况.但是你说你还有20个可以搜索的字段.因此,如果您没有为所有这些索引编制索引,以便有可用的第二个索引来加入IsActive索引,那么您将不会使用索引合并/连接.
现在,如果你对该列进行分区,那么你将拥有5%的IsActive = True的块,并且它们将被密集打包.完整分区扫描将快速生成活动记录列表,并允许将每个其他谓词应用为过滤器而不是索引搜索.
但那个标志发生了变化,对吧.
在Oracle中,我们有一个允许我们启用行迁移的命令.这意味着,当Is_Active从True更改为False时,移动该行所在的分区.这非常昂贵,但只比索引维护时更多,如果您索引该列而不是通过它进行分区.在分区示例中.Oracle首先使用更新更改行,然后执行删除操作,然后执行插入操作.如果您为该列编制索引,则会对该行进行更新,然后删除TRUE的索引条目,然后创建False的索引条目.
如果MySQL没有行迁移,那么你必须对你的crud包进行编程才能做到这一点.UPDATE_ROW_ISACTIVE(pk IN number)程序<----类似的东西)将为您执行删除和插入.
关于Konerak的答案
虽然我同意并行访问是分区的一种用法,但它并不是唯一的.但是,如果您按照他提供的链接,页面最底部的用户评论是:
小心你的桌子上有低选择性索引.如果将Index_Merge优化与intersect()算法一起使用,复杂的AND/OR WHERE子句肯定会使查询非常慢.
这似乎与你的情况有关,所以你可以接受FWIW的评论.