中间件分表是不是一个好的主意?通过中间件来对MYSQL的数据进行分表是一个常见的对于大数量的解决的方案,通过中间件将应用的数据在中间层进行路由,通过路由将一张表的数据,映射到不同物理数据库上的表,通过应用设计的分片键将数据根据规则存储在不同的物理服务器上。实际上分布式数据库的基本原理也是这样。
至于说这是不是一个好的注意,下面想根据不同的层面来看看,分表的方式本身是不是一个好的方式。
分表的起因主要由三点组成 (基于MYSQL数据库)
1 数据量大,单体数据库无法承载单表的数据量
2 数据量大,数据访问出现在优化后,数据访问缓慢的问题,数据写入性能的问题等等
3 单体数据库在大数据量后的运维难度提高,如备份,进行DDL操纵 等等这些问题
4 单体数据库在硬件上无法进行垂直化的升级和提升
反观,SQL SERVER , PG, ORACLE 等数据库在之前基本上是没有分表这么一说的,主要还是这些数据库本身单体可以承载更大的数据量和运维的需求。
在分表后,我们解决了单体MYSQL无法解决的一些问题,那么这是一个好主意吗? 这里且不武断的评判这是不是一个好的注意,我们看看在我们分库分表后,我们会遇到什么其他的问题。
1 数据查询的问题
上面提到,数据在分表后,是需要指定分片键来对数据进行存储和查询的,在数据查询的过程中,如果查询的语句中没有分片键的信息,那么数据查询本身是要通过扫描全体分表后,在给出数据结果的。显然数据查询会比在单体数据库上更慢。
分表本身必须在特定的查询模式的情况下,有利于数据查询性能的提高,如果无法达到之前预先的设计要求的查询,查询的速度会更慢。
2 应用程序编制的难度提高
上面提到了由于分表后数据分散在不同的数据库物理服务器,一些之前可以运行的查询,尤其JOIN 的一些查询,在分表的服务器上无法正常进行,或性能低下,尤其是两张分表后的JOIN 查询。这就要求应用程序本身,需要将复杂的JOIN表查询,拆分,拆成简单的SQL 语句,在通过多次的访问,或许本来可以一条SQL 就可以完成的语句。提高数据访问的频次,以及应用程序获取数据的难度。
3 运维难度和成本的大幅度提高
原先一台服务器上可以进行运维的数据表,现在分布到不同的物理服务器上,运维的成本会大大提高。
1 物理服务器的成本,单台的物理服务器成本,对应N台物理服务器的成本
2 数据库服务器中的数据备份的问题,单体数据库备份中可以采用PXB的方式进行物理范式的备份和数据恢复,速度较快,相关自动化脚本也比较好编写,分表后,数据备份中会遇到第一个挑战就是数据的备份的一致性,通过逻辑备份可以满足一致性的数据表备份的问题,但又保证不了数据备份中的性能的问题,本来就要解决数据库性能的问题,而大表在数据备份中逻辑备份保证不了性能。通过PXB的方式备份分表的数据库,就需要提供多点中的数据增量备份,来解决多解决数据恢复中的事务一致性的问题。本身的数据备份和恢复的难度明显提高。
3 中间件单点的问题,虽然数据库可以在数据存储方面进行高可用的设计,但中间件单点的问题就没有那么好解决了
4 分片键设计的局限性,分片键一般选择的方式主要有两大类,range的方式和hash的方式,这两种方式分别对应不同的业务类型,在业务转换后,分片的方式并不能改变,可能就会涉及数据的在迁移等等问题。
5 一些特殊语句的执行的性能问题难以解决,这类查询如count() , distinct ,order by 等查询,在中间件上通过对每个数据库表进行扫描的方式进行累加或排除的方式,操作时的性能问题突出,并很难解决。
综上,分表本身是不是一个好主意,如果是一个系统建立之初,业务不稳定,数据量不确定的情况下,贸然采用分表的方式,可能不是适用,而在业务稳定后,再次进行改造,会解决部分上面提到的一些问题,至少那时你的分片键用哪个基本上是可以确定的。