【MySQL 7】SQL优化
为了便于理解,可以先了解一些数据库内部结构和原理。
一、数据库内部结构和原理
底层逻辑架构

0 mysql之外类似java程序访问——1 和连接池沟通——2 缓存、缓冲查询——3 SQL接口分析sql——4 解析器复杂sql解析 ——5 优化器、不影响结果进行优化,生成执行计划——6 存储引擎按计划分类型执行——7 存入缓存——8 返回结果
和其他数据库相比,MySQL有点与众不同,他的架构可以在多种不同场景中应用并发挥良好作用,主要体现在存储引擎的架构上,插件式的存储引擎架构将查询处理和其他的系统任务以及数据的存储提取相分离。这种架构可以根据业务的需求和实际需要选择合适存储引擎。
(即在不改变SQL语句结果的前提下,优化改变SQL语句原本的标准执行顺序,如先执行from,on where,group by,having ,使得效率更优)
二、存储引擎 MyISAM和InnoDB
1、InnoDB存储引擎
InnoDB是my sql 的默认事务型引擎,被设计用来处理大量的短期事务。除非有非常特别的原因需要使用其他存储引擎,否则都会优先考虑它。
2、MyISAM存储引擎
提供大量特性,包括全文索引、压缩、空间函数,但不支持事务和行级锁,缺陷是崩溃后无法安全恢复
3、Archive引擎
只支持insert和select 操作,适合日志和数据采集类应用
4、blackhole引擎
没有实现任何存储机制,会丢弃所有插入数据,不做任保存,但服务器会记录日志。可用于复制数据到备库,或简单的记录到日志。不推荐。
5、CSV引擎
可作为一种数据交换的机制,很有用,将普通的CSV文件作为mysql表来处理,但不支持索引。
CSV存储的数据之间可以在操作系统里,用文本编辑器或excel读取
6、Memory引擎
可以快速访问数据,并且这些数据不会被修改,重启以后会丢失。比2、MyISAM存储引擎要快一个数量级。
7、Memory引擎
是访问其他mysql服务器的一个代理,虽然看起来给跨服务器带来灵活性,但经常出问题,所以默认是禁用。
三、数据库建模优化
1、数据库索引的建立
1.1索引是什么?
定义:索引(index)是帮助MySQL高效获取数据的数据结构。索引的本质:是数据结构。
详细定义:在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。
通俗的说就是“排好序的快速查找数据结构”
一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。

1.2索引的优势:
a)类似大学图书馆建书目索引,提高数据检索的效率,降低数据库的IO成本
b) 通过索引列对数据进行排序,降低数据排序的成本,降低CPU的消耗
1.2索引的劣势:
a)虽然索引大大提高了查询速度,同时也降低更新表的速度。因为更新表时,MYSQL不仅要保存数据,还要保存索引文件每次更新添加数据所带来的键值变化后的索引信息。
b) 索引实际上也是一张表,该表保存了主键与索引字段,并指向实体表的记录,所以索引列也是要占空间的。
1.3 mySQL 的底层索引结构
a) B tree :有数据,有向下的指针,指向数据的指针

b) B+tree :有数据,有向下的指针

虽然看起来,B tree比B+tree更快。但同样情况下,B+tree比B tree少1/3的I /O次数(I /O表示耗时操作)。
所以为了在资源有限的情况下(一般电脑都是资源有限)更优的查询大数据,mySQL选择的是B+tree。因为想降低时间复杂度(有时宁愿增加空间复杂度)
同一问题可用不同算法解决,而一个算法的质量优劣将影响到算法乃至程序的效率。算法分析的目的在于选择合适的算法和改进算法。

注释:数组不一定有序,查找最大是N,插入可以随意插入,删除前要先找到数再删除。
有序数组 查找可以用二分法,插入前和删除前应先查数
有序链表就算有序,可能会有跳表,指针。

c ) 聚簇索引与非聚簇索引
聚簇索引
与非聚簇索引

三、SQL语句优化
可以结合 建中间表、分区、语句规范、性能优化 等多种方式优化
1、尽量避免全表扫描查询,可以在where、order by 涉及的列上加索引。
2、in 和 not in、<>等负向查询和%开头的模糊查询会导致全表扫描。比如 in(1,2,3)尽量改成between1 and 3
3、select *,*替换成指定列,因为a)读取不需要的列会增加CPU、IO、NET消耗
b)不能有效的利用覆盖索引
c)使用SELECT *容易在增加或者删除字段后出现程序BUG
4、查询数字型字段时,注意格式,是否需要加引号。
如:SELECT uid FROM t_user WHERE phone=13812345678 会导致全表扫描,而不能命中phone索引,因为phone是varchar类型,需要添加引号
5、union all (不去重),union (去重),若确认2段表不重复,用union all会更快。
*mysql 没有outjoin,oracl才有