数据库分区。我认为这是数据库存储结构的一个“伟大”概念。如果程序员(不是专业的DBA)关注表结构本身,分区可能是最接近底层的数据库设计需要关注。比如数据库的表空间这样的概念,平时普通的开发者可能不会关注。但分区概念不同,因为它与应用场景的结合更紧密。比如按时间、按地区、按类别等。我猜很多人不同意数据库分区是一个“伟大”的概念。原因是看了市面上各种主流数据库的书籍。入门级的像《XX数据库从入门到删库跑路》,高端的像《XX数据库的技术内幕》。大部分书籍在介绍分区的内容时,都没有给出很大的篇幅。.甚至在好几本书中,都是这么简单:对于一个大表,每次查找都要扫描整张表,耗费大量时间。如果是分区的,就访问某个分区。很快。这不是误导吗?分区真的可以这么简单明了吗?我想当然不是,所以这篇文章的内容就是说说我认为分区的重要性和伟大之处。1、为什么要对数据库进行分区?《孙子兵法》的第五篇——《兵势篇》中,孙子说:“凡治众者,如治少数者,分也。”斗众如斗寡妇,就是这个样子。说句人话:管理大数据库表和管理小数据库表一样,分区即可;充分利用所有隔断的功能,与充分发挥其中一个隔断的作用是一样的。它们可以有一个统一的表名,可以使用统一的SQL语句进行调度。上面的段落可以分为上句和下句,用分号隔开。那么“伟大”是在前半句还是后半句呢?显然是下半场。为什么?你分人容易,但是你要像一个人一样去指挥广大的分人,这事就大了。1.最好考虑隔离和瓶颈。先讨论一下前半句,分而治之的思想。我经常遇到这样的对话场景。场景一:对话者:“我们的数据太大了,我们分表吧!”我:“为什么不使用分区?”对话者:“分区能解决吗?”(请弥补不信任的眼神和疑惑的语气)场景二:演讲者:“我们考虑用最先进的分库技术理念来解决这个瓶颈。”所有人都投来羡慕和崇拜的目光,等待着大神来出一个华丽而牛逼的方案。我:“这里有一个瓶颈,我们需要对这张表进行分区。”众人不屑一顾,不辞而别,好,分吧。其实无论是分区、分表还是分库,我们都需要关注两个重要的概念,一个是隔离,一个是瓶颈。第一种场景,用户为什么需要分表?常见的情况,比如我的两张表虽然结构一样,但是一张是北京的数据,一张是上海的数据。如果北京的数据坏了,或者我对北京的数据进行了奇怪的操作,我需要对上海的数据完全没有影响。这就是所谓的隔离。再比如,可能是全国数据量太大,交易量太大,磁盘、IO、网络、CPU等都可能支撑不住。这就是所谓的瓶颈。分区、分表、分库满足不同的隔离级别,解决不同的瓶颈。但是,他们的想法非常接近。2.Partition和Sharding这个词Sharding(通常译为sharding)可以说是有着自己高贵的属性。每当和别人讨论数据库技术的时候,谈到Sharding,自然有一种上档次的感觉。而且它有很多好朋友,个个都华丽无比,分布式、集群、大数据等等。Partition这个词,虽然从很多角度来看,都和Sharding很像,或者说都是出自“分也”的概念。但它只是感觉很低。为什么?根据我的理解,因为Partition的实现是由DBMS完成的,所以用户感觉不到。但是Sharding往往需要程序、设计模式,甚至整个架构的设计都围绕着它服务,存在感很强。它们在实际使用中有区别吗?当然有!那么什么时候用Sharding,什么时候用Partition呢?我个人认为使用Sharding有两种情况。第一个是没钱的时候,第二个是Partition用***的时候,不确定。那么Partition什么时候可以失败呢?有两种,一种是没钱的时候,第二种是超过世界硬件限制的时候(忍不住买最贵的装备)。1)当我们没钱的时候,仔细想想就会发现,分库分表的套路用的最多的是哪个数据库?或者你在哪里看到更多?我认为它通常指的是同一个地方,叫做MySQL。虽然它有各种华丽的马甲,比如腾讯的TDSQL。为什么要使用MySQL?因为开源是免费的。什么?InnoDB也很强大?如果Oracle明天开源免费,你在选机型的时候还会选择MySQL吗?还别说,为什么MySQL要分库分表那么多?我认为真相只有这一个。因为在5.1版本之前,MySQL不支持分区。这是我提到的第一种情况。当我没钱的时候,我买不起Oracle、SQLServer和DB2。好了,下个空闲的MySQL,做分库分表。抛开玩笑的内容,还有Partition解决不了瓶颈,需要分库分表的时候。但是,一个成熟的数据库用户不应该滥用分库分表。这就是DBA界所谓的数据库细分铁律,我非常认同。那么,说说第二种,Partition使用***的场景。2)超过当前硬件限制简单来说,我买了一个Oracle,但是我的系统TPS是10000。在X86上运行Oracle,不支持怎么办?那么有两个出路,第一个,了解Exadata?购买IBM大型机?买不起,好吧,我们在MySQL或者X86上用Oracle做分库分表,这就是第二类没钱的时候。还有一个就是Exadata和IBM的大型机都支持不了,所谓超越地球技术产品的极限,反正我没见过。3、看到这里分库分表分区的使用场景,是不是觉得废话太多了。分区情况如何?分表是什么情况?什么时候分库?还是那句话,首先要看隔离级别,其次要看瓶颈。上一段主要讲了瓶颈场景,那么隔离级别呢?1)分库选取两个结构相同的数据。但他属于两个客户。客户说,我有监管要求,我不能把数据和别人的数据放在一起。必须绝对隔离,并有严格的访问控制。其他人根本无法登录我的数据库服务器。这就要求数据在数据库层面是完全分离的,可以使用分库。2)分表选择如果我是云商,有两个客户使用我的客户,他们各自有自己的用户(Schema),允许与他人共享数据库服务器,但严禁他人使用属于他的数据库表。那么这个时候,就可以分表了。3)如果选择分区,两个数据需要简单隔离,相互处理互不影响。有时候,我也希望一个用户可以用一条SQL来比较分析他们的差异。这时候分区就是最好的选择。2.数字数据库分区的优点接下来,我们将讨论本章的后半部分。1、在划分的同时,应对技术壁垒。这句话说起来简单,执行起来可就没那么简单了。在主流的DBMS中,不同的分区代表不同的对象(比如Oracle中DB2分区表的不同段、不同分区对应数据文件)。不夸张的说,很多数据库中间件产品都是反复纠结和反复实现的,这本身就是主流DBMS在分区时必须应对的技术壁垒。比如:跨库SQL改写,一个运行在分布式场景下的SQL,需要通过中间件改写成多条SQL,丢给多个库执行。特别是跨库联动和聚合(包括Max、Min、Sum、Count)。事实上,当有多个分区时,也会出现这样的问题。如果说到这个问题,开发者是不容易关注的。另一个例子:全局/本地索引。在DBMS中,全局索引通常是通过设计来避免的。一般数据表一旦分区,就意味着数据量比较大。比如最常见的B-tree索引,全局索引意味着索引层级多,查询速度慢。但不管怎样,当我在查询的时候,分区KEY发不进去,全局索引永远是最好的选择。在分布式场景下,如果没有分库key会很尴尬。要么无法检查,要么必须遍历所有库。这个成本几乎是无法接受的。2、分区和优化密不可分。分区和分库面临的很多问题有巨大的相似性。开发者总是关注分库面临的问题和困难,却普遍低估了分区可能带来的副作用。经常有人质疑,数据太多了,为什么不加分区!?并发冲突,为什么不加分区!?程序速度慢,为什么不加分区!?PS:这一系列问题同样适用于Whynotindextheseries。这种轻视源于主流的DBMS系统对分区功能的支持非常好。作为一个DBA,我比较怕的是有人对数据库有点了解,而且特别有信心站在自己的立场上和我讨论。一些开发人员向我传递了一个概念,即分区越多越好。只要使用分区,它可以更快,至少不能更差!开发人员在谈论这些时非常有信心。其实在我看来,分区设计和查询优化是息息相关的。分区设计必须匹配特定的查询场景才能达到好的效果。比如上面提到的不带分区列的查询,需要逐个遍历每个分区,再比如Hash分区后的范围搜索。Oracle中索引的Hash分区在大规模、高并发插入的数据库表中非常常见,因为这种场景下非常容易发生冲突。使用Hash分区后,可以大大缓解。但是,这也挖了一个坑,就是在这个索引上的范围搜索变得不太理想。由此可以推断,分区上可能遇到的大坑其实都是用在了分库的场景中。比如做分库后,发现事务的业务场景无法获取到ShardingKey。使用Hash算法计算出ShardingKey,突然发现有笔交易需要查ShardingKey,这样我可能要在各个库里转悠了。分区所面临的陷阱在分库场景下可以说是被大大放大了。因此,不能随意滥用分区,更不能随意分库。3、容错率提高反过来说,为什么一开始说分区很大,尤其是Oracle。你违背了各种优化原则之后,做了NPI,做了跨分区JOIN等等。尽管性能上有所损失,但数据库还是会为您完成复杂的工作。当你的需求不是实时响应,这些奇怪的跨分区问题要解决的时候,Rdbms仍然透明地为你完成工作,怎么能不说它很棒呢?我想那些开发分布式数据库中间件的人最能认同。3.写在****写到这里,作为一个DBA,特别希望能给程序开发者传递一个理念,那就是这个世界上一定没有完美的优化方案。你想要一个可以高并发插入,可以做各种高效查询的表。一时局限,一时迷离。可以说,这是不可能的。所有优化方案都以牺牲一种性能换取另一种性能。DBA的职责是弄清楚业务需要什么,不需要什么。牺牲不需要的功能来换取需要的功能,甚至牺牲不常用的功能来换取优秀的常用功能。这其实是最好的解决方案,分区也不例外。在本文的最后,我想留下一个一直困扰着我的问题。看了无数分库分表拼凑的文章和帖子后,我开始怀疑人生了。作者介绍宇文占全,现任金融行业核心业务系统DBA,主要参与Oracle、DB2、Cassandra等数据库的开发。
