索引
是什么
类似于目录,提高查询的速度,但是本身会占用空间,增删数据的时候也需要维护索引。所以查询操作频繁的时候可以创建索引。如果非条件查询列,或经常做插入、修改操作,或磁盘空间不足时,不考虑创建索引。
创建主键约束(primary key),唯一约束(unique),外键约束(foreign key)时会自动创建对应列索引。
查询索引
show index from 表名;
创建索引
当数据库的数据量很大时,创建和删除索引是很危险的操作,会大量消耗CPU,IO等资源,可能导致数据库卡死。所以要在放入数据之前,或者数据库中的数据量不大时创建索引。如果要给一个数据量很大的数据库添加索引,就需要再准备一个服务器,在空的数据库中创建好索引,将另一个数据库的数据慢慢导入这个空的数据库里。
create index 索引名 on 表名(列名 );//底层是创建出一棵独立的B+树来组织索引,跟主键的B+树没有关联。是两棵独立的树。
删除索引
drop index 索引名 on 表名 ;
底层结构
数据库的索引是用B+树表示存储的。
B+树结构
仅叶子节点存储数据并通过链表指针连接(叶子节点从左到右是有序的,且存储在一块连续内存空间,避免频繁访问硬盘,一次硬盘IO就能读出整个节点数据;访问的数据都在叶子节点,树高一样,则每次查询次数是稳定的);
非叶子节点存储键,键值为其叶子节点中的最大值(方便进行范围查询,锁定叶子节点中数据的位置);
当叶子节点个数达到阈值,会进行分叉。(索引在内存中,个数增加了对速度影响不大,但叶子节点存在硬盘中,访问硬盘的速度比访问内存满很多,所以要进行分叉,根据索引查找数据时范围更精确)
1.N叉搜索树(多叉树可以控制树的高度)
2.父节点以叶子节点中最大值的形式存在(快速锁定子树的数据范围)
3.叶子节点这一层用链表结构连上,不用再回溯到父节点。(范围查寻更高效)
4.数据存储在叶子节点,索引存在非叶子节点中,因为占用空间小,索引就存在内存中。(索引在内存中加快查找速度)
为什么用B+树,不用其他数据结构?
AVL树是严格的自平衡二叉搜索树(子树高度差不能超过1),随便进行一下增删改就会触发AVL树旋转。每一次旋转都有对应的开销,所以用AVL树除了查询外,其他操作的效率不高,每一次增删都需要维护树的平衡;
而红黑树虽然旋转的概率没有AVL树高,但他是二叉树,当数据量很大时,树的高度就会很高,高度每增加一层,查询比较次数就多一次,而数据库数据索引是存储在硬盘上的,每一次对硬盘的IO操作很耗时间,查询的速度就会慢很多;
hash表存储数据是无序的,不能进行范围查询(不能用>或者<找到一个范围的数据),只能比较相同key值的数据,因为经过hash函数的计算,原来key之间的大小关系 已经不能通过计算出来的hash值反应了。
事务
什么是事务
当实现一个目的需要多个sql语句执行时,将这些sql语句打包成的一个整体,称作事务。事务中的sql语句要么全部执行成功,要么全部失败。对于转账这类场景,开启事务更能保证安全。当A给B转账500,A的账号-500,如果设备发生故障,sql没执行完,B的账户没有+500,如果没有开启事务,那么这500就消失了。开启事务后,出现故障后,会撤销对A账户执行的操作,将A账号的金额还原到转账前。
使用
1.start transaction ;//开启事务
2.中间执行多个sql语句
3.rollback或commit
rollback表示回滚,中间的sql语句全部执行失败,commit表示提交,sql全部执行成功。
进行回滚了,name为a的数据没有插入成功。
基本特性
1.原子性
事务里的sql语句执行要么都成功执行,要么都不执行。当一部分sql语句执行成功,出现网络崩溃,计算机死机,主机掉电等操作时,像网络崩溃这种不影响数据库的,则会执行回滚操作,将已经执行的sql语句造成的影响恢复到没执行时候的情况。当事务执行时,sql语句会记录在mysql日志中,像主机掉电这种情况,数据库没办法运行的时候,也不影响执行回滚操作,当电来了,恢复正常,数据库会根据日志信息执行回滚。
2.一致性
执行事务之后,数据能对得上;事务没执行成功,执行回滚后,能与执行事务之前数据一样。
3.持久性
持久性指数据被存在硬盘上,主机/程序重启后,数据依然存在。事务执行具有持久性,对数据库造成的修改,会保存在硬盘上持久存在。
4.隔离性
在执行并发操作时存在的概念。隔离性提高,并发能力就降低,数据库服务器执行效率就会降低,但数据准确性会提高 。当多个客户端同时对服务器发起事务时,可能存在下面几种情况。
1.脏读问题:读取到其他事务未提交的数据
当执行事务A对某一张表做一些修改时,事务B在事务A还没执行完就来读取这张表的数据,但是B这时读取的表的数据是临时的,B如果基于这个临时数据进行一些操作,结果可能不正确。这样导致的问题称作脏读问题,这个临时数据也称‘脏数据’。
2.不可重复读问题:指同一事务内相同查询条件多次执行结果不同(数据值被修改)
当事务B有多个读的操作时,有一个事务C要对这张 表做修改,这样可能导致事务B多个读的结果前后不一致。
3.幻读问题:指同一事务内相同范围查询返回的行数发生变化(新增或删除行),这是不可重复读的特殊情况。
MySQL 的四个隔离等级
可以在MySQL的配置文件中设置等级
1.read uncommitted:允许读取其他事务未提交的数据 ;//存在脏读+不可重复读+幻读,
这样就是降低了并发时事务之间的影响,提高了隔离性,牺牲了部分效率,提高了数据准确性。
2.read committed:只能读取其他事务提交后的数据;//解决脏读 ,存在不可重复读+幻读,进一步降低了并发性,提高安全性。
3.repeatable read: 针对读和写操作都加锁了;//解决了脏读+不可重复读,存在幻读问题 (MySQL默认隔离等级)
4.串行化(serialiable) :所有事务串行执行;//严格的一个接一个执行,这时完全没有并发,也就不存在上诉三个问题;隔离性是最高的,效率是最低的。