索引
什么是索引?
索引是一种特殊的文件,包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现
作用
快速定位、检索数据
提高查询效率
提高数据库的性能
索引有哪些数据结构?
hash B树 B+树
hash 表
可以快速的精确查询,但是不支持范围查询
速度慢
hash表一般适用于有序数组的查询
不适用于新增、删除、修改数据
hash表可以用来做静态存储引擎,用来保存静态数据
MySQL选择B+树可以提高查询索引时的磁盘IO效率,并且可以提高范围查询的效率,并且B+树里的元素是有序的
使用场景
数据量较大,且经常对这些列进行条件查询
该数据库表的插入操作,及对这些列的修改操作频率较低
索引会占用额外的磁盘空间
操作
创建主键约束(PRIMARY KEY)、唯一约束(UNIQUE)、外键约束(FOREIGN KEY)时,会自动创建对应列的索引
- 查看索引
show index from 表名;
- 创建索引
1)普通索引
create index 索引名 on 表名(字段);
2)主键索引
无需显示创建,自动创建
3)唯一索引
单列索引
create unique index 索引名 on 表名(字段);
4)组合索引
将多个字段联合起来
create index 索引名 on 表名(字段1,字段2);
- 删除索引
drop index 索引名 on 表名;
主键索引和普通索引的区别?
- 主键索引不需要显示创建,普通索引需要创建
- 主键索引不能删除,而普通索引可以
- 主键索引查询更快,而普通索引因为有回表查询,索引性能没有主键索引性能高
回表查询
- 主键索引它的非叶子节点存储的所有的数据,当我们根据主键查询响应节点信息之后就可以拿到这个整个数据,对于普通索引来说,当我们根据索引得到节点信息之后,只能得到这个节点的主键信息,然后再根据这个主键信息去查询整体数据的内容,这个过程叫做回表查询,因此普通索引的查询性能是比较低,而主键索引的性能比较高。
注意
- 在生产服务器不要直接执行添加索引的操作(创建索引的过程非常耗时,且数据量越大,创建的时间就越长)
- 对于多读(查询)的场景,适合使用索引,而对于添加、删除 比较多的场景,不适合使用
- 避免使用查询的时候,不触发索引查询,比如在列上进行赋值运算
什么情况下,索引不会触发?
- 当对一个列(已经设置索引),进行赋值查询时
- 当使用模糊查询的时候可能不触发索引,当使用like '%xx%'时不会触发索引,like ‘xx%’ 可以触发
- 当使用组合索引时,一定要遵循最左匹配原则
- 尽量避免使用or查询,可能会导致索引不生效
- 不要使用!=、<> ,会导致索引不生效
- 如果是字符串查询,一定加上单引号,否则会导致索引不生效
最左匹配原则
先查询最左边的,依次查询
eg:表名(A,B,C)
where a=xxx and b=xxx and c=xxx
where a=xxx and b=xxx
where a=xxx and c=xxx
符合最左匹配原则
where c=xxx and a=xxx
where b=xxx and a=xxx
不符合最左匹配原则,不触发索引
如何优化MySQL的性能?
- 在查询比较多的关键列上加索引
- 使用慢查询日志,找到执行比较慢的sql,再针对性的优化解决问题
- 能使用主键索引时,尽量使用主键索引
- 分表(垂直分隔)分库(水平分隔)
- 提高数据库的硬件配置,更换一个读写性能更好的磁盘,更大的内存
如何开启慢查询?
- 修改配置文件
修改配置文件my.cnf,在[mysqld] 下方加入
[mysqld]
slow_query_log ON
slow_query_log_file = /usr/local/mysql/data/show_query.log
long_query_time = 1 - 重启MySQL服务
service mysqld restart
事务
什么是事务
事务指逻辑上的一组操作,组成这组操作的各个单元,要么全部成功,要么全部失败
使用
- 开启事务
start transaction;
- 执行多条sql语句
- 回滚或提交
rollback//回滚:全部失败
commit//提交:全部成功
特性(ACID)
- 原子性
指事务包含的操作要么全部成功,要么全部失败 - 一致性
事务执行前后,数据保持一致(正确) - 隔离性
多个用户并发访问数据库时,不能被其他事务相互干扰,事务之间要相互隔离 - 持久性
指一个事务一旦被提交,那么它对数据库的改变是永久性的
存在的问题
-
脏读
事务A执行时,读取到了事务B未提交的数据,事务B回滚,事务A读取到了不存在的数据,就产生了脏读 -
不可重复读
事务A使用相同的查询条件,得到的两条数据结果不一致,因为这个过程中,事务B修改了数据 -
幻读
事务A将数据修改后,事务B又插入了一条数据,导致事务A执行的结果和预期不一致
不可重复读和幻读的区别?
- 不可重复读—修改
- 幻读—添加、删除
幻读问题解决:
- 使用MVCC解决,添加版本号
- gap 间隙锁
事务的隔离级别
- 读未提交
一个事务读到了另一个事务未提交的执行结果,会出现脏读问题 - 读已提交
一个事务只能看见已经提交的事务所做的改变,会出现不可重复读问题 - 可重复读
MySQL默认事务隔离级别
同一个事务在读取数据时,会得到同样的数据行,会出现幻读问题(读取到另一个事务新插入的数据) - 可串行化(加锁,排队处理、性能不高)
最高的事务隔离级别
强制事务排序,使之不会产生冲突
是在每个读的数据行上加共享锁,会导致大量的超时现象和锁竞争问题
- | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | √ | √ | √ |
读已提交 | × | √ | √ |
可重复读 | × | × | √ |
可串行化 | × | × | × |
级别越高,执行效率越低
事务锁
只有拿到锁的事务才可对数据库进行读写操作
读锁
共享锁
事务拿到这把锁时,只能进行读操作,其他事务也可能拿到这把锁
写锁
独占锁
事务拿到这把锁时,能进行读、写操作,其他事务不能拿到这把锁
一个事务拿到读锁,其他事务也可以拿到读锁,但是拿不到写锁
一个事务拿到写锁,其他事务不能拿到写锁,也拿不到读锁