05MySQL的索引、存储引擎和事物

一、MySQL的索引

索引是通过某种算法,构建出一个数据模型,用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速到达一个位置去搜索数据文件,而不必查看所有数据,那么将会节省很大一部分时间。

索引的优点:

  • 大大加快数据的查询速度
  • 使用分组和排序进行数据查询时,可以显著减少查询时分组和排序的时间
  • 创建唯一索引,能够保证数据库表中每一行数据的唯一性
  • 在实现数据的参考完整性方面,可以加速表和表之间的连接

索引的缺点

  • 创建索引和维护索引需要消耗时间,并且随着数据量的增加,时间也会增加

  • 索引需要占据磁盘空间

  • 对数据表中的数据进行增加,修改,删除时,索引也要动态的维护,降低了维护的速度

创建索引的原则

  • 更新频繁的列不应设置索引

  • 数据量小的表不要使用索引

  • 重复数据多的字段不应设为索引,一般来说:重复的数据超过百分之15就不该建索引

  • 首先应该考虑对where 和 order by 涉及的列上建立索引

1.1 索引的分类

索引是存储引擎用来快速查找记录的一种数据结构,按照实现的方式类分,主要有Hash索引和B+Tree索引

图片.png
图片.png

按照功能划分,索引划为以下分类:

  • 单列索引:一个索引只包含单个列,但一个表中可以有多个单列索引;
    • 普通索引:MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。
    • 唯一索引:唯一索引与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。它有以下几种创建方式:
    • 主键索引:每张表一般都会有自己的主键,当我们在创建表时,MySQL会自动在主键列上建立一个索引,这就是主键索引。主键是具有唯一性并且不允许为NULL,所以他是一种特殊的唯一索引。
  • 组合索引:组合索引也叫复合索引,指的是我们在建立索引的时候使用多个字段,例如同时使用身份证和手机号建立索引,同样的可以建立为普通索引或者是唯一索引。复合索引的使用复合最左原则。
  • 全文索引:全文索引主要用来查找文本中的关键字,而不是直接与索引中的值相比较,它更像是一个搜索引擎,基于相似度的查询,而不是简单的where语句的参数匹配。
  • 空间索引:空间索引是对空间数据类型的字段建立的索引,MYSQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON。

1.2 单列索引的操作

1.2.1 普通索引

1.2.1.1 创建索引

-- 方式1-创建表的时候直接指定
create  table student(
    name varchar(20),
    -- 省略部分代码
    index index_name(name) -- 给name列创建索引
);

-- 方式2-直接创建
create index indexname on tablename(columnname); 

-- 方式3-修改表结构(添加索引)
alter table tablename add index indexname(columnname)

1.2.1.2 查看索引

-- 1、查看数据库所有索引 
select * from mysql.`innodb_index_stats` a where a.`database_name` = '数据库名'; 

-- 2、查看表中所有索引 
select * from mysql.`innodb_index_stats` a where a.`database_name` = '数据库名' and a.table_name like '%表名%'; 

-- 3、查看表中所有索引 
show index from table_name; 

1.2.1.3 删除索引

-- 方法1
drop index 索引名 on 表名 

-- 方法2
alter table 表名 drop index 索引名 

1.2.2 唯一索引

1.2.2.1 创建索引

-- 方式1-创建表的时候直接指定
create  table student2(
    card_id varchar(20),
    -- 省略部分代码
    unique index_card_id(card_id) -- 给card_id列创建索引
);

-- 方式2-直接创建
create unique index 索引名 on 表名(列名) 

-- 方式3-修改表结构(添加索引)
alter table 表名 add unique [索引名] (列名)

1.2.2.2 删除索引

-- 方法1
drop index index_card_id on student2 

-- 方法2
alter table student2 drop index index_phone_num

1.3 组合索引

-- 创建索引的基本语法-- 普通索引
create index indexname on table_name(column1(length),column2(length)); 

-- 操作-删除索引
 drop index index_phone_name on student; 
 
-- 创建索引的基本语法-- 唯一索引
create  unique index index_phone_name on student(phone_num,name); 

1.4 全文索引

全文索引的关键字是fulltext,MySQL 中的全文索引,有两个变量,最小搜索长度和最大搜索长度,对于长度小于最小搜索长度和大于最大搜索长度的词语,都不会被索引。通俗点就是说,想对一个词语使用全文索引搜索,那么这个词语的长度必须在以上两个变量的区间内。这两个的默认值可以使用以下命令查看:

show variables like '%ft%';

参数解释如下表

# 参数名称 默认值 最小值 最大值 作用
1 ft_min_word_len 4 1 3600 MyISAM 引擎表全文索引包含的最小词长度
2 ft_query_expansion_limit 20 0 1000 MyISAM引擎表使用 with query expansion 进行全文搜索的最大匹配数
3 innodb_ft_min_token_size 3 0 16 InnoDB 引擎表全文索引包含的最小词长度
4 innodb_ft_max_token_size 84 10 84 InnoDB 引擎表全文索引包含的最大词长度

操作如下

-- 修改表结构添加全文索引
alter table t_article add fulltext index_content(content)
 
-- 直接添加全文索引
create fulltext index index_content on t_article(content);

使用全文索引使用 match 和 against 关键字,格式:

match (col1,col2,...)  against(expr [search_modifier])

1.5 空间索引

  • MySQL在5.7之后的版本支持了空间索引,而且支持OpenGIS几何数据模型

  • 空间索引是对空间数据类型的字段建立的索引,MYSQL中的空间数据类型有4种,分别是GEOMETRY、POINT、LINESTRING、POLYGON。

  • MYSQL使用SPATIAL关键字进行扩展,使得能够用于创建正规索引类型的语法创建空间索引。

  • 创建空间索引的列,必须将其声明为NOT NULL。

类型 含义 说明
Geometry 空间数据 任何一种空间类型
Point 坐标值
LineString 线 有一系列点连接而成
Polygon 多边形 由多条线组成

例如:

create table shop_info (
  id  int  primary key auto_increment comment 'id',
  shop_name varchar(64) not null comment '门店名称',
  geom_point geometry not null comment '经纬度',
  -- 空间索引
  spatial key geom_index(geom_point)
);

二、MySQL的存储引擎

数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。MySQL的核心就是存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎

可以使用 SHOW ENGINES 命令 可以查看Mysql的所有执行引擎我们 可以看到默认的执行引擎是innoDB,支持事务,行级锁定和外键。

图片.png
  • MyISAM:Mysql 5.5之前的默认数据库引擎,最为常用。拥有较高的插入,查询速度,但不支持事务
  • InnoDB:事务型速记的首选引擎,支持ACID事务,支持行级锁定,MySQL5.5成为默认数据库引擎
  • Memory: 所有数据置于内存的存储引擎,拥有极高的插入,更新和查询效率。但是会占用和数据量成正比的内存空间。并且其内容会在MYSQL重新启动是会丢失。
  • Archive :非常适合存储大量的独立的,作为历史记录的数据。因为它们不经常被读取。Archive 拥有高效的插入速度,但其对查询的支持相对较差
  • Federated :将不同的 MySQL 服务器联合起来,逻辑上组成一个完整的数据库。非常适合分布式应用
  • CSV :逻辑上由逗号分割数据的存储引擎。它会在数据库子目录里为每个数据表创建一个 .csv 文件。这是一种普通文本文件,每个数据行占用一个文本行。CSV 存储引擎不支持索引。
  • BlackHole: 黑洞引擎,写入的任何数据都会消失,一般用于记录 binlog 做复制的中继
  • ERFORMANCE_SCHEMA存储引擎该引擎主要用于收集数据库服务器性能参数。
  • Mrg_Myisam Merge存储引擎,是一组MyIsam的组合,也就是说,他将MyIsam引擎的多个表聚合起来,但是他的内部没有数据,真正的数据依然是MyIsam引擎的表中,但是可以直接进行查询、删除更新等操作。

一些引擎用的操作如下:

-- 查询当前数据库支持的存储引擎:
show engines;
 
-- 查看当前的默认存储引擎:
show variables like ‘%storage_engine%’;

-- 查看某个表用了什么引擎(在显示结果里参数engine后面的就表示该表当前用的存储引擎): 
show create table student; 
 
-- 创建新表时指定存储引擎:
create table(...) engine=MyISAM;
 
-- 修改数据库引擎
alter table student engine = INNODB;
alter table student engine = MyISAM;

三、MySQL的事物

3.1 概述

数据库存储引擎是数据库底层软件组织,数据库管理系统(DBMS)使用数据引擎进行创建、查询、更新和删除数据。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能。现在许多不同的数据库管理系统都支持多种不同的数据引擎。MySQL的核心就是存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎

可以使用 SHOW ENGINES 命令 可以查看Mysql的所有执行引擎我们 可以到 默认的执行引擎是innoDB 支持事务,行级锁定和外键。

在MySQL中的事务(Transaction)是由存储引擎实现的,在MySQL中,只有InnoDB存储引擎才支持事务。事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。事务用来管理 DDL、DML、DCL 操作,比如 insert,update,delete 语句,默认是自动提交的。

3.2 事物的操作

  • 开启事务:Start Transaction

    • 任何一条DML语句(insert、update、delete)执行,标志事务的开启
    • 命令:BEGIN 或 START TRANSACTION
  • 提交事务:Commit Transaction

    • 成功的结束,将所有的DML语句操作历史记录和底层硬盘数据来一次同步
    • 命令:COMMIT
  • 回滚事务:Rollback Transaction

    • 失败的结束,将所有的DML语句操作历史记录全部清空
    • 命令:ROLLBACK

之前的所有SQL操作其实也有事务,只是MySQL自动帮我们完成的,每执行一条SQL时MySQL就帮我们自动提交事务,因此如果想要手动控制事务,则必须关闭MySQL的事务自动提交。在MySQL中直接用 SET 来改变 MySQL 的自动提交模式:

select @@autocommit;
set autocommit=0 禁止自动提交 
set autocommit=1 开启自动提交 

3.3 事物的隔离级别

  • 读未提交(Read uncommitted):一个事务可以读取另一个未提交事务的数据,最低级别,任何情况都无法保证,会造成脏读。
  • 读已提交(Read committed):一个事务要等另一个事务提交后才能读取数据,可避免脏读的发生,会造成不可重复读。
  • 可重复读(Repeatable read):就是在开始读取数据(事务开启)时,不再允许修改操作,可避免脏读、不可重复读的发生,但是会造成幻读。
  • 串行(Serializable):是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

Mysql的默认隔离级别是Repeatable read。

-- 查看隔离级别 
show variables like '%isolation%'; 

-- 设置隔离级别
/*
set session transaction isolation level 级别字符串
级别字符串:read uncommitted、read committed、repeatable read、serializable
*/
-- 设置read uncommitted
set session transaction isolation level read uncommitted;
 
-- 设置read committed
set session transaction isolation level read committed;
 
-- 设置repeatable read
set session transaction isolation level repeatable read;
 
-- 设置serializable
set session transaction isolation level serializable;

事务A 按照一定条件进行数据读取, 期间事务B 插入了相同搜索条件的新数据,事务A再次按照原先条件进行读取时,发现了事务B 新插入的数据 称为幻读

如果事务A 按一定条件搜索, 期间事务B删除了符合条件的某一条数据,导致事务A 再次读取时数据少了一条。这种情况归为不可重复读

四、MySQL的锁机制

4.1 概述

锁是计算机协调多个进程或线程并发访问某一资源的机制(避免争抢)。在数据库中,除传统的计算资源(如 CPU、RAM、I/O 等)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。从这个角度来说,锁对数据库而言显得尤其重要,也更加复杂。

锁有以下几种分类

  1. 从对数据操作的粒度分 :
  • 表锁:操作时,会锁定整个表。
  • 行锁:操作时,会锁定当前操作行
  1. 从对数据操作的类型分:
  • 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。
  • 写锁(排它锁):当前操作没有完成之前,它会阻断其他写锁和读锁。

4.2 MySQL锁的特点

相对其他数据库而言,MySQL的锁机制比较简单,其最显著的特点是不同的存储引擎支持不同的锁机制。

存储引擎 表级锁 行级锁
MyISAM 支持 不支持
InnoDB 支持 支持
MEMORY 支持 不支持
BDB 支持 不支持

MySQL锁的特性可大致归纳如下 :

锁类型 特点
表级锁 偏向MyISAM存储引擎,开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低
行级锁 偏向InnoDB存储引擎,开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率最低,并发度也最高

仅从锁的角度来说:

  • 表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如Web 应用;

  • 行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并查询的应用,如一些在线事务处理(OLTP)系统。

4.3 MyISAM表锁

MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT 等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预,因此,用户一般不需要直接用 LOCK TABLE 命令给 MyISAM 表显式加锁

-- 加读锁 : 
lock table table_name read; 
-- 加写锁 : 
lock table table_name write;

表锁特点:

  • 对MyISAM 表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;
  • 对MyISAM 表的写操作,则会阻塞其他用户对同一表的读和写操作;

此外,MyISAM 的读写锁调度是写优先,这也是MyISAM不适合做写为主的表的存储引擎的原因。因为写锁后,其他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远阻塞。

4.4 InnoDB行锁

InnoDB 与 MyISAM 的最大不同有两点:一是支持事务;二是 采用了行级锁。InnoDB 实现了以下两种类型的行锁:

  • 共享锁(S):又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
  • 排他锁(X):又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据就行读取和修改。

对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁(X);而对于普通SELECT语句,InnoDB不会加任何锁;可以通过以下语句显示给记录集加共享锁或排他锁 。

-- 共享锁(S):
SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE 
-- 排他锁(X) :
SELECT * FROM table_name WHERE ... FOR UPDATE

你可能感兴趣的:(05MySQL的索引、存储引擎和事物)