目录
1. 索引介绍
1.1 索引的概念
1.2 索引的作用
1.2.1 索引的副作用
1.3 创建索引的原则依据
1.4 索引如何工作的?
1.5 索引的分类和创建
1.5.1 普通索引
1.5.2 唯一索引
1.5.3 主键索引
1.5.4 组合索引(单列索引与多列索引)
1.5.5 全文索引(FULLTEXT)
1.6 删除索引
1.7 查看索引
1.8 索引的主要作用和副作用
1.8.1 索引是如何提高查询速度的?
1.8.2 select 语句的慢查询问题,如何处理?
2. 事务介绍
2.1 事务的概念
2.2 事务的ACID特点
2.2.1 原子性
2.2.2 一致性(保证数据的完整性)
2.2.3 隔离性
2.2.3.5 设置事务的隔离级别
2.2.4 持久性
2.3 事务控制语句
2.3.1 自动提交事务
2.3.2 案例
索引是一个排序的列表
,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址(类似于c语言的链表通过指针指向数据记录的内存地址)。使用索引后可以不用扫描全表来定位某行的数据
,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据,因此能加快数据库的查询速度。索引就好比是一本书的目录
,可以根据目录中的页码快速找到所需的内容。索引是表中一列或者若干列值排序的方法
建立索引的目的是加快对表中记录的查找或排序。
索引可以成千上万倍地提高查询速度
。索引还可以降低数据库的排序成本
。保证数据表中每一行数据的唯一性
。总结:
- 加快【大表或者多表】查询速度,对字段排序
- 降低IO成本和排序成本
- 唯一性索引还可以保证字段的唯一性
- 加快多表连接、分组、排序、恢复数据库的速度
对于
MyISAM 引擎
而言,索引文件和数据文件是分离的,索引文件用于保存数据记录的地址。而
InnoDB 引擎
的表数据文件本身就是索引文件
更新一个包含索引的表需要比更新一个没有索引的表花费更多的时间
,这是由于索引本身也需要更新。因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引索引虽可以提升数据库查询的速度,但并不是任何情况下都适合创建索引。因为索引本身会消耗系统资源,在有索引的情况下,数据库会先进行索引查询,然后定位到具体的数据行,如果索引使用不当,反而会增加数据库的负担
表的主键、外键必须有索引
。因为主键具有唯一性,外键关联的是主表的主键,查询时可以快速定位。记录数超过300行的表应该有索引
。如果没有索引,每次查询都需要把表遍历一遍,会严重影响数据库的性能。经常与其他表进行连接的表
,在连接字段上应该建立索引。唯一性太差的字段不适合建立索引
。更新太频繁的字段不适合创建索引
。经常出现在where子句中的字段
,特别是大表的字段,应该建立索引。经常进行GROUP BY(分组)、 ORDER BY(排序)的字段
上建立索引;没有索引时,每次查询都需要先全表扫描来定位某行数据,查询速度慢,IO资源消耗较大 有索引时,会先进行索引查询,然后通过索引值的数据对应的物理地址定位到具体的数据行,从而加快查询速度
create table member (id int(10),name varchar(10),cardid int(18),phone int(11),address varchar(50),remark text);
//插入数据
insert into member values(1, 'zhangsan' ,123123, 123123, 'nanjing', 'this is member!');
insert into member values(2, 'lisi', 456456, 456456, 'beijing','this is vip!');
insert into member values(3, 'wangwu', 789789, 78979, ' shanghai', 'this is vip member!');
复制代码
转存失败重新上传取消
最基本的索引类型,没有唯一性之类的限制。
CREATE INDEX 索引名 ON 表名(列名[(length)]);
复制代码
(列名(length)): length是可选项,下同。如果忽略length 的值,则使用整个列的值作为索引。如果指定,使用列的前length个字符来创建索引,这样有利于减小索引文件的大小。在不损失精确性的情况下,长度越短越好。
索引名建议以"_index"结尾。
create index name_index on memeber(name);
复制代码
ALTER TABLE 表名 ADD INDEX 索引名(列名);
//例
alter table member add index cid_index(cardid);
复制代码
CREATE TABLE 表名 (字段1 数据类型,字段2 数据类型[...], INDEX 索引名(列名));
//例
create table member1 (id int(10),name varchar(10),cardid int(18),phone int(11),address varchar(50),remark text,index name_index(name));
复制代码
与普通索引类似,但区别是唯一索引列的每个值都唯一。唯一索引允许有空值(注意和主键不同)。如果是用组合索引创建,则列值的组合必须唯一。添加唯一键将自动创建唯一索引。
CREATE UNIQUE INDEX 索引名 ON 表名(列名);
//例:
create unique index cardid_index on member(cardid);
复制代码
ALTER TABLE 表名 ADD UNIQUE 索引名(列名);
//例
alter table member add unique cardid_index(cardid)
复制代码
CREATE TABLE 表名 (字段1 数据类型,字段2 数据类型,[....],UNIQUE 索引名(列名));
//例
create table member2 (id int(10),name varchar(10),cardid int(18),phone int(11),address varchar(50),remark text,unique name_index(name));
复制代码
是一种特殊的唯一索引,必须指定为"PRIMARY KEY"。一个表只能有一个主键,不允许有空值。添加主键将自动创建主键索引。
CREATE TABLE 表名([...],PRIMARY KEY (列名));
create table member3 (id int(10),name varchar(10),cardid int(18),phone int(11),address varchar(50),remark text,primary key(name));
复制代码
ALTER TABLE 表名 ADD PRIMARY KEY(列名);
//例:
alter table member add primary key(id);
复制代码
可以是单列上创建的索引,也可以是在多列上创建的索引。需要满足最左原则,因为select 语句的where条件是依次从左往右执行的,所以在使用select语句查询时where条件使用的字段顺序必须和组合索引中的排序一致,否则索引将不会生效。
CREATE TABLE 表名(列名1 数据类型,列名2 数据类型,INDEX 索引名(列名1,列名2));
select * from 表名 where 列名1='...' AND 列名2='...';
复制代码
//例
create table member (id int(10),name varchar(10),cardid int(18),phone int(11),address varchar(50),remark text,index id_name_index(id,name));
select * from member where id=1 and name='zhangsan';
复制代码
ALTER TABLE 表名 ADD INDEX 索引名(列名1,列名2);
//例
alter table member add index id_name_index(id,name);
复制代码
CREATE INDEX 索引名 on 表名(字段1,字段2,字段3);
//示例:
create index name_cardid_phone_index on member4(name,cardid,phone);
复制代码
适合在进行模糊查询的时候使用,可用于在一篇文章中检索文本信息。在MySQL5.6 版本以前FULLTEXT 索引仅可用于MyISAM 引擎,在5.6版本之后innodb 引擎也支持FULLTEXT 索引。
全文索引可以在CHAR、 VARCHAR 或者TEXT 类型的列上创建
。
CREATE FULLTEXT INDEX 索引名 ON 表名(列名);
create fulltext index name_fulltext on member(name);
复制代码
ALTER TABLE 表名 ADD FULLTEXT 索引名(列名);
alter table member add fulltext remark_index(remark);
复制代码
CREATE TABLE 表名(字段1 数据类型[,...], FULLTEXT 索引名(列名));
create table member4 (id int(10),name varchar(10),cardid int(18),phone int(11),address varchar(50),remark text,fulltext remark_index(remark));
复制代码
//插入数据
insert into member4 values(1, 'zhangsan' ,123123, 123123, 'nanjing', 'this is member!');
insert into member4 values(2, 'lisi', 456456, 456456, 'beijing','this is vip!');
insert into member4 values(3, 'wangwu', 789789, 78979, ' shanghai', 'this is vip member!');
复制代码
SELECT * FROM 表名 WHERE MATCH (列名) AGAINST ('查询内容');
//例:模糊查询
select * from member where match (remark) against('vip') ;
复制代码
DROP INDEX 索引名 ON 表名;
drop index name_index on member;
复制代码
ALTER TABLE 表名 DROP INDEX 索引名;
alter table member drop index cid_index;
复制代码
ALTER TABLE 表名 DROP PRIMARY KEY;
alter table member3 drop primary key;
复制代码
show index from 表名;
show keys from 表名;
//例:
show index from member\G
Table: member
Non_unique: 0
Key_name: cardid_index
Seq_in_index: 1
Column_name: cardid
Collation: A
Cardinality: 3
Sub_part: NULL
Packed: NULL
Null: YES
Index_type: BTREE
Comment:
Index_comment:
复制代码
Table: 表的名称。
Non_unique: 如果索引不能包括重复词,则为0; 如果可以,则为1。
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:备注。
复制代码
作用: 加快查询速度,对字段进行排序。
副作用:
索引需要占用额外的磁盘空间。
在插入和修改数据时要花费更多的时间、消耗更多性能,因为索引也要随之变动。
索引包含着对数据表里所有记录的引用指针。索引是一个排序的列表,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址。
使用索引后可以不用扫描全表来定位某行的数据,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据,因此能加快数据库的查询速度。
使用 explain 命令,即
explain select ...;
分析一下 这个 select语句是否使用了索引或者索引使用是否正确。如果没有用索引或者索引用得不正确,可以使用
create index 索引名 on 表名 (字段);
或者alter table 表名 add index 索引名(字段);
添加索引去优化查询速度。
事务是一种机制、一个操作序列
,包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求
,即这一组数据库命令要么都执行,要么都不执行。总结:所谓事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
ACID,是指在可靠数据库管理系统(DBMS) 中,事务(transaction)应该具有的四个特性:原子性(Atomicity) 、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)这是可靠数据库所应具备的几个特性。
指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生。
案例:
A给B转账100元钱的时候只执行了扣款语句,就提交了,此时如果突然断电,A账号已经发生了扣款,B账号却没收到加款,在生活中就会引起纠纷。这种情况就需要事务的原理
指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
案例说明:
对银行转帐事务,不管事务成功还是失败,应该保证事务结束后表中A和B的存款总额跟事务执行前一致。例如,A的账户有1000元,B的账户有1000元,现在A转账200元给B,不管事务成功还是失败,转账前后A和B的存款总额都应该是2000元。
指在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。
2.2.3.1 事务之间的相互影响
当多个客户端并发地访问同一个表时,可能出现下面的一致性问题:
可以通过添加事务的隔离级别解决上述的一致性问题。
2.2.3.2 事务的隔离级别
事务的隔离级别决定了事务之间可见的级别。
MySQL事务支持如下
四种隔离
,用以控制事务所做的修改,并将修改通告至其它并发的事务:
允许脏读,即允许一个事务可以看到其他事务未提交的修改。
允许一个事务只能看到其他事务已经提交的修改,未提交的修改是不可见的。防止脏读。
确保如果在一个事务中执行两次相同的SELECT语句,都能得到相同的结果,不管其他事务是否提交这些修改。可以防止脏读和不可重复读。
完全串行化的读,将一个事务与其他事务完全地隔离。每次读都需要获得表级共享锁,读写相互都会阻塞。可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的执行效率。
隔离级别 | 脏读取 | 不可重复读 | 幻像读 | 第一类丢失更新 | 第二类丢失更新 |
---|---|---|---|---|---|
未提交读 | 允许 | 允许 | 允许 | 禁止 | 允许 |
已提交读 | 禁止 | 允许 | 允许 | 禁止 | 允许 |
可重复读 | 禁止 | 禁止 | 对 InnoDB 禁止 | 禁止 | 禁止 |
串行读 | 禁止 | 禁止 | 禁止 | 禁止 | 禁止 |
mysql默认的事务处理级别是repeatable read,而Oracle和SQL Server是read committed 。
2.2.3.3 事务隔离级别的作用范围
事务隔离级别的作用范围分为两种:
- 全局级:对所有的会话有效
- 会话级:只对当前的会话有效(退出连接后即失效)
2.2.3.4 查询事务的隔离级别
variables 指变量, global variables 指全局变量。
show global variables like '%isolation%'; //方法一
SELECT @@global.tx_isolation; //方法二
//注释:
//like:表示模糊查询。
//'%isolation%':表示包含isolation字符串。
//'isolation%':以isolation字符串开头。
//'%isolation':以isolation字符串结尾。
复制代码
转存失败重新上传取消
session variables 指会话变量。
show session variables like '%isolation%'; //方法一
SELECT @@session.tx_isolation; //方法二
SELECT @@tx_isolation; //方法三
复制代码
全局级别设置之后,当前会话需要退出重新进入才会生效。
set global transaction isolation level 隔离级别; //永久生效
// 示例:
set global transaction isolation level read committed; //将全局事务隔离级别设置为提交读(RC)
//read uncommitted 未提交读
//read committed 提交读
//repeatable read 可重复读
//serializable 串行读
复制代码
会话事务隔离级别只对当前连接有效,退出连接后失效。在其他终端连接无效。
再次连接后会恢复为全局事务的隔离级别。
set session transaction isolation level 隔离级别;
//示例:
set session transaction isolation level read committed; //将会话事务隔离级别设置为提交读(RC)
复制代码
在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
总结:在事务管理中,原子性是基础,隔离性是手段,一致性是目的,持久性是结果。
BEGIN
或 START TRANSACTION: 显示地开启一个事务
。COMMIT
或 COMMITWORK:提交事务
,并使己对数据库进行的所有修改变为永久性的。ROLLBACK
或 ROLLBACK WORK:回滚会结束用户的事务
,并撤销正在进行的所有未提交的修改。SAVEPOINT S1
:使用 SAVEPOINT 允许在事务中创建一个回滚点
,一个事务中可以有多个SAVEPOINT: “S1"代表回滚点名称。ROLLBACK TO [SAVEPOINT] S1
: “S1"代表回滚点名称,把事务回滚到标记点
。show variables like 'autocommit';
set autocommit=0 | 1; // 0代表关闭自动提交事务,1代表开启
复制代码
开启自动提交事务,mysql会把每个sql语句当成一个事务然后自动commit提交
关闭自动提交事务,把在当前会话中的所有操作都当成一个事务直到执行commit 或 rollback
举例:终端一的操作会被立即提交,在终端二立刻显示
//插入数据
use can;
create table account (
id int(10) primary key not null,
name varchar(40),
money double);
insert into account values (1, 'A', 1000);
insert into account values (2, 'B', 1000);
复制代码
终端一开启一个事务,给A的money减100,再给B的money加100,
不提交事务
终端一开启一个事务,给A的money减100,再给B的money加100,
提交事务
终端一开启一个事务,给A的money减100,再给B的money加100,同时终端二也开启一个事务