数据库MySQL(三):存储引擎、索引、触发器、锁

目录

1 表设计

1.1 存储引擎

1.2 存储引擎特点

1.2.1 InnoDB

1.2.2 MyISAM

1.2.3 Memory

2 表结构设计

2.1 范式设计,消除冗余

2.2  反范式设计,适当冗余

2.3.主键

2.4.选择数据类型

3 索引

3.1 什么是索引

3.2 索引的分类

3.3 索引的优缺点

3.4 索引失效

3.5 索引优化

4 触发器 

4.1 概念

4.2  触发器类型

4.3 触发器优缺点

5 锁 

5.1 行级锁

5.2 InnoDB 中的两个表锁


1 表设计

1.1 存储引擎

存储引擎:存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所以存储引擎也被称为表类型

  • 连接层:提供一些客户端和连接服务,主要完成连接处理、授权认证等相关的安全方案。同时服务器也会为每个安全连接的用户验证其操作权限。
  • 服务层:主要完成大多数核心服务功能,如:SQL接口,并完成缓存的查询,SQL的分析和优化。所有跨存储引擎的功能也在这一层实现,如存储过程、函数等。
  • 引擎层:存储引擎真正负责MySQL中数据的存储和使用,服务器通过API和存储引擎进行通信。不同的存储引擎具有不同的功能,可根据具体需求选择最适合的存储引擎。
  • 存储层:主要是将数据存储在文件系统上,并完成与存储引擎的交互。

注意:索引是在引擎层完成的,不同的存储引擎 他的索引结构不同  

查询当前数据库支持的存储引擎,MySQL5.5后默认的存储引擎INNODB 之前默认支持MyISAM
show engines;


在创建表时,指定存储引擎
create table 表名(
    字段 数据类型 约束,
    字段 数据类型 约束
) engine = 存储引擎名称;

1.2 存储引擎特点

1.2.1 InnoDB

介绍:InnoDB是一种兼顾高可靠和高性能的通用存储引擎,在MySQL5.5之后,InnoDB是默认的MySQL存储引擎

特点

  1. DML操作遵循ACID原则,支持事务;

  2. 支持行锁,采用MVCC来支持高并发 ;

  3. 支持外键FROEIGN KEY约束,保证数据的完整性和正确性;

  4. 支持崩溃后的安全恢复;

  5. 不支持全文索引

MVCC :mvcc全称是multi version concurrent control(多版本并发控制)。mysql把每个=操作都定义成一个事务,每开启一个事务,系统的事务版本号自动递增。每行记录都有两个隐藏列:创建版本号和删除版本号

文件存储

XXX.ibd:xxx代表的是表名,innoDB引擎的额每张表都会对应这样一个表空间文件,存储该表的表结构(frm、sdi)、数据和索引。

sdi数据字典,mysql8.0以前存储在frm文件中,mysql8.0之后就存储在sdi中

参数:innodb_file_per_table

1.2.2 MyISAM

MyISAM是MySQL早期默认的存储引擎

特点

  1. 不支持事务,不支持外键

  2. 支持表锁,不支持行锁

  3. 访问速度快

  4. 在表有读取查询的同时,支持往表中插入新纪录 

  5. 对于不会进行修改的表,支持压缩表,极大减少磁盘空间占用

1.2.3 Memory

介绍:Memory引擎的表结构存储数据在内存中,由于受到硬件问题、电源问题的影响,只能将这些表作为临时表或缓存使用。

特点

  1. 内存存放--访问速度快

  2. 支持hash索引

三者间的对比:

2 表结构设计

2.1 范式设计,消除冗余

数据库范式是确保数据库结构合理,满足各种查询需要、避免数据库操作异常的数据库设计方式。满足范式要求的表,称为规范化表,范式产生于20世纪70年代初,一般表设计满足前三范式就可以。

通俗的三范式解释:

  • 第一范式:属性(字段)的原子性约束,要求属性具有原子性,不可再分割;   
  • 第二范式:记录的惟一性约束,要求记录有惟一标识,每条记录需要有一个属性来做为实体的唯一标识。   
  • 第三范式:属性(字段)冗余性的约束,即任何字段不能由其他字段派生出来,在通俗点就是:主键没有直接关系的数据列必须消除(消除的办法就是再创建一个表来存放他们,当然外键除外)

2.2  反范式设计,适当冗余

数据库设计的实用原则是:在数据冗余和处理速度之间找到合适的平衡点,满足范式的表一定是规范化的表,但不一定是最佳的设计。

很多情况下会为了提高数据库的运行效率,常常需要降低范式标 准:适当增加冗余,达到以空间换时间的目的。比如我们有一个表,产品名称,单价,库存量,总价值。这个表是不满足第三范式的,因为“总价值”可以由“单价”乘以“数量”得到,说明“金额”是冗余字段。但是,增加“总价值”这个冗余字段,可以提高查询统计的速度,这就是以空间换时间的作法。合理的冗余可以分散数据量大的表的并发压力,也可以加快特殊查询的速度,冗余字段可以有效减少数据库表的连接,提高效率。

2.3.主键

主键:根据第二范式,需要有一个字段去标识这条记录,主键无疑是最好的标识,需要满足唯一性、非空性,但是很多表也不一定需要主键,但是对于数据量大,查询频繁的数据库表,一定要有主键,主键可以增加效率、防止重复等优点。

2.4.选择数据类型

MySQL支持的数据类型非常多, 选择正确的数据类型对于获得高性能至关重要。

更小的通常更好 更小的数据类型通常更快, 因为它们占用更少的磁盘、 内存和CPU缓存, 并且处理时需要的CPU周期也更少。

简单就好 简单数据类型的操作通常需要更少的CPU周期。 例如, 整型比字符操作代价更低, 因为字符集和校对规则(排序规则 )使字符比较比整型比较更复杂。

尽量避免NULL

如果查询中包含可为NULL 的列, 对MySQL来说更难优化, 因为可为NULL 的列使得索引、 索引统计和值比较都更复杂。

数据类型尽量用数字型,数字型的比较比字符型的快很多

3 索引

3.1 什么是索引

在数据之外,数据库还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用指向数据,这样就可以在这些数据结构上实现高效查找,这些数据结构就是索引。

简单来说索引的出现就是为了提高数据的查询效率,就像书的目录一样。在书籍中,用户不必翻阅完整个书就能根据目录迅速地找到所需要的信息。在数据库中,索引也允许数据库程序迅速地找到表中的数据,而不必扫描整个数据库。

3.2 索引的分类

单值索引:一个索引只包含单个列,一个表中可以有多个单值索引

唯一索引:索引列的值必须唯一,可为空

复合索引:一个索引包括多个列

3.3 索引的优缺点

优点:

1.提高数据检索效率,降低磁盘IO成本

2.通过对数据的排序,降低排序成本

缺点:

1.索引虽提高了查询效率,但同时降低了更新、修改、删除的效率,因为MySQL不仅要保存数据,还要维护数据和索引的关系。

2.需要成本去维护索引。一个性能良好的索引需要不断的去尝试,以找到最优解。

3.4 索引失效

1、like以通配符开头('%abc')会导致索引失效,违反最左前缀法则

最左前缀法则:如果索引了多列(联合索引)。最左前缀法则指的是查询从索引的最左列开始,并且不跳过索引中的列。如果跳跃某一列,索引将部分失效(后面的字段索引失效)

2、在索引列上做任何操作(计算、函数、类型转换),会导致索引失效而转向全表扫描

3、存储引擎不能使用索引中范围条件右边的列,举例:select id,name from student where id > 50 and name = '张三',会导致name索引失效

4、尽量使用覆盖索引,不要select *

5、MySQL在使用不等于(!=或<>)的时候无法使用索引会导致全表扫描,理由也很简单,B+Tree叶子节点用指针相连且是排好序的,这种数据结构只能解决有序的定值查询,像不等于这种无法利用索引查询。

6、IS NULL、IS NOT NULL无法使用索引,理由同上

7、字符串不加单引号索引失效

隐式转换-->函数操作

8、用or连接时会导致索引失效

3.5 索引优化

前缀索引优化:使用某个字段中字符串的前几个字符建立索引

使用前缀索引是为了减小索引字段大小,可以增加一个索引页中存储的索引值,有效提高索引的查询速度。在一些大字符串的字段作为索引时,使用前缀索引可以帮助我们减小索引项的大小。

前缀索引的局限性:

1、order by 无法使用前缀索引;
2、无法把前缀索引用作覆盖索引;

覆盖索引优化:SQL 中 query 的所有字段,在索引 B+Tree 的叶子节点上都能找得到的那些索引,从二级索引中查询得到记录,而不需要通过聚簇索引查询获得,可以避免回表的操作。

使用覆盖索引的好处就是,不需要查询出包含整行记录的所有信息,也就减少了大量的 I/O 操作。

 主键索引最好是自增的:InnoDB 创建主键索引默认为聚簇索引,数据被存放在了 B+Tree 的叶子节点上。也就是说,同一个叶子节点内的各个数据是按主键顺序存放的,因此,每当有一条新的数据插入时,数据库会根据主键将其插入到对应的叶子节点中。

如果我们使用自增主键,那么每次插入的新数据就会按顺序添加到当前索引节点的位置,不需要移动已有的数据,当页面写满后,就会自动开辟一个新页面。因为每次插入一条新记录,都是追加操作,不需要重新移动数据,因此这种插入数据的方法效率非常高。

如果我们使用非自增主键,由于每次插入主键的索引值都是随机的,因此每次插入新的数据时,就可能会插入到现有数据页中间的某个位置,这将不得不移动其它数据来满足新数据的插入,甚至需要从一个页面复制数据到另外一个页面,我们通常将这种情况称为页分裂。页分裂还有可能会造成大量的内存碎片,导致索引结构不紧凑,从而影响查询效率。

索引最好设置为NOT NULL

第一原因:索引列存在 NULL 就会导致优化器在做索引选择的时候更加复杂,更加难以优化,因为可为 NULL 的列会使索引、索引统计和值比较都更复杂,比如进行索引统计时,count 会省略值为NULL 的行。

第二个原因:NULL 值是一个没意义的值,但是它会占用物理空间,所以会带来的存储空间的问题,会导致更多的存储空间占用,因为 InnoDB 默认行存储格式COMPACT,会用 1 字节空间存储 NULL 值列表

防止索引失效

4 触发器 

4.1 概念

触发器(trigger)是个特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,比如当对一个表进行操作( insert,delete, update)时就会激活它执行。

作用:

触发器经常用于加强数据的完整性约束和业务规则等;

可在写入数据前,强制检验或者转换数据(保证安全性);

触发器发生错误时,前面用户已经执行成功的操作会被撤销,类似事务的回滚。

4.2  触发器类型

触发器是与表有关的数据库对象,指在insert/update/delete之前或之后,触发并执行触发器定义的sql语句。使用别名OLD和NEW来引用触发器中发生变化的记录内容,现在的触发器只支持行级触发,不支持语句级触发

4.3 触发器优缺点

优点

安全性

触发器有回滚性,保证数据完整

保存用户的操作,存入日志

触发器可以对数据库中的相关表进行连环更新  

缺点

过分依赖触发器,影响数据库的结构,增加数据库的维护成本 

5 锁 

MySQL的InnoDB锁机制分为表级锁和行级锁

5.1 行级锁

行级锁中有共享锁和排它锁。

共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。

select * from t_user where id =10 lock in share mode;

排他锁又称为写锁(独占锁),简称X锁,顾名思义,排他锁就是不能与其他锁并存。

如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,

包括共享锁和排他锁。

select * from t_user where id =10 for update;

MySQL InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给涉及到的数据加上排他锁,select语句默认不会加任何锁类型。

5.2 InnoDB 中的两个表锁

意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁;

意向排他锁(IX):类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。

  意向锁是 InnoDB 自动加的,不需要用户干预。

  再强调一下,对于INSERT、UPDATE和DELETE,InnoDB 会自动给涉及的数据加排他锁;对于一般的SELECT语句,InnoDB 不会加任何锁,事务可以通过以下语句显式加共享锁或排他锁。

共享锁:SELECT … LOCK IN SHARE MODE;
排他锁:SELECT … FOR UPDATE;

 两种锁的优劣

表锁的优势:开销小;加锁快;无死锁 表锁的劣势:锁粒度大,并发处理能力低

行锁的劣势:开销大;加锁慢;会出现死锁 行锁的优势:锁的粒度小,处理并发的能力

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值