当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下:
限定数据的范围
务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以 控制在一个月的范围内;
读/写分离
经典的数据库拆分方案,主库负责写,从库负责读;
垂直分区
根据数据库里面数据表的相关性进行拆分。 例如,用户表中既有用户的登录信息又有用户的基本信息, 可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。
简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。 如下图所示,这样来说大 家应该就更容易理解了
垂直拆分的优点: 可以使得列数据变小
,在查询时减少读取的Block数
,减少I/O次数
。此外,垂直分区可以简化表的结构,易于维护。
垂直拆分的缺点: 主键会出现冗余
,需要管理冗余列
,并会引起Join
操作,可以通过在应用层进行 Join来解决。此外,垂直分区会让事务变得更加复杂
;
保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了 分布式的目的。 水平拆分可以支撑非常大的数据量。
水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成 多张表来存放。举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据 量过大对性能造成影响。
水平拆分可以支持非常大的数据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题
,但由于表的数据还是在同一台机器上,其实对于提升MySQL并发能力没有什么意义,所以水平拆分最好 分库 。
水平拆分能够支持非常大的数据量存储,应用端改造也少,但分片事务难以解决 ,跨节点Join性能较差,逻辑复杂。《Java工程师修炼之道》的作者推荐尽量不要对数据进行分片
,因为拆分会带来逻辑
、 部署
、运维
的各种复杂度 ,一般的数据表在优化得当的情况下支撑千万以下的数据量是没有太大问题的。如果实在要分片,尽量选择客户端分片架构
,这样可以减少一次和中间件的网络I/O。
下面补充一下数据库分片
的两种常见方案:
因为要是分成多个表之后,每个表都是从 1 开始累加,这样是不对的,我们需要一个全局唯一的 id 来 支持。
生成全局 id 有下面这几种方式 :
UUID:不适合作为主键,因为太长了,并且无序不可读,查询效率低。比较适合用于生成唯一的名字 的标示比如文件的名字。
数据库自增 id : 两台数据库分别设置不同步长,生成不重复ID的策略来实现高可用。这种方式生成的 id 有序,但是需要独立部署数据库实例,成本高,还会有性能瓶颈。
利用 redis 生成 id : 性能比较好,灵活方便,不依赖于数据库。但是,引入了新的组件造成系统更加复杂
,可用性降低,编码更加复杂,增加了系统成本。
Twitter的snowflake算法 :Github 地址:https://github.com/twitter-archive/snowflake。
美团的Leaf分布式ID生成系统 :Leaf 是美团开源的分布式ID生成器,能保证全局唯一性、趋势递增、 单调递增、信息安全,里面也提到了几种分布式方案的对比,但也需要依赖关系数据库、Zookeeper等 中间件。感觉还不错。
美团技术团队的一篇文章:https://tech.meituan.com/2017/04/21/mt-leaf.html
一组为了完成特定功能的 SQL 语句集,存储在数据库中,经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据 库中的一个重要对象。
查找语句尽量不要放在循环内
触发器是一段能自动执行的程序,是一种特殊的存储过程, 触发器和普通的存储过程的区别是:触发器 是当对某一个表进行操作时触发。 诸如: update、 insert、 delete 这些操作的时候,系统会自动调用 执行该表上对应的触发器。 SQL Server 2005 中触发器可以分为两类: DML 触发器和DDL 触发器,其 中 DDL 触发器它们会影响多种数据定义语言语句而激发,这些语句有 create、alter、 drop 语句。
并发控制一般采用三种方法,分别是乐观锁和悲观锁以及时间戳。
共有 5 种类型的表格:
MyISAM:
不支持事务,但是每次查询都是原子的;
支持表级锁,即每次操作是对整个表加锁; 存储表的总行数;
一个 MYISAM 表有三个文件:索引文件、表结构文件、数据文件;
采用菲聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引 基本一致,但是辅索引不用保证唯一性。
InnoDb:
支持 ACID
的事务,支持事务的四种隔离级别
; 支持行级锁及外键约束:因此可以支持写并发;
不存储总行数:
一个 InnoDb 引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多 个文件里),也有可能为多个(设置为独立表空,表大小受操作系统文件大小限制,一般为 2G),受 操作系统文件大小的限制;
主键索引采用聚集索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅 索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时, 为维持 B+树结构,文件的大调整。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。