1.数据库基本概念
DBMS DB
2.结构化查询语言
名称 | 解释 | 命令 |
---|---|---|
DDL(数据库定义语言) | 定义和管理数据对象,如数据库和数据表等等 | CREATE、DROP、ALTER |
DML(数据库操作语言) | 用于操作数据库对象中所包含的数据 | INSERT、UPDATE、DELETE |
DQL(数据库查询语言) | 用于查询数据库数据 | SELECT |
DCL(数据库控制语言) | 用于管理数据库的语言,包括权限管理和数据更改 | GRANT、COMMIT、ROLLBACK |
3.事务
原子性(Atomic)
- 整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(ROLLBACK)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性(Consist)
- 一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少,数据库的完整性约束没有被破坏。也就是说:如果事务是并发多个,系统也必须如同串行事务一样操作。其主要特征是保护性和不变性(Preserving an Invariant),以转账案例为例,假设有五个账户,每个账户余额是100元,那么五个账户总额是500元,如果在这个5个账户之间同时发生多个转账,无论并发多少个,比如在A与B账户之间转账5元,在C与D账户之间转账10元,在B与E之间转账15元,五个账户总额也应该还是500元,这就是保护性和不变性。
隔离性(Isolated)
- 隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。
事务并发带来的问题:脏读、不可重复度和幻影读。
事务隔离分为不同级别:
读未提交(Read uncommitted):事务的最低隔离级别,不能解决事务并发执行产生的任何问题。
读提交(read committed):可以解决脏读。
可重复读(repeatable read):可以解决脏读和不可重复读。
串行化(Serializable):可以解决脏读、不可重复读和幻影读。
![](https://cdn.nlark.com/yuque/0/2021/png/12810482/1616132911674-b33b8321-3650-43af-8196-a5e8e3424681.png#align=left&display=inline&height=156&margin=%5Bobject%20Object%5D&originHeight=156&originWidth=514&size=0&status=done&style=shadow&width=514)<br />**持久性(Durable)**
- 在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
4.索引
4.1索引的定义
参考文献:http://blog.codinglabs.org/articles/theory-of-mysql-index.html
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。
4.2 Mysql中Innodb存储引擎的索引结构
4.2.1索引类型
- 普通索引
create index index_name on table(column);
或者创建表时指定,create table(…, index index_name column);
- 唯一索引
类似普通索引,索引列的值必须唯一(可以为空,这点和主键索引不同)
create unique index index_name on table(column);
或者创建表时指定unique index_name column
- 主键索引
特殊的唯一索引,不允许为空,只能有一个,一般是在建表时指定primary key(column)
- 组合索引
在多个字段上创建索引,遵循最左前缀原则。alter table t add index index_name(a,b,c);
- 全文索引
主要用来查找文本中的关键字,不是直接与索引中的值相比较,像是一个搜索引擎,配合match against使用,现在只有char,varchar,text上可以创建全文索引。在数据量较大时,先将数据放在一张没有全文索引的表里,然后再利用create index创建全文索引,比先生成全文索引再插入数据快很多。
4.2.2 聚簇索引和非聚簇索引
- 聚簇索引:聚簇索引是逻辑结构与数据存储物理结构一致的一种索引,并且一个表的聚簇索引只能有唯一的一条。
- 非聚簇索引:非聚簇索引记录的物理顺序与逻辑顺序没有必然的联系,与数据的存储物理结构没有关系;一个表对应的非聚簇索引可以有多条,根据不同列的约束可以建立不同要求的非聚簇索引。
先引进聚簇索引和非聚簇索引的概念! 我们平时在使用的Mysql中,使用下述语句
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name
[USING index_type]
ON tbl_name (index_col_name,...)
index_col_name:
col_name [(length)] [ASC | DESC]
创建的索引,如复合索引、前缀索引、唯一索引,都是属于非聚簇索引,在有的书籍中,又将其称为辅助索引(secondary index)。在后文中,我们称其为非聚簇索引,其数据结构为B+树。
那么,这个聚簇索引,在Mysql中是没有语句来另外生成的。在Innodb中,Mysql中的数据是按照主键的顺序来存放的。那么聚簇索引就是按照每张表的主键来构造一颗B+树,叶子节点存放的就是整张表的行数据。由于表里的数据只能按照一颗B+树排序,因此一张表只能有一个聚簇索引。
在Innodb中,聚簇索引默认就是主键索引。 这个时候,机智的读者,应该要问我
如果我的表没建主键呢? 回答是,如果没有主键,则按照下列规则来建聚簇索引
- 没有主键时,会用一个唯一且不为空的索引列做为主键,成为此表的聚簇索引
- 如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。
ps
:大家还记得,自增主键和uuid作为主键的区别么?由于主键使用了聚簇索引,如果主键是自增id,,那么对应的数据一定也是相邻地存放在磁盘上的,写入性能比较高。如果是uuid的形式,频繁的插入会使innodb频繁地移动磁盘块,写入性能就比较低了。
索引原理介绍
先来一张带主键的表,如下所示,pId是主键
画出该表的结构图如下
如上图所示,分为上下两个部分,上半部分是由主键形成的B+树,下半部分就是磁盘上真实的数据!那么,当我们, 执行下面的语句
select * from table where pId='11'
那么,执行过程如下
如上图所示,从根开始,经过3次查找,就可以找到真实数据。如果不使用索引,那就要在磁盘上,进行逐行扫描,直到找到数据位置。显然,使用索引速度会快。但是在写入数据的时候,需要维护这颗B+树的结构,因此写入性能会下降! OK,接下来引入非聚簇索引!我们执行下面的语句
create index index_name on table(name);
此时结构图如下所示
大家注意看,会根据你的索引字段生成一颗新的B+树。因此, 我们每加一个索引,就会增加表的体积, 占用磁盘存储空间。然而,注意看叶子节点,非聚簇索引的叶子节点并不是真实数据,它的叶子节点依然是索引节点,存放的是该索引字段的值以及对应的主键索引(聚簇索引)。 如果我们执行下列语句
select * from table where name='lisi'
此时结构图如下所示
通过上图红线可以看出,先从非聚簇索引树开始查找,然后找到聚簇索引后。根据聚簇索引,在聚簇索引的B+树上,找到完整的数据!
什么情况不去聚簇索引树上查询呢? 还记得我们的非聚簇索引树上存着该索引字段的值么。如果,此时我们执行下面的语句
select name from table where name='lisi'
此时结构图如下
如上图红线所示,如果在非聚簇索引树上找到了想要的值,就不会去聚簇索引树上查询。 当执行select col from table where col = ?,col上有索引的时候,效率比执行select * from table where col = ? 速度快好几倍! 看完上面的图,你应该对这句话有更深层的理解了。
那么这个时候,我们执行了下述语句,又会发生什么呢?
create index index_birthday on table(birthday);
此时结构图如下
看到了么,多加一个索引,就会多生成一颗非聚簇索引树。因此,很多文章才说,索引不能乱加。因为,有几个索引,就有几颗非聚簇索引树!你在做插入操作的时候,需要同时维护这几颗树的变化!因此,如果索引太多,插入性能就会下降!