事务、索引和存储引擎

一、存储引擎

  1. InnoDB 默认的存储引擎,也是所有存储引擎中唯一支持事务、XA协议的存储引擎。

  2. MyISAM 基于ISAM(Indexed Sequential Access Method目前已经废弃)的存储引擎,特点是查询效率较高。但不支持事务和容错性。

  3. MEMORY 纯内存型型存储引擎。所有数据都在内存中,硬盘只存储.frm文件。所以当MySQL宕机或非法关闭时只生效表结构。当然了,由于所有数据都在内存上,所以相对来说性能较高。

  4. MRG_MYISAM 以前也叫MERGE,简单理解就是对MyISAM表做了特殊的封装,对外提供单一访问入口,减少程序的复杂性。

  5. ARCHIVE存储引擎主要用于通过较小的存储空间来存放过期的很少访问的历史数据。ARCHIVE表不支持索引,通过一个.frm的结构定义文件,一个.ARZ的数据压缩文件还有一个.ARM的meta信息文件。由于其所存放的数据的特殊性,ARCHIVE表不支持删除,修改操作,仅支持插入和查询操作。

  6. BLACKHOLE 俗称“黑洞”存储引擎。是一个非常有意思的存储引擎。所有的数据都是有去无回。

  7. CSV存储引擎实际上操作的就是一个标准的CSV文件,他不支持索引。起主要用途就是大家有些时候可能会需要通过数据库中的数据导出成一份报表文件,而CSV文件是很多软件都支持的一种较为标准的格式,所以我们可以通过先在数据库中建立一张CSV表,然后将生成的报表信息插入到该表,即可得到一份CSV报表文件了。

  8. PERFORMANCE_SCHEMA 从MySQL 5.6新增的存储引擎。主要用于收集一些系统参数。

二、事务控制(DCL)

开启事务 关闭事务 主动回滚
数据库中 start transaction commit rollback
Java文件中 Connection.setAntoCommit(false) Connection.commit() Connection.rollback()

(1)事务:

事务是一个整体, 由一条或者多条SQL语句组成, 这些SQL语句要么都执行成功, 要么就失败, 只要有一条SQL出现异常, 整个操作就会回滚。

(2)回滚:

就是事务运行的过程中发生了某种故障, 或者SQL出现了异常, 事务不能继续执行, 系统将事务中对数据库的所有已完成的操作全部取消, 回滚到事务开始时的状态。

三、事务的特性ACID

  • 原子性(Atomicity) 一个事务要么全部提交成功,要么全部失败回滚,不能只执行其中的一部分操作,这就是事务的原子性。

  • 一致性(Consistency) 指事物必须是数据库从一个一致性状态到另一个一致性状态。也就是说一个事物执行之前和执行之后都必须处于一致性状态。

  • 隔离性(Isolation) 事务的隔离性是指在并发环境中,并发的事务时相互隔离的,一个事务的执行不被其他事务干扰。即并发执行的各个事务之间不相互干扰。

  • 持久性(Durability) 一旦事务提交,那么它对数据库中的对应数据的状态的变更就会永久保存到数据库中。即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束的状态。

 四、事务的隔离级别

(1)并发访问的问题

事务、索引和存储引擎_第1张图片

 (2)事务的隔离级别

事务、索引和存储引擎_第2张图片

重点注意:隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。

MVCC:版本控制+快照机制。

(3)隔离级别相关命令

查看隔离级别:select @@transaction_isolation;

设置隔离级别:set session transaction isolation level 隔离级别名称;

set session transaction isolation level read uncommitted;

(4)锁

共享锁又称读锁,表示在读取数据时不允许其他事务对数据进行修改

sql:select...lock in share mode;

排它锁又称独占锁。在一个事务操作时,其他事务不允许操作数据。

sql:update(|insert|delete)...for update;

五、索引

(1)什么是索引:索引类似图书的目录,一种数据结构,通过索引可以快速的找到需要查询的内容。

(2)索引的结构:索引在数据库底层有两种结构:BTree和Hash。默认使用的是BTree。

(3)Hash结构:Hash底层实现是由Hash表来实现的,是根据键值 存储数据的结构。非常适合根据key查找value值,也就是单个key查询,或者说等值查询。

缺点:

  1. 哈希表是把索引字段映射成对应的哈希码然后再存放在对应的位置,这样的话,如果我们要进行模糊查找的话,显然哈希表这种结构是不支持的,只能遍历这个表

  2. 适合于精确的查找, 也不适合范围查询。

(4)BTree结构:BTree分为B-Tree和B+Tree, MySQL数据库索引采用的B+Tree, B+Tree是在B-Tree上做了优化改造。

(5)B-Tree结构

  • 索引值和data(数据)分布在整棵树结构中

  • 每个节点可以存放多个索引值以及对应的data(数据)

  • 树节点中的多个索引值从左到右升序排列 

缺点: 所有的节点都存放数据, 数据会占用空间, 导致存放的索引变少。  

(6)B+Tree结构

  • 非叶子节点不存储data数据,只存储索引值,这样便于存储更多的索引值

  • 叶子节点包含了所有的索引值和data数据

  • 叶子节点用指针连接,提高区间的访问性能

范围查找特性:相比B-树,B+树进行范围查找时,只需要查找定位两个节点的索引值,然后利用叶子节点的指针进行遍历即可。而B-树需要遍历范围内所有的节点和数据,显然B+Tree效率高。

(7)索引的优点

  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。

  • 可以大大加快数据的检索速度,这也是创建索引的最主要的原因。

  • 可以加速表和表之间的连接,特别是在实现数据的完整性方面特别有意义。(外键)

  • 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。

  • 通过使用索引,可以在查询的过程中,使用查询优化器,提高系统的性能。

(8)索引的缺点 

  • 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。

  • 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间。如果要建立聚簇索引,那么需要的空间就会更大。

  • 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

(9)什么字段适合创建索引 

  1. 在经常需要搜索的列上,可以加快搜索的速度;

  2. 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;

  3. 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度;

  4. 在经常需要根据范围进行搜索的列上创建索引,因为索引已经排序,其指定的范围是连续的;

  5. 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序查询时间;

  6. 在经常使用在WHERE子句中的列上面创建索引,加快条件的判断速度。

(10)什么字段不适合创建索引

  1. 对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

  2. 对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。

  3. 对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。

  4. 当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

六、索引分类及使用

-- 查看表中的索引

show index from 表名;

(1)索引分为单列索引组合索引

单列索引就是只是给某个列加索引;组合索引是给表中大于等于两个列添加索引。

(2)单列索引:又分为主键索引、普通索引和唯一索引。

主键索引:

  • 它是一种特殊的唯一索引,不允许有空值

  • 在创建或修改表时添加主键约束即可,添加了主键约束就会自动创建主键索引

  • 每个表只能有一个主键约束, 所以一张表只能有一个主键索引

普通索引:这是最基本的索引类型,基于普通字段建立的索引,没有任何限制。

创建方式:

-- 1. 创建表时创建普通索引
create table 表名(
   字段1 类型,
   ...,
   index [索引名称](字段名) -- 不指定索引名称,自动生成
);

-- 2. 为创建好的表添加普通索引
alter table 表名 add index [索引名称](字段名); -- 不指定索引名称,自动生成

-- 3. 为创建好的表添加普通索引
create index <索引名称> on 表 (字段名); -- 必须指定索引名称

唯一索引:与"普通索引"类似,不同的就是:索引字段的值必须唯一,但允许有空值。在创建或修改表时追加唯一约束,就会自动创建对应的唯一索引。

-- 创建表时指定唯一约束,会自动创建唯一索引
create table 表名(
   字段1 类型 unique,
   ...
);
    
-- 为创建好的表添加唯一索引
alter table 表名 add unique index [索引名称](字段名);

-- 为创建好的表添加唯一索引
create unique index <索引名称> on 表名(字段名);

(3)组合索引:

-- 语法格式:
create index 索引名 on 表名(列1,列2...)

create index index3 on demo(col1,col2,col3)

给表中大于等于两个列添加索引。但是需要满足最左前缀,创建组合索引相当于创建了多个索引,一般把最常用的放在最左边。

此时相当于创建col1、col1-col2、col1-col2-col3、col1-col3四个索引。

(4)全文索引:他们可以从CHAR、VARCHAR或TEXT列中作为CREATE TABLE语句的一部分被创建,或是随后使用ALTER TABLE 或CREATE INDEX被添加。

特点:对于较大的数据集,将你的数据输入一个没有FULLTEXT索引的表中,然后创建索引,其速度比把数据输入现有FULLTEXT索引的速度更为快。不过切记对于大容量的数据表,生成全文索引是一个非常消耗时间非常消耗硬盘空间的做法。

-- 方式1
CREATE FULLTEXT INDEX index_name ON table_name(column(length));
-- 方式2
ALTER TABLE table_name ADD FULLTEXT index_name( column);
-- 方式3
CREATE TABLE table_name (
    id int not null auto_increment,
    title varchar(30) ,
    PRIMARY KEY(id) ,  
    FULLTEXT  index_name (title)
);

使用方式:创建好的全文索引需要配合match(列[,列]) against(‘内容’)使用。

select * from tb_fulltext where match(name) against('yizhuang');

against中内容有三种模式:

  • 自然语言模式:IN NATURAL LANGUAGE MODE

  • 布尔模式:IN BOOLEAN MODE

  • 查询扩展模式:WITH QUERY EXPANSION

1.自然语言模式(默认):文本按照空格拆分,必须严格匹配,并且against中的字符数要大于2全文索引才会生效。

2.布尔模式:支持特殊符号。即使对没有全文索引的列也可以进行搜索,但是非常慢。查询时必须从最左开始查询,例如:北京昌平,按照昌平无法查询。

select * from tb_fulltext where match(address) against('daxin*' in boolean mode);

理解:表中有三条数据,daxin beijing,daxinbeijing,beijing daxin,执行上面语句能查询到前两条数据。

3.查询扩展:查询时进行扩展查询,发现和条件有关系的内容都查询出来

select * from tb_fulltext where match(address) against('daxing' with query expansion);

理解:表中有三条数据,zs ls,ls wu,wu ls那么使用查询扩展查询zs结果三条数据都能查出

4.中文拆词器

可以设置把整个中文按照指定大小进行拆词。设置步骤如下:

1.在my.ini中[mysqld]下添加参数,设置拆词长度(根据自己的需求进行完成即可)

 ngram_token_size=2

2.给address创建全文索引。注意后面的with parser ngram

create fulltext index index3 on ft(address)  with parser ngram;

(5)聚簇索引和非聚簇索引

聚集和非聚集最主要的区别就是索引是否和数据在一起。

聚集索引(聚簇索引)之所以叫“聚集”是因为索引和数据一起存储。叶子节点中存储索引和数据。因为数据顺序和索引顺序是一样的,且顺序存储,所以查询速度比较快。当然了因为有顺序的所以新增需要重新排序会影响速度。简单记忆:主键索引就是聚集索引。

非聚集索引之所以叫“非聚集”是因为叶子节点中只存储主键和索引列。所以在非聚集索引查询时需要通过主键再去查询想要的数据。在叶子节点上通过主键查询数据的过程就是所谓的回表。

七、count(*),count(列),count(1)的区别

  • 在InnoDB引擎中count(*)和count(1)性能没有什么差别

  • count(列)需要看列和count(*)优化后的列情况,如果count(列)使用了非索引列,而表中包含索引列则count(*)更快。如果count(列)和count(*)优化后的是同一个列则性能没有什么差别。如果表中没有索引则count(列)和count(*)性能也没有什么差别。

八、索引优化 

1.使用短索引(前缀索引):对串列进行索引,如果可能应该指定一个前缀长度。

CREATE INDEX  index_name  ON  table_name (column(length));

2.索引列排序:MySQL查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。

3.like语句操作:一般情况下不鼓励使用like操作,如果非使用不可,如何使用也是一个问题。like “%aaa%” 不会使用索引,而like “aaa%”(非前导模糊查询)可以使用索引。使用后,优化到range级别。

4.不要在列上进行运算:例如:select * from users where YEAR(adddate)<2007,将在每个行上进行运算,这将导致索引失效而进行全表扫描,因此我们可以改成:select * from users where adddate<’2007-01-01′。

5.范围列可以使用索引:范围列可以用到索引(联合索引必须是最左前缀),但是范围列后面的列无法用到索引,索引最多用于一个范围列,如果查询条件中有两个范围列则无法全用到索引。所以where中把最主要的查询条件放在第一个。

6.类型转换会导致索引无效:当列是文本类型时,把数值类型当作列的条件会弃用索引。

总结:MySQL只对以下操作符才使用索引:<,<=,=,>,>=,between,in,以及某些时候的like(不以通配符%或_开头的情形)。而理论上每张表里面最多可创建16个索引,不过除非是数据量真的很多,否则过多的使用索引也不是那么好玩的。

建议:一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要。

九、视图

(1)什么是视图

  1. 视图是一种虚拟表

  2. 视图建立在已有表的基础上, 视图建立依赖的这些表称为基表

  3. 向视图提供数据内容的语句为 SELECT 语句, 可以将视图理解为存储起来的 SELECT 语句

  4. 视图向用户提供基表数据的另一种表现形式

(2) 视图的作用

  1. 视图本身就是一条查询SQL, 我们可以将一次复杂的查询构建成一张视图, 用户只要查询视图就可以获取想要得到的信息(不需要再编写复杂的SQL), 可以理解为查询视图就相当于将创建视图的SQL再次执行一次

  2. 视图主要就是为了简化多表的查询

(3)创建视图:create view 视图名称 as select语句; 

(4)删除视图:drop view 视图名称;

(5)视图与表的区别

  • 视图是建立在表的基础上,表存储数据库中的数据,而视图只是做一个数据的展示

  • 通过视图不能改变表中数据(一般情况下视图中的数据都是表中的列 经过计算得到的结果,不允许 更新)

  • 删除视图,表不受影响,而删除表,视图不再起作用

十、数据控制语言(DCL)

(1)用户管理

-- 查询所有用户
use mysql;
select * from user;

-- 创建用户
create user '用户名'@'主机名' identified by '密码'; 
-- 主机名: localhost 只能本机连接  % 所有都可以连接

-- 修改用户密码
ater user '用户名'@'主机名' identified by '密码';

-- 删除用户
drop user '用户名'@'主机名'; 

(2)权限管理

-- 为某个用户授权
grant 权限1, 权限2 ... on 数据库名.表名 to '用户名'@'主机名';

-- 查看某个用户有哪些权限
show grants for '用户名'@'主机名';

-- 撤销用户权限
revoke 权限1, ... on 数据库名.表名 from '用户名'@'主机名';

-- 刷新权限(添加, 撤销授权之后一定要刷新权限)
flush privileges;

(3)角色管理

-- 创建角色
create role '角色名称', ...;

-- 为角色授权
grant 权限1, 权限2, ... on 数据库名.表名 to '角色名称';

-- 为用户分配角色
grant '角色名称' to '用户名'@'主机名';

-- 撤销角色的权限
revoke 权限1, ... on 数据库名.表名 from '角色名称';

你可能感兴趣的:(数据库,sql,mysql)