您的位置:首页 > 数据库 > MySQL

关于Mysql SQL优化的总结,持续更新中

2018-07-25 23:17 627 查看
SQL优化的思路:
1.优化更需要优化的sql;

2.定位优化对象的性能瓶颈:优化前需了解查询的瓶颈是IO还是CPU,可通过PROFILING很容易定位查询的瓶颈。

3.明确优化目标;

4.从Explain入手;

5.多使用profile;

SQL优化的基本原则:
1.永远用小结果集驱动大结果集;

From子句中sql解析顺序为从右向左,执行时会以最左边的表为基础表循环与右边表数据做笛卡尔积,所以以小结果集驱动能减少循环次数,从而减少对被驱动结果集的访问,从而减少被驱动表的锁定。

2.尽可能在索引中完成排序;

排序算法有两种:a.查出排序字段和行指针,排序,再通过行指针获得行数据所需列,返回结果集;b.取出所有排序列数据,在排序缓冲区中排完序直接返回结果集。

索引排序是利用索引的有序性对数据排序的。

3.只取出子集需要的colums

4.仅仅使用最有效的过滤条件;

5.尽可能避免复杂的Join和子查询;

索引的好处:
(1).提高数据检索效率,降低数据库的IO成本。

(2).降低数据排序成本:要求排序字段和索引键字段一致。

(3).降低数据分组成本:因为分组之前会先排序,同意如果分组字段与索引字段一致,会降低分组消耗的成本。

索引的弊端:
(1).索引是独立于基础数据的数据库对象,因此它会占用存储空间。

(2).数据新增、更新会导致索引的同步更新,所以会增加数据新增、更新所消耗的成本。

判断是否需要创建索引:
(1).较为频繁的作为查询条件的字段需要创建索引

(2). 唯一性太差的字段不适合单独创建索引,即使频繁作为查询条件;

(3).更新非常频繁的字段不适合创建索引;

(4).不会出现在where子句中的字段不要创建索引;

1、只要能满足你的需求,应尽可能使用更小的数据类型:例如使用MEDIUMINT代替INT
2、尽量把所有的列设置为NOT NULL,如果你要保存NULL,手动去设置它,而不是把它设为默认值。
3、尽量少用VARCHAR、TEXT、BLOB类型
4、如果你的数据只有你所知的少量的几个。最好使用ENUM类型
5、正如graymice所讲的那样,建立索引。

SQL编写注意事项:
1.原则1、仅列出需要查询的字段,这对速度不会明显的影响,主要是考虑节省应用程序服务器的内存。

2.原则2、尽量避免在列上做运算,这样导致索引失效。

3.原则3、使用JOIN 时候,应该用小的结果驱动大的结果(left join 左边表结果尽量小 如果有条件应该放到左边先处理,right join 同理反向),同事尽量把牵涉到多表联合的查询拆分多个query(多个连表查询效率低,容易到之后锁表和阻塞)。

4.原则4、注意LIKE 模糊查询的使用, 避免使用 %% ,可以使用 后面带% ,双%是不走索引的。

5.原则5、使用批量插入节省交互 (当如如果使用存储过程来处理批量的sql 各种逻辑是更好的选择)。

6.原则6、limit的基数比较大时使用between。

原来语句:select * from admin order by admin_id limit 100000,10
优化为:  select * from admin where admin_id between 100000 admin 100010 order by admin_id

7.原则7、不要使用rand函数获取多条随机记录。

原来语句: select * from admin order by rand() limit 20
优化为: select * from admin as t1 Join(select round(rand()*((select max(admin_id) from admin)-(select min(id) from admin))+(select min(id) from admin)) as id) as t2 where t1.id>=t2.id order by t1.id limit

8.原则8、避免使用NULL。

9.原则9. 不要使用 count(id) 使用 count(*)。

10.原则10、不要做无谓的排序操作,而应该使用索引列完成排序。即order排序列必为索引

11.原则11、where条件中,过滤量最大的条件放在where子句最后;

12.原则12、在索引列上使用计算、改变索引列的类型(不匹配的数据类型)、在索引列上使用!=将放弃索引;

13.运算符效率:exists高于in高于or,(not exists高于not in); IN、OR子句常会使用工作表,使索引失效。如果不产生大量重复值,可以考虑把子句拆开。拆开的子句中应该包含索引。用union 连接

14.避免在索引列上使用is null和is not null;

15.用union-all替代union;
16.采用as 别名 采用绑定变量有助于提高效率;

17.使用函数=将放弃索引;

18/避免使用HAVING字句

B-tree 索引和 hash索引
Innodb和MyISAM默认的索引是Btree索引;而Mermory默认的索引是Hash索引。

hash索引

所谓Hash索引,当我们要给某张表某列增加索引时,将这张表的这一列进行哈希算法计算,得到哈希值,排序在哈希数组上。所以Hash索引可以一次定位,其效率很高,而Btree索引需要经过多次的磁盘IO,但是innodb和myisam之所以没有采用它,是因为它存在着好多缺点:

1、因为Hash索引比较的是经过Hash计算的值,所以只能进行等式比较,不能用于范围查询

1、每次都要全表扫描

2、由于哈希值是按照顺序排列的,但是哈希值映射的真正数据在哈希表中就不一定按照顺序排列,所以无法利用Hash索引来加速任何排序操作

3、不能用部分索引键来搜索,因为组合索引在计算哈希值的时候是一起计算的。

4、当哈希值大量重复且数据量非常大时,其检索效率并没有Btree索引高的。

Btree索引(单独文章描述)

至于Btree索引,它是以B+树为存储结构实现的。

但是Btree索引的存储结构在Innodb和MyISAM中有很大区别。

所以我们经常会说MyISAM中数据文件和索引文件是分开的。

因此MyISAM的索引方式也称为非聚集,Innodb的索引方式成为聚集索引。

至于辅助索引,类似于主索引,唯一区别就是主索引上的值不能重复,而辅助索引可以重复。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MyISAM MySQL InnoDB BTree