跟孙哥学java
存储引擎
存储引擎简介
存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所以存储引擎也可被称为表类型。 查询表的存储引擎,通过查询建表语句
show create table user;
--查询当前数据库支持的存储引擎:
show engines;
--创建一个以MyISAM存储引擎的表
create table my_myisam(
id int,
name varchar(10)
) engine =MyISAM;
show create table my_myisam;
--创建一个以MEMORY存储引擎的表
create table my_memory(
id int,
name varchar(10)
) engine =MEMORY;
:::info 1.在创建表时,指定存储引擎 CREATE TABLE表名( 字段1字段1类型[COMMENT字段1注释], 5595: 字段n字段n类型 [COMMENT字段n注释] )ENGINE=INNODB[COMMENT表注释] 2.查看当前数据库支持的存储引擎 SHOW ENGINES :::
存储引擎特点
InnoDB
- 介绍
InnoDB是一种兼顾高可靠性和高性能的通用存储引擎,在MySQL5.5之后,InnoDB是默认的MySQL存储引擎。
- 特点
DML操作遵循ACID模型,支持事务; 行级锁,提高并发访问性能: 支持外键FOREIGN KEY约束,保证数据的完整性和正确性;
- 文件
XXX.ib:xx代表的是表名,innoDBi引擎的每张表都会对应这样一个表空间文件,存储该表的表结构(frm、sdi)、数据和索引。
参数:innodb_file_per_table
MyISAM
介绍 MyISAM是MySQL早期的默认存储引擎。 特点 不支持事务,不支持外键 支持表锁,不支持行锁 访问速度快 文件 Xx.sdi:存储表结构信息 Xx.MYD:存储数据 Xx.MYI:存储索引 Memory 介绍 Memoryi引擎的表数据时存储在内存中的,由于受到硬件问题、或断电问题的影响,只能将这些表作为临时表或缓存使用。 特点 内存存放 hash索引(默认)】 文件 x.sdi:存储表结构信息
存储引擎选择
在选择存储引擎时,应该根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统,还可以根据实际情况选择多种存储引擎进行组 合。
InnoDB:是Mysql的默认存储引擎,支持事务、外键。如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包含很多的更新、删除操作,那么InnoDB存储引擎是比较合适的选择。 MyISAM:如果应用是以读操作和插入操作为主,只有很少的更新和删除操作,并且对事务的完整性、并发性要求不是很高,那么选择这个存储引擎是非常合适的。 MEMORY:将所有数据保存在内存中,访问速度快,通常用于临时表及缓存。MEMORY的缺陷就是对表的大小有限制,太大的表无法缓存在内存中,而且无法保障数据的安全性。
总结
索引
索引概述
介绍
索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法,这种数据结构就是索引。
演示
优缺点
索引结构
MySQL的索引是在存储引擎层实现的,不同的存储引擎有不同的结构,主要包含以下几种:
一般默认就是B+tree索引
所有数据都会出现在叶子节点
叶子节点形成一个单向列表
为什么InnoDB存储引擎选择使用B+tree索引结构?
相对于二叉树,层级更少,搜索效率高; 对于B-tree,无论是叶子节点还是非叶子节点,都会保存数据,这样导致一 页中存储的键值减少,指针跟着减少,要同样保存大量数据,只能增加树的 高度,导致性能降低; 相对Hash索引,hash索引只支持等值匹配,B+tree支持范围匹配及排序操作;
索引分类
聚集索引,叶子节点保存了一行的数据,而二级索引,存储的是主键的索引
思考?
第一条语句的效率高,因为第一条只需要到聚集索引去找到行数据
而第二条数据需要先走name的二级索引查找对应的id值,再到聚焦索引去找行数据,需要回表查询
每一个节点都是存储在一个页中
高度为2: n8+(n+1)6=161024 (16k,一页) n=1170
它能够存储的数据量为 117116=18736
高度为3:11711171*16=21939856
索引语法
- 创建索引
CREATE [UNIQUE| FULLTEXT] INDEX index_name ON table_name index_col_name,...)
- 查看索引
SHOW INDEX FROM table name
- 删除索引
DROP INDEX index name ON table_name
show index from b_user;
--常规索引
create index idx_user_name on b_user(user_name);
--唯一索引
create unique index idx_money on b_user(money);
--联合索引
create index idx_user_name_money on b_user(user_name,money);
create index idx_user_meail on tb_user(email);
--删除索引
drop index idx_money on b_user;
SQL性能分析
- SQL执行频率
MySQL客户端连接成功后,通过show[sessionlglobal]status命令可以提供服务器状态信息。通过如下指令,可以查看当前数据库的
INSERT、UPDATE、DELETE、SELECT的访问频次 :
SHOW GLOBAL STATUS LIKE 'Com_______';
- 慢查询日志
慢查询日志记录了所有执行时间超过指定参数(long_query_.time,单位:秒,默认10秒)的所有SQL语句的日志。
MySQL的慢查询日志默认没有开启,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:
默认关闭
vi /etc/my.cnf
- profile详细
show profiles能够在做SQL优化时帮助我们了解时间都耗费到哪里去了。通过nave profiling参数,能够看到当前MySQL是否支持
默认profile是关闭的
开启profile
profile操作:
- explain执行计划
EXPLAIN或者DESC命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序。
查询所有学生的选课情况
查看执行顺序:
查询选修了MYSQL课程的学生(子查询)
select _* _from student s where s.id in(select sc.studentid from student_course sc where sc.courseid= (select id from course c where c.name='MySQL'));
的代表内部子查询
不访问任何表它的连接类型才是null
语法: #直接在selecti语句之前加上关键字explain/deC EXPLAIN SELECT字段列表FROM表名WHERE条件;
Id selecti查询的序列号,表示查询中执行select-子句或者是操作表的顺序(id相同,执行顺序从上到下;id不同,值越大,越先执行)。 select_type 表示SELECT的类型,常见的取值有SIMPLE(简单表,即不使用表连接或者子查询)、PRIMARY(主查询,即外层的查询)、 UNION(UNION中的第二个或者后面的查询语句)、SUBQUERY(SELECT./WHERE之后包含了子查询)等 type 表示连接类型,性能由好到差的连接类型为NULL、system、const(主键/唯一索引)、eq_ref、ref(非唯一性索引)、range、index、all。 possible key 显示可能应用在这张表上的索引,一个或多个。 Key 实际使用的索引,如果为NULL,则没有使用索引。 Key_len 表示索引中使用的字节数,该值为索引字段最大可能长度,并非实际使用长度,在不损失精确性的前提下,长度越短越好。 rows MySQL认为必须要执行查询的行数,在innodb引擎的表中,是一个估计值,可能并不总是准确的。 filtered 表示返回结果的行数占需读取行数的百分比,filtered的值越大越好。
索引使用
最左前缀原则
对于tb_user ,的联合索引 profession,age,status ,若最左边的列 profession不存在,索引就全部失效了
若跳跃了某一列,索引会部分失效
索引的最左字段只要存在,就会生效,跟查询的顺序无关
范围查询:
联合索引中,出现范围查询(>,<),范围查询右侧的列索引失效
explain selectfrom tb_user where profession='软件工程'and age>30 and status='0';
索引长度为49,导致 age的索引失效了
如何规避索引失效呢??
explain selectfrom tb_user where profession='软件工程'and age>=30 and status='0';
把>,<改成>= <=
索引失效的情况
- 不要在索引列上进行运算操作, 索引将失效。
explain select * from tb_user where phone = '17799990015';
使用了单列索引
explain select * from tb_user where substring(phone,10,2) = '15';
并没有使用phone索引,因为对索引列进行了函数运算
- 字符串类型的字段没有加' ';
explain select * from tb_user where phone = 17799990015;
explain select * from tb_user where phone = '17799990015';
- 模糊查询
如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。
等值匹配
模糊匹配 尾部模糊匹配
模糊匹配 头部模糊匹配
前后都模糊匹配,也失效
- OR连接的条件
用or分割开的条件,如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。
explain select * from tb_user where id=10 and age=23;
explain select * from tb_user where phone ='17799990017'or age=23;
给age建立索引 ,再次使用查询or
索引生效了
- 数据分布影响
当我们把电话改成最小的电话
就不走索引了,这是因为所有的表的数据都是 >=这个电话号,就走了全表扫描
这说明了如果走索引查询慢就不会走索引
走不走索引取决于当前数据库的数据分布情况
SQL提示
SQL提示,是优化数据库的一个重要手段,简单来说,就是在SQL语句中加入一些人为的提示来达到优化操作的目的。
给profession添加索引
发现还是走的联合索引,没有走单列索引
我们可以建议sql走哪一个索引 (mysql内部会进行评估,可能不会接收你的建议)
explain select *from tb_user use index(idx_user_pro) where profession='软件工程';
忽略某个索引:
explain select *from tb_user ignore index(idx_user_pro) where profession='软件工程';
强制某一个索引:
explain select *from tb_user force index(idx_user_pro) where profession='软件工程';
覆盖索引
尽量使用覆盖索引(查询使用了索引,并且需要返回的列,在该索引中已经全部能够找到),减少select*。
explain select * from tb_user where profession ='软件工程’and age=31 and status ='0';
explain select id,profession,age,status from tb_user where profession='软件工程' and age=31 and status='0';
:::info 知识小贴士: NULL:查找使用了索引,但是需要回表查询数据 using index:查找使用了索引,但是需要的数据都在索引列中能找到,所以不需要回表查询数据 :::
给username 和password 建立联合索引,不需要走回表查询了,直接覆盖查询
前缀索引
当字段类型为字符串(varchar,text等)时,有时候需要索引很长的字符串,这会让索引变得很大,查询时,浪费大量的磁盘O,影响查询效率。此时可以只将字符串的一部分前缀,建立索引,这样可以大大节约索引空间,从而提高索引效率。
语法: create index idx_xxxx on table_name(column(n)) ;
前缀长度:
可以根据索引的选择性来决定,而选择性是指不重复的索引值(基数)和数据表的记录总数的比值,索引选择性越高则查询效率越高, 唯一索引的选择性是1,这是最好的索引选择性,性能也是最好的。
select count(distinct email)/count(*) from tb_user;
创建索引 email ,前五个数据的 索引
长字符串和文本比较长的时候,可以考虑使用前缀索引,降低索引的体积,提高查询的效率
单列索引和联合索引
单列索引:一个索引只包含单个列,单个字段 联合索引:一个索引包含多个列,多个字段
有name和phone两个单列索引进行查询,只走了phone索引
给它创建联合索引
:::info
在业务场景中,如果存在多个查询条件,考虑针对于查询字段建立索引时,建议建立联合索引,而非单列索引。
:::
索引设计原则
:::info 1). 针对于数据量较大,且查询比较频繁的表建立索引。 2). 针对于常作为查询条件(where)、排序(order by)、分组(group by)操作的字段建立索引。 3). 尽量选择区分度高的列作为索引,尽量建立唯一索引,区分度越高,使用索引的效率越高。 4). 如果是字符串类型的字段,字段的长度较长,可以针对于字段的特点,建立前缀索引。 5). 尽量使用联合索引,减少单列索引,查询时,联合索引很多时候可以覆盖索引,节省存储空间,避免回表,提高查询效率。 6). 要控制索引的数量,索引并不是多多益善,索引越多,维护索引结构的代价也就越大,会影响增删改的效率。 7). 如果索引列不能存储NULL值,请在创建表时使用NOT NULL约束它。当优化器知道每列是否包含NULL值时,它可以更好地确定哪个索引最有效地用于查询。 :::