文章目录
索引
定义
索引是一个排序的列表,包含索引字段的值和其对应的行记录的数据所在的物理地址
作用
加快表的查询速度,还可以对字段排序
副作用:会额外占用磁盘空间;更新包含索引的表会花费更多的时间,效率会更慢
工作方式
没有索引的情况下,要根据条件查询某行数据时,需要先扫描全表,再定位某行数据的位置。
有了索引后,会先通过查询条件的字段值找到其索引对应的行记录的数据的物理地址,然后根据物理地址直接访问相应的行记录的数据,就像根据书目录的页码快速找到所需的内容。
创建索引的依据
- 表中的记录行数较多时,一般超过300行的表建议要有索引
- 建议在表中的主键字段、外键字段、多表连接使用的公共关键字段、唯一性较好的字段、不经常更新的字段、经常出现在 where,group by,order by 子语句的字段、 短小的字段上面创建索引
- 不建议在唯一性较差的字段、更新太频繁的字段、大文本字段上面创建索引
索引的类型
mysql
普通索引 create index 索引名 on 表名 (字段); alter table 表名 add index 索引名 (字段);
唯一索引 create unique index 索引名 on 表名 (字段); alter table 表名 add unique 索引名 (字段);
主键索引 alter table 表名 add primary key (字段);
组合索引 1.create index 索引名 on 表名 (字段1, 字段2, ....); alter table 表名 add index 索引名 (字段1, 字段2, ....);
2.create unique index 索引名 on 表名 (字段1, 字段2, ....); alter table 表名 add unique 索引名 (字段1, 字段2, ....);
select .... from 表名 where 字段1=XX and 字段2=XX ... ;
#用 and 做逻辑运算符多字段查询时,要创建组合索引且要满足最左原则
#用 or 做逻辑运算符多字段查询时,所有字段都要单独创建单列索引
全文索引 create fulltext index 索引名 on 表名 (字段); alter table 表名 add fulltext 索引名 (字段);
支持模糊查询 select .... from 表名 where match(字段) against('单词');
查看索引
mysql
show create table 表名;
show index from 表名;
show keys from 表名;
各字段的含义如下:
Table:表的名称。
Non_unique:如果索引不能包括重复词,则为 0;如果可以,则为 1。
Key_name:索引的名称。
Seq_in_index:索引中的列序号,从 1 开始。
Column_name:列名称。
Collation:列以什么方式存储在索引中。在 MySQL 中,有值'A'(升序)或 NULL(无分类)。
Cardinality:索引中唯一值数目的估计值。
Sub_part:如果列只是被部分地编入索引,则为被编入索引的字符的数目。如果整列被编入索引,则为 NULL。
Packed:指示关键字如何被压缩。如果没有被压缩,则为 NULL。
Null:如果列含有 NULL,则含有 YES。如果没有,则该列含有 NO。
Index_type:用过的索引方法(BTREE, FULLTEXT, HASH, RTREE)。
Comment:备注。
删除索引
mysql
直接删除索引
DROP INDEX 索引名 ON 表名;
修改表方式删除索引
ALTER TABLE 表名 DROP INDEX 索引名;
删除主键索引
ALTER TABLE 表名 DROP PRIMARY KEY;
遇到 select 语句查询速度慢改怎么办?
1.先使用 explain 分析 select 语句,看 key 字段,确定 select 语句使用使用了索引或索引使用是否正确
2.再根据 select 语句中 where 子语句使用的条件字段创建相应的单列索引或组合索引,组合索引要满足最左原则
事务
定义
事务就是一组数据库操作序列(包含一个或者多个SQL操作命令),事务会把所有操作看作是一个不可分割的整体向数据库系统提交或撤消操作,所有操作要么都执行,要么都不执行。
ACID
事务的 ACID 特性: 原子性、一致性、隔离性、持久性
-
原子性:事务管理的基础。把事务中的所有操作看作是一个不可分割的工作单元,要么都执行,要么都不执行。
-
一致性:事务管理的目的。保证事务开始前和事务结束后数据的完整和一致
-
隔离性:事务管理的手段。使多个事务并发操作同一个表数据时,每个事务都有各自独立的数据空间,事务的执行不会受到其它事务的干扰。可通过设置隔离级别解决不同的一致性问题。
-
持久性:事务管理的结果。当事务被提交以后,事务中的命令操作修改的结果会被持久保存,且不会被回滚。
隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
READ UNCOMMITTED 未提交读 | 允许 | 允许 | 允许 |
READ COMMITTED 提交读 | 不允许 | 允许 | 允许 |
REPEATABLE READ 可重复度读 | 不允许 | 不允许 | 有条件允许(InnoDB中不允许) |
SERIALIZABLE 串行读 | 不允许 | 不允许 | 不允许 |
设置隔离级别
mysql
set global transaction isolation level 隔离级别名称;
#全局级别的设置,可在所有会话有效,需要重新登录才可生效
set session transaction isolation level 隔离级别名称;
#会话级别的设置,在当前会话会话中立即生效
查看隔离级别
mysql
show global variables like '%isolation%'; #查看全局
show session variables like '%isolation%'; #当前会话
事务管理操作
mysql
begin; #开启一个事务
.... insert into update XXX set delete from #事务性操作
savepoint XX; #在事务中创建回滚点
rollback to XX; #在事务中回滚操作到指定的回滚点位置
commit; 或 rollback; #提交或回滚结束事务
自动提交事务
mysql
set [global/session] autocommit = 0/1; #0关闭自动提交,1开启自动提交
show [global/session] variables like 'autocommit'; #查看自动提交[autocommit]设置
存储引擎
定义
存储引擎是MySQL数据库中的组件,负责执行实际的数据I/O操作(数据的存储和提取)。工作在文件系统之上,数据库的数据会先传到存储引擎,再按照存储引擎的存储格式保存到文件系统。
常用的存储引擎
- InnoDB
- MyISAM
MyISAM 与 InnoDB 的区别
-
MyISAM:不支持事务、外键约束,只支持表级锁定,适合单独的查询和插入的操作,读写会相互阻塞,支持全文索引,硬件资源占用较小,数据文件和索引文件是分开存储的(存储成三个文件:表结构文件.frm、数据文件.MYD、索引文件.MYI)
使用场景:适用于不需要事务支持,单独的查询或插入数据的业务场景
-
InnoDB:支持事务、外键约束,支持行级锁定(在全表扫描时仍然会表级锁定),读写并发能力较好,支持全文索引(5.5版本之后),缓存能力较好可以减少磁盘IO的压力,数据文件也是索引文件(存储成两个文件:表结构文件.frm、数据文件.ibd)
使用场景:适用于需要事务的支持,一致性要求较高,数据会频繁更新,读写并发高的业务场景
查看表的存储引擎
mysql
show create table 表名;
show table status [from 库名] where name='表名'\G
show engines; #显示所有支持的存储引擎
alter table 表名 engine=InnoDB/MyISAM; #针对已存在的表修改存储引擎
create table 表名 (....) engine=InnoDB/MyISAM; #新建表时指定存储引擎
vim /etc/my.cnf
[mysqld]
default-storage-engine=InnoDB/MyISAM #设置新建表的默认存储引擎
死锁
死锁是指两个或多个事务在同一个资源上相互占用,并请求对方的锁定资源,从而导致恶性循环的现象。
如何避免死锁
- 合理的锁定顺序
确保所有事务以相同的顺序获取锁。例如,如果一个事务首先锁定表 A,然后再锁定表 B,那么其他事务也应该按照相同的顺序来避免相反的顺序(先锁定 B 再锁定 A),这种情况可能导致死锁。
- 减少事务持有锁的时间
尽可能减少事务持有锁的时间。如果一个事务需要长时间持有锁(如进行大量计算或者网络操作),那么其他事务可能因等待时间过长而发生死锁。
- 事务尽量简短和简单
将较长的事务分解成多个较短的事务,以便快速完成并释放锁资源。这样可以减少死锁的概率。
- 合理使用事务隔离级别
选择合适的事务隔离级别(如 READ COMMITTED、REPEATABLE READ、SERIALIZABLE)。更高的隔离级别可能会增加死锁的风险,因为它们会引入更多的锁定行为。了解业务需求并选择最适合的隔离级别是很重要的。
- 避免在事务中执行大量的 DML 操作
在事务中执行大量的数据操作(如更新或删除大量行)可能增加死锁的风险。如果可能的话,尝试将这些操作分散到较小的事务中,以减少事务持有锁的时间和范围。
- 使用数据库提供的死锁检测和处理机制
设置事务的锁等待超时时间 innodb_lock_wait_timeout;设置开启死锁检测 innodb_deadlock_detect
- 监控和调优数据库性能
定期监控数据库的性能和锁等待情况,及时调整数据库的配置和索引以优化查询性能,减少锁等待时间。
- 合理设计数据库和应用程序
在数据库和应用程序设计阶段,考虑并发访问和数据访问模式,合理设计数据模型、索引和事务逻辑,以最大程度地减少死锁的可能性。
待超时时间 innodb_lock_wait_timeout;设置开启死锁检测 innodb_deadlock_detect
- 监控和调优数据库性能
定期监控数据库的性能和锁等待情况,及时调整数据库的配置和索引以优化查询性能,减少锁等待时间。
- 合理设计数据库和应用程序
在数据库和应用程序设计阶段,考虑并发访问和数据访问模式,合理设计数据模型、索引和事务逻辑,以最大程度地减少死锁的可能性。