存储引擎--MyISAM和InnoDB的区别
使用场景
对比
MySQL隔离级别--未提交读,提交读,可重复读,序列化
隔离级别含义
隔离级别 | 英文名称 | 含义 | 脏读 | 不可重复读 | 幻读 |
未提交读 | READ UNCOMMITTED | 可读取其它事务未提交的结果 | √ | √ | √ |
提交读 | READ COMMITTED | 一个事务开始时,只能读到其他事务已经提交的修改。 例:如果A事务已经修改了XX,但还没提交,则B事务读XX时还是未修改的值。 (Oracle等多数数据库默认是该级别)。 | × | √ | √ |
可重复读 | REPEATABLE READ | 在开启事务时,同一条件的查询返回的结果是一样的。 例:A事务开启,查询一条记录;B事务更新这条记录并提交,A事务再次查询这条记录(查到的结果跟第一次查到的一样,而不是B修改过的结果)。 (MySQL默认级别) | × | × | √ |
可序列化 | SERIALIZABLE
| 当一个事务执行时,会对所涉及的数据行进行加锁,其他事务无法对这些数据行进行修改或读取,直到当前事务提交或回滚。 | × | × | × |
脏读、不可重复读、幻读的含义
索引的分类
索引的优点/缺点
优点
索引优点就是提高了查询性能,主要是以下几个方面
- 索引大大减少了服务器需要扫描的数据量。
- 索引可以帮助服务器避免排序和临时表。
- 索引可以将随机I/O 变为顺序I/O
缺点
- 降低了数据写入的效率。原因:当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护
- 索引增加了查询优化器的选择时间。查询优化器在对一条sql语句进行分析时,会结合一系列的分析计算出一条最优的查询sql。添加了索引之后,相当于是在原来的基础上,添加了对索引因素的分析,若在很多字段上创建了索引,会增加这个选择的时间。
- 索引占物理空间。除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
创建索引的原则
索引原则 | 说明/示例 |
对查询频率高的字段创建索引 | 查询频率高的字段有:作为查询条件的字段(where子句中的列)、连接子句中指定的列 |
为经常需要排序、分组和联合操作的字段建立索引 | 经常需要ORDER BY、GROUP BY、DISTINCT和UNION等操作的字段,排序操作会浪费很多时间。 如果为其建立索引,可以有效地避免排序操作。 |
尽量使用唯一索引 | 唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。 唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。 |
使用短索引 | 如果索引的值很长,那么查询的速度会受到影响。例如,对一个CHAR(100)类型的字段进行全文检索需要的时间肯定要比对CHAR(10)类型的字段需要的时间要多。 |
使用前缀来索引 | 如果索引字段的值很长,最好使用值的前缀来索引。例如,TEXT和BLOG类型的字段,进行全文检索会很浪费时间。如果只检索字段的前面的若干个字符,这样可以提高检索速度。 |
索引的数目不要太多 | 过多的索引会导致insert、update、delete语句的执行效率降低; 每创建一个索引都会占用相应的物理空间; |
对查询频率高的字段创建索引 | 查询频率高的字段有:作为查询条件的字段(where子句中的列)、连接子句中指定的列 |
对查询频率高的字段创建索引 | 查询频率高的字段有:作为查询条件的字段(where子句中的列)、连接子句中指定的列 |
索引失效的原因/解决方案
联合索引--使用/原理/优化
使用联合索引可以做到覆盖索引,从而避免会表查询。举个例子,从user表中查询用户id,姓名和性别,查询条件为姓名,这时候就可以对用户姓名和性别创建联合索引,这样可以做到覆盖查询和避免会表查询。
另一个场景是,如果存在多个查询条件,针对于查询字段建立联合索引,可以提高多个查询条件组合的查询性能。
索引的优化--LIKE模糊查询
聚集索引/辅助索引/回表查询/覆盖索引
回表查询,先查询辅组索引,再查询聚集索引。
覆盖索引,只用查询辅组索引或者聚集索引。
尽量将回表查询转换为覆盖查询,转换的方法为对要查询的字段建立联合索引,从而避免回表查询。
分库分表--垂直分表与水平分表
垂直(纵向)切分
垂直分库就是根据业务耦合性,将关联度低的不同表存储在不同的数据库,如下图。
垂直分表是基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不经常用或字段长度较大的字段拆分出去到扩展表中。
在字段很多的情况下(例如一个大表有100多个字段),通过"大表拆小表",更便于开发与维护,也能避免跨页问题,MySQL底层是通过数据页存储的,一条记录占用空间过大会导致跨页,造成额外的性能开销。
另外数据库以行为单位将数据加载到内存中,这样表中字段长度较短且访问频率较高,内存能加载更多的数据,命中率更高,减少了磁盘IO,从而提升了数据库性能。如下图。
优缺点
优点:
解决业务系统层面的耦合,业务清晰
与微服务的治理类似,也能对不同业务的数据进行分级管理、维护、监控、扩展等
高并发场景下,垂直切分一定程度的提升IO、数据库连接数、单机硬件资源的瓶颈
缺点:
部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度
分布式事务处理复杂
依然存在单表数据量过大的问题(需要水平切分)
水平(横向)切分
- 切分时机:当一个应用难以再细粒度的垂直切分,或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平切分了。
- 分类:水平切分分为库内分表和分库分表,是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。库内分表只解决了单一表数据量过大的问题,但没有将表分布到不同机器的库上,因此对于减轻MySQL数据库的压力来说,帮助不是很大,大家还是竞争同一个物理机的CPU、内存、网络IO,最好通过分库分表来解决。
优缺点
水平分库优点:
- 不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力
-
应用端改造较小,不需要拆分业务模块
水平分库缺点:
-
跨分片的事务一致性难以保证
-
跨库的join关联查询性能较差
-
数据多次扩展难度和维护量极大
分片规则
- 取余/取模
- 均匀存放数据
- 缺点: 不能扩容
- 按照数量范围
- 1-500万 501万-1000万
- 按照日期范围
- 日志 ,订单信息,统计
- 按照月份
- 按照枚举值
- 常量
- 二进制取模范围
- 类似HashMap
- 缺点:数据存放不均匀
- 一致性hash分片
典型的数据分片规则
1、根据数值范围
按照时间区间或ID区间来切分。例如:将userId为1~9999的记录分到第一个库,10000~20000的分到第二个库,以此类推。
优点:
- 单表大小可控
- 天然便于水平扩展,后期如果想对整个分片集群扩容时,只需要添加节点即可,无需对其他分片的数据进行迁移
-
使用分片字段进行范围查找时,连续分片可快速定位分片进行快速查询,有效避免跨分片查询的问题。
缺点:
热点数据成为性能瓶颈。连续分片可能存在数据热点,例如按时间字段分片,有些分片存储最近时间段内的数据,可能会被频繁的读写,而有些分片存储的历史数据,则很少被查询
2、根据数值取模
一般采用hash取模mod的切分方式,例如:将 Customer 表根据 id字段的hash值取模的余数切分到各个库中。这样同一个用户的数据会分散到同一个库中,如果查询条件带有id字段,则可明确定位到相应库去查询。
优点:数据分片相对比较均匀,不容易出现热点和并发访问的瓶颈。
缺点:
1、后期分片集群扩容时,需要迁移旧的数据。
2、容易面临跨分片查询的复杂问题。比如上例中,如果频繁用到的查询条件中不带id时,将会导致无法定位数据库,从而需要同时向4个库发起查询,分库反而成为拖累。