Mysql
查看存储引擎:
show ENGINES;
查看所有搜索引擎SHOW VARIABLES LIKE '%storage_engine%';
查看当前正在使用的搜索引擎
#SQL读取顺序:
MylSAM和InnoDB的区别:
主外键:MylSAM:不支持,InnoDB:支持
事务:MylSAM:不支持,InnoDB:支持
行表锁:MylSAM:表锁,InnoDB:行锁
缓存:MylSAM:只缓存索引,不缓存数据,InnoDB:不仅缓存索引,还要缓存真实数据,对内存要求比较高,而且内存大小对性能有决定性的影响。
表空间:MylSAM:小,InnoDB:小
关注点:MylSAM:性能,InnoDB:事务
默认安装:创建表的时候默认安装InnoDB
文件结构:
MylSAM:
b.frm:描述结构文件,字段长度等
b.MYD(MYData):数据信息文件,存储数据信息(如果采用独立表存储模式)
b.MYI(MYIndex):索引信息文件
InnoDB:
b.frm:描述表结构文件,字段长度等
b.ibd:存储数据信息和索引信息
#Join连接:
内连接和左右连接:
内连接查询:查询两张表共有部分
对应语句如下:SELECT*from sourse a INNER JOIN demo b ON a.art_id = b.id
左连接查询:把左边表的内容全部查出,右边表只查出满足条件的记录,也就是A和B共有的再加上A独有的。
对应语句如下:SELECT*from sourse a LEFT JOIN demo b ON a.art_id = b.id
右连接查询:和左连接相反,把B和A共有的再加上B独有的。
对应语句如下:SELECT*from sourse a RIGHT JOIN demo b ON a.art_id = b.id
内连接:查询合并两张表,但是mysql它并不支持全连接,并不支持Full Outter关键字,但是oracle是可以的,但mysql可通过左右连接合并的方式来取。
对应语句如下:SELECT*from sourse a left JOIN demo b ON a.art_id = b.id
UNION
SELECT*from sourse a RIGHT JOIN demo b ON a.art_id = b.id
查询左右表独有的数据:
同上,也就是加一个条件,相当于两表共有的不取。
左连接语句如下:SELECT*from sourse a left JOIN demo b ON a.art_id = b.id WHERE b.id is NULL
右连接语句如下:SELECT*from sourse a RIGHT JOIN demo b ON a.art_id = b.id WHERE a.art_id is NULL
内连接语句如下:SELECT*from sourse a left JOIN demo b ON a.art_id = b.id WHERE b.id is NULL
UNION
SELECT*from sourse a RIGHT JOIN demo b ON a.art_id = b.id WHERE a.art_id is NULL
优化分析:
##Sql性能下降原因:
###sql性能下降的表现:
1.执行时间长
2.等待时间长
性能下降原因:
1.查询语句写的不好:各种连接,各种子查询导致用不上索引或者没有建立索引
2.建立的索引失效:建立了索引,在真正执行时,没有用上建立的索引
3.关联查询太多join
4.服务器调优及和个配置参数导致:如果设置的不合理,比例不恰当,也会导致性能下降,sql变慢
索引
什么是索引?
1.帮助mysql搞笑获取数据的数据结构
2.索引就是数据结构
3.类似新华字典的索引目录,可以通过索引目录快速查到你想要的的字
3.排好序的快速查找数据
为什么要建立索引?
**1.**提高查询效率:
1.没有排序之前是一个一个往后找
2.通索引进行排序之后,可以直接定义到想要的位置
**2.**排好序的快速查找数据结构–>就是索引
优势:
1.索引类似大学图书馆建立的书目录索引,提高数据检索的效率,降低数据库的IO成本
2.通过索引对数据项进行排序,降低数据排序成本,降低了CPU的消耗
劣势:
1.一般来说,索引本身也很大,索引往往以文件的形式存储到磁盘上
2.索引也是一张表,该表保存了主键于索引字段,并指向实体表的记录,所以索引也是要占磁盘空间的
3.虽然索引提高了查询速度,但是会降低更新表的速度
4.因为更新表时,mysql不仅要保存数据,还要保存一下索引文件每次更新添加了索引的字段
5.会调整因为更新所带来的键值变化后索引的信息
索引分类:
1.单值索引:1.一个索引只包含间个列,一个表可以有多个单值索引2.一般来说,一个表建立索引不要超过5个
2.唯一索引:索引列的值必须唯一,但允许有空值
3.复合索引:一个索引包含多个列
4.全文索引:mysql全文检索是利用查询关键字和查询列内容之间的相关度进行检索,可以利用全文索引来提高匹配的速度。
索引为什么能快速查找数据:
1.概述:在我们存数据时,如果建立索引,数据库系统会维护一个满足特定查找算法的数据结构,这些数据结构以某种方式引用数据,可以在这些数据结构之上,实现高级查找算法,这种结构就是索引。一般来说,索引本身也很大,不可能全部存储在内存中,因此索引往往以文件的形式存储在磁盘上,为了加快数据的查找,可以维护二叉查找树,每个节点分别包含索引键值和一个指向对应数据记录的物理地址的指针,这样就可以运用二叉查找在一定的复杂度内容获取相应的数据,从而快速的检索出符合条件的记录,除了二叉树还有BTtree索引,我平时所说的索引,如果没有特别指定,都是指B树结构组织的索引,其中聚焦索引,次要索引,复合索引,前缀索引,唯一默认都是B+树索引,处B+树索引之外,还有哈希索引(Hash index)等。
2.二叉查找树:
1.特性:左子树键值小于根的键值,右子树的键值大于根的键值。示例图:
3.B-Tree(B树):
特性:
1.根节点至少包括两个孩子
2.树中每个节点最多有m个孩子(m>=2)
3.除了根节点和叶子节点外,其它每个节点至少有Ceil(m/2)个孩子
4.所有叶子节点都在同一层
5.ki(1=1…n)为关键字,且关键字按顺序升序排列k(i-1)<k 8<9
6.关键字的个数n满足:ceil(m/2)-1<=n<=m-1(非叶子节点关键字个数比指向孩子的指针少1个)
7.非叶子节点的指针p1,p2,…p[m]其中p1指向关键字小于k1的子树 3<8
p[m]指针关键字大于k[m-1]的子树 15>12
p[i]指向关键字属于(k[i-1],k[i])的子树, 9,10是位于8和12之间示例图:
**4.B+Tree(B+树)**:
B+树是B树的变体,基本与B树相同。
不同点:
1.非叶子节点的子树指针与关键字个数相同
2.非叶子节点的子树指针,指向关键字值[k[i],k[i+1]]的子树 (10<18<20)
3.非叶子节点禁用来做索引,数据都保存在叶子节点中
4.所有叶子节点均有一个链指针指向下一个叶子结点:链接起来能够方便我们直接在叶子节点做范围统计,而不是再回到子节点中,一旦定位到某个叶子节点,便可以从该叶子节点横向的取跨子树去做统计。示例图:
5.采用B+Tree做为主流索引数据结构的原因:
B+树更适合用来做存储索引。
**一.**B+树的磁盘读写代价更低:
1.内部的结构并没有指向关键字的具体指针
2.不存放数据,只存放索引信息
3.内部节点相对B树更小
**二.**B+树的查询效率更加稳定:
1.内部节点并不是最终指向文件内容的节点,只是叶子节点中关键字的索引
2.所以它任何关键字的查找,必须走一条从根节点到叶子节点的路
3.所有关键字查询的长度相同,导致每一个数据查询的效率也几乎是相同的
**三.**B+树更有利于对数据库的扫描:
1.B树在提高IO性能同时,并没有解决元素遍历效率底下问题
2.B+树只需要遍历叶子节点,就可以解决对全部关键字信息的扫描
3.对数据库中,频繁使用的范围查询,性能更高
总结:B+树的磁盘读写代价更低,它的内部并没有真正指向磁盘里面的,相比于B树每一个都要去磁盘里找数据,B+树的第二层还继续往下的,它的叶子节点里的数据才到磁盘里面的才开始找数据,然后B+树相比于B树,它的效率更加稳定,每一个查找都是从根节点到子结点再到叶子节点,你无论查哪一个数据,他们基本速度基本都差不多基本可以说是相同的。而且它更利于数据库的扫描,因为它里面的叶子节点都是链接起来的,它做范围查找的话,性能会更高,因为直接在里面就通过链接的节点去做一个范围的查找,就不用再返回上面了,它更适合做范围查找。B+树它只需要你去遍历叶子节点即可查找所有的关键字信息。
索引创建与查看:
索引查看:SELECT cus_id FROM testemployee WHERE cus_id = 5;
索引创建:CREATE INDEX CUS_IDX(索引命名) ON testemployee(cus_id(以这个字段创建索引));
查看创建的索引:show index from testemployee;
索引建立的选择:
一、适合建立索引:
1.主键自动建立唯一索引 primary
2.频繁作为查询条件的字段应该创建索引:比如银行账户,电信手机号
3.查询中与其它表关联的字段,外键关系建立索引,比如员工部门外键
4.频繁更新的字段不适合建立索引:每次更新不单单更新数据,还要更新索引
5.where条件里用不到的字段不建立索引
6.查询中排序的字段,排序的字段若通过索引去访问将大大提升排序速度:索引能够提高检索的速度和排序的速度
7.查询中统计或分组的字段:分组的前提是比排序
二、不适合建立索引:
1.记录比较少
2.经常增删改的表:索引提高了查询的速度,同时却会降低更新表的速度,如果对表的INSERT,UPDATE和DELETE,因为建立索引后,更新表时,MYSQL不仅要保存数据,还要保存一下索引文件
3.数据重复的表字段:如果某个数据列包含了许多重复的内容,为它建立索引,就没有太大的实际效果。还有比如表中的某一个字段为国际、性别。数据的差异率不高,这种建立索引就没有太大的意义
性能分析
表设计准则:
一、满足关系数据库的三范式:
(一):
1.是指数据库表的每一列都是不可分割的基本数据项,同一列中不能有多个值
2.第一范式是对关系模式的基本要求,不满足第一范式的数据库就不是关系数据库
(二):
1.要求数据库表中的每个实例或行必须可以被唯一的区分
2.设置主键
(三):
1.要求一个数据库表中不包含已在其它表中已包含的非主关键字信息
2.两张表不要重复的字段,通常都是设置外键
二、大表拆小表,有大数据的列单独拆成小表:
1.在数据库中,一般不会涉及属性过多的表
2.在一个数据库中,一般不会有超过500/1000万数据的表 拆表
3.有大数据的列单独拆成小表(富文本编辑器,CKeditor)
##DQL的执行过程:
一、sql的执行过程:
1.客户端发送一条查询给服务器;
2.服务器通过权限检查之后,先会检查查询缓存,如果命中了缓存,则立即返回存储在缓存中的结果,否则进入下一阶段
3.服务器端进行SQL解析、预处理,再由优化器根据该sql所涉及的数据表的统计信息进行计算,生成对应的执行计划
4.Mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询
5.将结果返回给客户端
二、查询优化器:
1.写的任何sql,到底是怎么样真正执行的,按照什么条件查询,最后执行的顺序,可能都会有多个执行方案
2.查询优化器根基对数据表的统计信息(比如索引,有多少条数据)在真正执行一条sql之前,会根据自己内部的数据,进行综合的查询
3.根据mysql自身的统计信息,从多种执行方案当中,选择一个它认为最优的执行方案,来去执行
三、做优化、做什么:
1.做优化,就是想让查询优化器按照我们的想法,帮我们选择最优的执行方案
2.让优化器选择符合程序员计划的执行语句,来减少查询过程中产生的IO示例图
:
##Explain:
一.查询执行计划:
1.使用explain关键字,可以模拟优化器执行的SQL语句
2.从而知道Mysql是如何处理sql语句的
3.通过Explain可以分析查询语句或表结构的性能瓶颈
二、作用:
1.查看表的读取顺序
2.数据读取操作的操作类型
3.查看哪些索引可以使用
4.查看哪些索引被实际使用
5.查看表之间的引用
6.查看每张表多少行被优化器执行
三、使用方法:EXPLAIN SELECT * FROM employee;
示例图:
四、分析包含信息:
一、id(表执行的顺序):
**(一)**、select查询序列号
**(二)**、包含一组数字,表示查询中执行select子句或操作表的顺序
**(三)**、值的三种情况:
1.id相同:
sql语句:EXPLAIN SELECT * from employee e, sourse s,demo d
WHERE e.dep_id = s.art_id and e.cus_id = d.id;
执行的顺序是由上至下的。
2.id不同:
如果是子查询,id的序号会递增,id值越大优先级越高,优先被执行
3.id相同不同,同时存在:
sql语句:EXPLAIN SELECT * from demo d,
(SELECT * FROM employee GROUP BY dep_id) t
WHERE d.id = t.dep_id;
可以认为是一组从上往下顺序执行
在所有组中,id值越大,优先级越高,越先执行
deriverd衍生出来的虚表
**(四)**、总结:
相同,顺序走
不同,看谁大
大的先执行
二、select_type(查询的类型):
1.作用:查询类型,只要用于区别普通查询,联合查询,子查询等复杂查询
2.结果值:
SIMPLE:简单select查询,查询中不包含子查询或者UNION
PRIMARY:查询中包含任何复杂的子查询,最外层查询则被标记为primary
三、table(查询的是哪张表):
显示这一行的数据是关于哪张表的
四、partitions(显示你访问的分区):
如果查询是基于分区表的话,会显示查询访问的分区
五、type(当前扫描表是以哪一种形式):
(一).结果值最好到最差:
1.system:表中有一行记录(系统表)这是const类型的特例,平时不会出现
2.const:
表示通过索引一次就找到了
const用于比较primary或者unique索引,直接查询主键或者唯一索引
因为只匹配一行数据,所以很快
sql语句:EXPLAIN SELECT id FROM employee WHERE id = 1;
3.eq_ef:唯一
性索引扫描
对于每个索引键,表中只有一条记录与之匹配
常见于主键或唯一索引扫描
sql语句:SELECT * FROM employee,demo WHERE employee.id = demo.id;
4.ref:非唯一
性索引扫描,返回匹配某个单独值的所有行
本质上也是一种索引访问
它返回所有匹配某个单独值的行
可能会找到多个符合条件的行
所以它应该属于查找和扫描的混合体
sql语句:SELECT * FROM employee,demo WHERE employee.dep_id = demo.id;
5.range:
只检索给定范围的行,使用一个索引来选择行
key列显示使用了哪个索引
一般就是在你的where语句中出现between<>\in等查询
这种范围扫描索引比全表扫描要好
因为它只需要开始于索引的某一点,而结束语另一点
不用扫描全部索引
sql语句:EXPLAIN SELECT * FROM employee WHERE employee.id in (1,2,3);
6.index:
Full Index Scan
index与All区别为index类型只遍历索引树,通常比All要快,因为索引文件通常比数据文件要小
all和index都是读全表,但index是从索引中读取,all是从硬盘当中读取
sql语句:EXPLAIN SELECT id FROM employee;
7.ALL:
将全表进行扫描,从硬盘当中读取数据
如果出现了All且数据量非常大,一定要去做优化
sql语句:EXPLAIN SELECT * FROM employee;
(二)、要求:
一般来说,保证查询至少达到range级别
最好能达到ref
六、possible_keys(可能用到的索引):
1.key与keys主要作用,是查看是否使用了建立的索引,也即判断索引失效
2.在建立多个索引的情况下,mysql最终用到了哪一个索引
**七、key(实际用到的索引)**: 1.实际使用的索引,如果为NULL,则没有使用索引 2.查询中若使用了覆盖索引,则该索引仅出现在key列表中 3.possible_keys与key关系,理论应该用到哪些索引,实际用到了哪些索引 4.覆盖索引,查询的字段和建立的字段刚好吻合,这种我们称为覆盖索引
**八、key_len(根据它的长度当前使用了几个索引)**: 表示索引中使用的字节数,可通过该列计算查询中使用的索引长度。 就比如建立一个符合索引,里面创建三个,然后查询,你每删除一个就会发现key_len的长度也会减少,所以key_len就是使用的长度,也就是字节数,但也不是最终使用的字节数,它仅仅是可能出现的最大值,所以我们就可通过它判定哪些索引失效了。
**九、ref(索引值是固定的值,还是等于另外的)**: 用于查看索引是否被引入,到底引用到哪几个索引。 **十、rows(优化的行数)**: 1.根据统计信息及索引选用情况,大致估算出找到所需的记录,所需的行数。 2.每长表有多少行被优化器查询过 3. **十一、filtered(过滤的百分比)**: 1.满足查询的记录数量的比例,注意是百分比,不是具体记录数 2.值越大越好,filtered列的值依赖统计信息,并不十分准确 总结:同样的一条sql语句,建立索引和不建立索引,所扫描的行数,以及命中率都不一样。总之rows被优化器扫描的就是越少越好,而filtered则是越高越好。 **十二、Extra(额外的参数)**: 额外的产生的值: Using filesort: 说明mysql会对数据使用一个外部的索引排序,而不是按照表内的索引顺序进行,mysql中无法利用索引完成排序操作称为“文件排序”。 Using temporary: use index: using where: using join buffer: impossible where:
# 性能优化 ## 索引失效: **一、全值匹配(最好)**: 首先建立复合索引,SQL语句如下:`create index idx_name_dep_age on employee(name,dep_id,age);`然后再`EXPLAIN SELECT * FROM employee where name = '鲁班' and dep_id = 1 and age = 10;` 意思也就是把创建的索引全都用上,就是全值匹配了。
二、最佳左前缀法则:
1.如果索引的多列,要遵守最左前缀法则,指的就是从索引的最左列开始,并且不跳过索引中的列
2.跳过第一个,索引失效
3.跳过前两个,索引失效
4.跳过中间一个,只有第一个生效,后面的都失效
5.顺序可以乱
三、不在索引列上做任何操作:
1.计算,函数,类型转换
2.会导致索引失效而转向全表扫描
范围条件右边的索引失效:
mysql在使用不等于(!=或者<>)的时候无法使用索引会导致全表扫描
is null,is not null 无法使用索引:
like以通配符开头(%qw)索引失效变成全表扫描:
字符串不加引号索引失效:
少用or,用or连接时,会导致索引失效: