数据分区
数据分区的含义有很多种。在本节中,它表示将数据根据其中的某些键划分到不同的数据段中,通常为了利用多个数据库来存储更大规模的数据集合,或者获得比单个数据库更高的访问速度。
数据分区还有其他的类型(例如,之前提到的功能性分区),但是,在本节中,我们只关注基于键的数据分区策略。
举一个简单的数据分区示例,即将某个应用程序的所有数据按照账号进行分区。这样所有账户名称由A~D开头的数据被划分到一个数据库中,所有账户名称由E~K开头的数据被划分到另一个数据库中,以此类推(如图4-1所示)。[1]这是一个非常简单的例子,但是应用程序的开发人员通常会采用数据分区技术,来大幅提升可以访问应用程序的用户并发数量,同时支持更大规模的数据量。
图4-1:根据账户名称进行数据分区的示例
一般来说,你应当尽可能避免使用数据分区。为什么?因为一旦像这样对数据进行分区,就可能遇到以下这些问题。
应用程序复杂性
增加了应用程序的复杂性。因为从现在开始,你在实际获取数据之前,需要先去计算数据存放在哪里。
跨分区查询
无法很容易地获取多个分区中的数据。这一点在做业务数据分析查询时非常有用。
分区使用倾斜
需要很谨慎地选择建立分区所依赖的分区键。如果你选择了错误的键,那么就可能导致数据库分区使用不均衡,某些分区使用频繁而其他分区很少被使用,这样不仅会降低分区的有效性,同时也会增加数据库管理和维护的复杂性,如图4-2所示。
图4-2:账户超出数据分区能力的示例
重新分区
需要偶尔进行重分区来平衡分区之间的数据。根据选择的分区键和数据集合的类型、体量不同,重分区可能变得非常困难、非常危险(数据迁移),甚至在某些时候,几乎无法实现。
一般来说,账户名和账户ID都不是好的分区键(虽然它们经常被作为分区键使用)。这是因为一个账户的数据体量可能会发生变化。它开始时可能很小,适合分配在一个存放大量小账号的分区中。但是,如果随着时间推移,它变得越来越大,很快会因为单个分区无法承载压力,所以你不得不重新进行分区,来更好地平衡账户数据。如果一个账号变得太大,甚至超过单个分区的容量,就会导致整个分区方案失败,即使是重分区也无法解决这个问题。
更好的分区键应该是大小尽可能保持固定的键。分区数量增长应当尽可能保持独立和一致,如图4-3所示。如果需要重分区,应该是所有的分区都一致地增长,因为分区数据量太大以至于无法处理所以才重新分配分区。
图4-3:数据保持一致增长的分区示例
实际中可能会用到的分区方案是,选择一个会产生大量小元素的分区键,然后将这些小分区映射到一个更大的分区数据库中。以后如果需要重分区,只需更新映射关系,将个别小元素移动到新的分区中即可,这样就避免了对整个系统的大范围重分区。如何选择和使用适当的分区键本身就是一门艺术。