基于MYSQL的开发已经形成了很明细的开发规范,很容易在网上能查询到相关的MYSQL 开发的军规等信息。 实际上即使掌握了军规等,对于MYSQL上的应用开发就100%的稳妥了吗?
实际上很多情况下,量变产生质变,所以理解为什么产生这些军规铁律与怎么能在开发中更方便的应用这些开发技巧就变得很重要了。
1 大数据量的情况下,不分库分表,直接进行数据的单表处理
基于MYSQL的数据库在处理上,在数据量单表较大的情况下,会进行分表,分表的原因在哪里。
1.1 单表数据承载量大,导致数据查询的效率在单表的情况下,降低,同时大表本身产生的索引,在查询时是需要放入到innodb_buffer_pool 中的,多个表放入到内存 和 单表放入到内存中在内存充足的情况下,多表的效率会更高,更有效的利用多核心的CPU 和 多个线程来处理数据,有效的利用了硬件的资源。
以下面的图为例,如果我要找到标黑的数据页面,一张大表本身数据可能需要扫描到更下层,而如果进行了分库的情况下,数据打散了,并且数据提取不用去更深的层次去提取,并且还可以利用多个CPU 在多个表查询数据,并汇总后产生整体的要的数据,提高了并行工作的能力。
这才是分表的提高性能的原因之一
不分表
分表
2 主键的问题
主键为什么越小越好
1 在查询中如果需要回表的话,那么必然会使用主键,主键是必须驻留在内存中的,那么越小的信息驻留在内存中,对于节省内存和查找速度都是一个有利的部分。
2 主键应该是有顺序的,雪花算法随机性的方案,不应该在MYSQL 中使用,对于数据的插入性能的损耗较大
3 唯一索引的设计问题
唯一索引在MYSQL 中不建议存在多个唯一索引,并且唯一索引也不建议多个字段联合进行处理。唯一索引的插入会在高并发的系统中出现频发的死锁,具体请参见, 所以对于唯一索引的使用,尽量一个表只有一个,并且只有一个字段 ,可以适当的改变设计,将多个字段的唯一索引设计改为hash 的方式来处理唯一索引。
MYSQL VS POLARDB 唯一索引死锁与应用设计 (qq.com)
3 基于表设计的问题
表设计基于MYSQL中会存在如下的一些尽量避免的问题
1 在表中插入大字段,如varchar(500)以上的字段,我们可以计算一下,基于 mysql 的一个字符是几个字节, 基于MYSQL 8 UTF8MB4 4个字节 * 500 = 2000个字节,那么一个行 65535字节 是一行最大的限制,实际上 65532是一行的限制,64K ,那么一行 最大可以支持 4个页面,
之前我们在对POLARDB 和 MYSQL RDS 进行了数据压力的测试,在测试中我们明显发现一个规律,就是字段越大,这样的字段越多,查询的效率越低,在增加一倍的长度的字段的情况下,对比标准的字段的数量和长度,查询延迟在标准的 2-4倍。
所以一行的数据占用的字节越大,查询越慢这是可以被测试验证的。
2 表是宽表还是 join 的方式来组织业务表
实际上这并不是一个选择题,这是一个平衡值,任何一个极端都不是一个好的选择,超宽表对于后续的数据的修改是一个问题,如果是一个业务表,这样的设计在查询和修改中,并且高并发的情况下,出现block 的情况会较多,性能并不会特别好。
而如果将这些数据分成多个表,那么这些表在提取数据时,又会产生多表关联查询,并产生对应的锁,同样查询频率高,修改数据库会产生死锁的可能性也会提高。
所以更巧妙的业务逻辑设计在表中的体现是重要的,比如将数据进行拆分,静态数据和动态数据 ,实际上就是将不经常被提起的数据单独放到一个表,而热数据放到一个表,并且热的数据可以通过业务逻辑的拆分,在分成多个表,降低在同一时刻对一个表中的行数据进行大量修改和查询的可能性,从而避免高并发的情况下,产生BLOCK 和 DEAD LOCK 的可能性。
同时基于某些查询进行读写分离也是一个好的方法,也是将写入和查询进行分离的方式,解决BLOCK 和 DEADLOCK 的问题的一种方式。
所以基于POLARDB 的代理模式,设置好了,的确可以降低发生死锁和BLOCK的情况。
所以结论是,宽表和JOIN 多表的方式,没有统一的标准,但可以建立一个看上去符合常理的标准。例如 表中的字段 VARCHAR(500)的不能超过 3个 ,JSON 数据的处理尽量使用MONGODB 来处理。
所以总结一个看似是结论的结论,MYSQL 处理业务变动的数据字段,以及业务数据,小型字段,是一个好的数据库。
3 查询的方式与UPDATE 方式
查询的方式尽量使用主键来操作,看上去有点麻烦,尤其针对UPDATE 操作,先查询出要更改数据的行的 PRIMARY KEY 在进行UPDATE 操作条件为这个行的主键。
大多数数据库都不会提出这样的要求,而这样的需求还是针对高频的更新和查询在MYSQL 中而言, 还是尽量提高更新的速度,解耦UDPATE 中的操作的事务大小,尤其针对多表的查询后的更新数据的情况。
数据更新中,要控制一次更新的数据量,不能一次批量更新太多行,如10万行以上的数据量,都要开始小心。可以分批的进行数据的更新,这点也是需要理解的,这样操作可以降低内存的使用,提高数据库在更新大量数据时的安全性。
4 不进行业务划分 使用MYSQL
这基本上是基于ORACLE 的使用方式而进化的想法,就是微服务分了很多,但在数据库上耦合了,多个数据库,在一个MYSQL的实例上,并且甚至在一个数据库上多个微服务的表在一个database中,这不是使用MYSQL 的方式, MYSQL 的使用方式 是 小而美 ,而不是大而全。
当然如果非要如此,考虑一下 POLARDB 可以解决部分问题。
5 索引无计划进行建立
这点问题也是在很多机遇MYSQL的数据库中频发的,ORACLE 有避免重复建立索引的机制,而MYSQL 数据库并不会控制重复索引的建立,并且过多的索引对于MYSQL 的数据的 DML ,INSERT 操作都是性能消耗和引起性能低下的因素之一。
写到这里,可以进行总结到底那些设计对于MYSQL 是不友好的
首先针对MYSQL 的使用中,没有进行业务的逻辑梳理,直接将众多的表不进行分析,数据量,业务并发量,以及查询模式等,就直接将这些表和数据统统塞入到一个 MYSQL ,然后这写表中的设计 ,要不就是逻辑分表太碎,导致查询一个数据库需要多个表才能提取数据,或者一个数据表被设计成宽表,导致这个表被高频的查询,DML,INSERT 导致严重的BLOCK 的问题,同时 过多的并发导致数据库资源消耗异常,导致MYSQL 使用了超大的 内存 和 CPU 使得 MYSQL 的使用方式越来越像 ORACLE ,同时不注意索引的设计,重复索引增加,导致一个表本身的数据比索引还小,查询中将OLAP的操作也集中到数据库中操作,引起 OLAP OLTP 的性能争抢问题,互相影响。
以上的就是一个非常糟糕的开发方式,当然还可以添加一条,在复杂的项目中,只使用MYSQL 数据库,也是糟糕的开始。