数据库索引
- 是一个排序的列表,存储着索引值和这个值对应的物理地址,在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址(类似于C语言的链表通过指针指向数据记录的内存地址)
- 无需对整个表进行扫描,而是先通过索引表找到该行数据对应的物理地址然后访问相应的数据,因此能加快数据库的查询速度。
- 索引就好比是一本书的目录,可以根据目录中的页码快速找到所需内容。
- 索引是表中一列或者若干列值排序的方法。
- 建立索引的目的是为了加快对表中记录的查找或排序。
索引的作用
- 设置了合适的索引之后,数据库利用各种快速定位技术,能够大大加快查询速度,这是创建索引的最主要原因。
- 当表很大或查询设计到多个表时,使用索引可以成千上万倍提高查询速度。
- 可以降低数据库的I/O成本,并且索引还可以降低数据库的排序成本。(升序)
- 可以加快表与表之间的连接。
- 在使用分组和排序时,可大大减少分组和排序的时间。
- 建立索引在搜索和恢复数据库中的数据时能显著提高性能
1、加快表的查询速度 2、可以对字段进行排序
如何实现: 如果没有索引的情况下,要求查询某行数据,需要先扫描全表来定位某行数据。有索引后会通过查找条件的字段,找到其索引对应的行数据的物理地址,然后根据物理地址访问相应的数据。
索引的副作用
- 索引需要占用额外的磁盘空间
对于MyISAM引擎而言,索引文件和数据文件是分离的,索引文件用于保存数据记录的地址。
而InnoDB引擎的表数据文件本身就是索引文件。
- 更新一个包含索引的表需要比更新一个没有索引的表花费更多时间。这是由于索引本身也需要更新。因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引。
创建索引的原则依据
索引虽可以提升数据库查询的速度,但并不是任何情况下都适合创建索引。因为索引本身会消耗系统资源,在有索引的情况下,数据库会先进行索引查询,然后定位到具体的数据行,如果索引使用不当,反而会增加数据库的负担。
- 表的主键字段、外键字段必须有索引。因为主键具有唯一性,外键关联的是主表的主键,查询是可以快速定位。
- 记录数超过300行的表应该有索引,如果没有索引,每次查询都需要把表遍历一遍,会严重影响数据库的性能。
- 经常与其他表进行连接的表,在连接字段上应该建立索引。
- 在经常出现where自己的字段,特别是大表的字段,应该建立索引
- 在经常使用GROUP BY、ORDER BY的字段上建立索引
- 索引应该建立在选择性高的字段
- 索引应该建立在小字段,对于打的文字字段甚至超长字段,不需要索引。
- 唯一性太差的字段不适合建立索引
- 更新太频繁的字段不适合创建索引
表的主键字段、外键字段、多表链接字段、唯一性较好字段、不经常更新的字段、经常出现在where、group by、order by语句的字段、小字段
索引类型:
普通索引 create index 索引名 on 表名 (字段(LEN));
alter table 表名 add index 索引名(字段);
唯一索引 create unique 索引名 on 表名 (字段(LEN));
alter table 表名 add unique 索引名(字段);
主键索引 alter table 表名 add primary key(字段)
组合索引 create index 索引名 on 表名(字段1,字段2,字段3...)
alter table 表名 add index 索引名 (字段1.字段2...);
select 查询时 where语句中的条件字段,要与组合索引的字段排列顺序一致(最左原则)
全文索引 create fulltext index 索引名 on 表名(字段);
alter table 表名 add fulltext 索引名(字段);
select 字段 from 表 where match (字段) against (‘查询内容’); #模糊查询
(1)普通索引
- 直接创建索引
CREATE INDEX 索引名 ON 表名 (列名[(length)]);
#(列名(length)):length是可选项。如果忽略length的值,则使用整个列的值作为索引。如果指定,使用列的前length个字符来创建索引,这样有利于减小索引文件大小。在不损失精确性的情况下,长度越短越好。
#索引名建议以“_index”结尾
- 修改表方式创建索引
ALTER TABLE 表名 ADD INDEX 索引名 (列名);
(2)唯一索引:与普通索引相似,但区别是唯一索引列的每个值都唯一。唯一索引允许有空值(注意和主键不同)。如果使用组合索引创建,则列值的组合必须唯一。添加唯一键将自动创建唯一索引。
- 直接创建唯一索引
CREATE UNIQUE INDEX CARDID_INDEX ON MEMBER(CARDID);
- 修改表方式创建
ALTER TABLE MEMBER1 ADD UNIQUE PHONE_INDEX(PHONE);
(3)主键索引:是一种特殊的唯一索引,必须指定为“PRIMARY KEY”。一个表只能有一个主键,不允许有空值。添加主键将自动创建主键索引。
- 创建表的时候指定
CREATE TABLE 表名 ([...],PRIMARY KEY(列名) );
- 修改表方式创建
ALTER TABLE 表名 ADD PRIMARY KEY (列名);
- 删除索引
DROP INDEX NAME_INDEX ON MEMBER;
ALTER TABLE MEMBER DROP INDEX PHONE_INDEX;
(4)组合索引:单列索引与多累索引:可以是单列上创建的索引,也可以是在多列上创建的索引。需要满足最左原则,因为select语句的where条件试一次从左往右执行的,所以在使用select语句查询时,where条件使用的字段顺序必须组合索引中的排序一致,否则索引将不会生效。
CREATE TABLE 表名 (列名1 数据类型,列名2 数据类型,列名3 数据类型,INDEX 索引名(列名1,列名2,列名3));
ALTER TABLE MEMBER ADD INDEX NAME_CARDID_PHONE_INDEX('NAME','CARDID','PHONE');
查询时顺序也要保持一致:SELECT * FROM WHERE NAME='' AND CARDID='' AND PHONE=''
(5)全文索引(FULLTEXT):适合在进行模糊查询的时候使用,可用于在一篇文章中检索文本信息。全文索引可以在CAHR/VARCHAR或者TEXT类型的列上。
- 直接创建
CREATE FULLTEXT INDEX REMARK_INDEX ON MEMBER (REMARK);
- 修改表方式创建
ALTER TABLE MEMBER1 ADD FULLTEXT REMARK_INDEX (REMARK)
使用全文索引查询
SELECT * FROM 表名 WHERE MATCH (REMARK)
模糊查询
SELECT * FROM 表名 WHERE MATCH (REMARK)
查看索引
SHOW INDEX FROM MEMBER1\G
SHOW KEYS FROM MEMBER1\G
Table:表的名称
Non_unique:如果缩印不能包括重复词,则为0;如果可以,则为1
Seq_in_index:索引中的列序号,从1开始
column_name:列名称
collation:列以什么方式存储在索引中。在MySQL中,有值‘A’(升序)或NULL(无分类)
cardinality:索引中唯一值数目的估计值
sub_part: 如果类只是被部分的编入索引的字符的数目。如果整列被编入索引,则为NULL
packed:指示关键字如何被压缩。如果没有被压缩,则为NULL
Null:如果列含有NULL,则含有YES
EXPLAIN分析优化,显示了MySQL如何使用索引
explain select * from ‘EXAM_RESULT_SKILL_72’ where ‘USER_ID’=12233
分析MySQL加载速度慢:网络慢 (ping延迟,抓包看是否丢包) 系统性能原因 (CPU、I/O)、服务本身问题(优化配置文件:增加缓存、连接数)、语法问题、没有用索引
MySQL事务
- 事务是一种机制、一个操作序列,包含了一组数据库操作命令,并且把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行。
- 是一个不可分割的工作逻辑单元,在数据库系统上执行并发操作时,事物是最小的控制单元
- 事务适用与多个用户同时操作的数据库系统场景,如:银行保险工作
- 事务通过事务的整体性以保证数据的一致性。
- 事务能够提高在向表中更新和插入信息期间的可靠性。
说白了,所谓事务,他就是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。
事务的ACID的特点
ACID是指在可靠数据库管理系统DBMS中,事务(transaction)应该具有的四个特性:原子性(Atomicity)、一致性(consistency)、隔离性(Isolation)、持久性(Durability)
原子性:
- 指事务是一个不可再分割的工作单位,事务中的操作要么都发生,要么都不发生
- 事务是一个完整的操作,事物的各个元素是不可分的
- 事务中的所有元素必须作为一个整体提交或回滚。
- 如果事务中的任何元素失败,则整个事务将失败。
一致性:
- 指在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
- 当事务完成时,数据必须处于一致状态。
- 在事务开始前,数据库中存储的数据处于一致状态。
- 在正在进行的事务中,数据可能处于不一致的状态。
- 当事务成功完成时,数据必须再次回到已知的一致状态。
隔离性:
- 指在并发环境中,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间。
- 对数据进行修改的所有并发事务是彼此隔离的,表名事务必须是独立的,它不应以任何方式依赖于或影响其他事务。
- 修改数据的事务可在另一个使用相同数据的事务开始之前访问这些数据,或者在另一个使用相同数据的事务结束之后访问这些数据。
- 也就是说并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事物之间和数据库是独立的。
当第一个客户端并发访问同一个表时,可能会出现一致性问题:
脏读:当一个事务正在访问数据,并且对数据进行了修改,并且这修改还未提交到到数据库中,这时,另外一个事务也访问了这个数据,然后使用了这个数据。
不可重复读:指在一个事务内,多次读同一数据。在这个事务还没有结束时,另外一个事务也访问该同一数据。那么,在第一个事务的两次读取之间,由干第一个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样就发生了在一个事务两次读到的数据是不一样的,因此称为是不可重复读。
幻读:一个事各对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,另一个事务也修改这个表中的数据。这种修改是向表中插入一行新数据。那么,操作前一个事务的用户会发现表中还有一个没有修改的数据行,就好象发生了幻觉一样
丢失更新:两个事务同时读取同一条记录,A先修改记录,B也修改记录(B不知道A修改过),B提交数据后B的修改结果覆盖了A的修改结果。
//事务的隔离级别决定了事物之间可见的级别。
MySQL事务支持如下四种隔离,用以控制事务所做的修改,并将修改通告至其他并发的事务:
(1) 未提交读(Read ncommitted (Ru) ):允许脏读,即允许一个事务可以看到其他事务未提交的修改。
(2) 提交读(Read Committed (RC) ):允许一个事务只能看到其他事务已经提交的修改,未提交的修改是不可见的。防止脏读。
(3) 可重复读(Repeatable Read(RR) ): ---mysql默认的隔离级别
确保如果在一个事务中执行两次相同的SELECT语句,都能得到相同的结果,不管其他事务是否提交这些修改。可以防止脏读和不可重复读。
(4) 串行读(Serializable):---相当于锁表
完全串行化的读,将一个事务与其他事务完全地隔离。每次读都需要获得表级共享锁,读写相互都会阳塞。可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的效率。
mysql默认的事务处理级别是 repeatable read ,而oracle和sOL Server是 read committed。
//事务隔离结的作用范围分为两种:
全局级:对所有的会话有效
会话级:只对当前的会话有效
查询会话事务隔离级别:
show global variables like '%isolation%';
select @@global.tx_isolation;
修改运行级别
set global transaction isolation level read uncommitted;
mysql>begin; #开始事务
mysql>rollback; #撤回,回滚
mysql>commit; #提交操作
持久性:
在事务完成以后,该事务所对数据库所做的更改便持久的保存在数据库之中,并不会被回滚。
指不管系统是否发生故障,事务处理的结果都是永久的。
一旦事务被提交,事物的结果就会被永久的保留在数据库中。
总结:在事务管理中,原子性是基础,隔离性是手段,一致性是目的,持久性是结果。
事务控制语句
- BEGIN 或 START TRANSACTION:显式地开启一个事务
- COMMIT 或 COMMIT WORK:提交事务,并使以对数据库进行的所有修改变为永久性的。
- ROLLBACK 或 ROLLBACK WORK: 当前事务结束,并且撤销正在进行的所有未提交的修改
- SAVEPOINT S1; 或 SAVEPOINT 允许在事务中创建一个回滚点,一个事物可以有多个SAVAPOINT
ROLLBACK TO S1; #事务没有结束
show variables like 'autocommit'; 数据库自动提交
set autocommit=0; 关闭自动提交