美文网首页
17.MySQL优化

17.MySQL优化

作者: 一枼落知天下 | 来源:发表于2019-07-26 16:19 被阅读0次
    MySQL调优思路

    《高性能MySQL》——这本书都有的

    “字段”优化总结

    1)尽量使用TINYINT、SMALLINT、MEDIUM_INT作为整数类型而非INT,如果非负则加上UNSIGNED;
    2)VARCHAR的长度只分配真正需要的空间;
    3)使用枚举或整数代替字符串类型;
    4)尽量使用TIMESTAMP而非DATETIME;
    5)单表不要有太多字段,建议在20以内;
    6)避免使用NULL字段,很难查询优化且占用额外索引空间;
    7)用整型来存IP。
    

    “索引”优化总结

    1)索引并不是越多越好,要根据查询有针对性的创建,考虑在WHERE和ORDER BY命令上涉及的列建立索引,可根据EXPLAIN来查看是否用了索引还是全表扫描;
    2)应尽量避免在WHERE子句中对字段进行NULL值判断,否则将导致引擎放弃使用索引而进行全表扫描。
    3)值分布很稀少的字段不适合建索引,例如"性别"这种只有两三个值的字段。
    4)字符字段只建前缀索引。
    5)字符字段最好不要做主键。
    6)不用外键,由程序保证约束。
    7)尽量不用UNIQUE,由程序保证约束。
    8)使用多列索引时主意顺序和查询条件保持一致,同时删除不必要的单列索引。
    

    索引的优化

    联合索引最左前缀原则
    复合索引遵守「最左前缀」原则,查询条件中,使用了复合索引前面的字段,索引才会被使用,如果不是按照索引的最左列开始查找,则无法使用索引。
    比如在 (a,b,c) 三个字段上建立联合索引,那么它能够加快 a|(a,b)|(a,b,c) 三组查询的速度,而不能加快 b|(b,a) 这种查询顺序。
    另外,建联合索引的时候,区分度最高的字段在最左边
    
    不要在列上使用函数,这将导致索引失效而进行全表扫描。
    例如:
    select * from student where YEAR(create_time) <= '2018';
    即使 date 上建立了索引,也会全表扫描,可以把计算放到业务层,这样做不仅可以节省数据库的 CPU,还可以起到查询缓存优化效果。
    
    负向条件查询不能使用索引
    负向条件有:!=、<>、not in、not exists、not like 等。
    select * from student  where status != 1 and status != 2; 
    可以使用 in 进行优化:
    select * from student  where status in (0,3) 
    
    使用覆盖索引
    
    所谓覆盖索引,是指被查询的列,数据能从索引中取得,而不用通过行定位符再到数据表上获取,能够极大的提高性能。
    可以定义一个让索引包含的额外的列,即使这个列对于索引而言是无用的。
    避免强制类型转换
    
    当查询条件左右两侧类型不匹配的时候会发生强制转换,强制转换可能导致索引失效而进行全表扫描。
    如果 phone 字段是 varchar 类型,则下面的 SQL 不能命中索引:
    select * from user where phone=12345678901; 
    可以优化为:
    select * from user where phone='12345678901'; 
    范围列可以用到索引
    
    
    范围条件有:<、<=、>、>=、between 等。
    范围列可以用到索引,但是范围列后面的列无法用到索引,索引最多用于一个范围列,如果查询条件中有两个范围列则无法全用到索引。
    更新频繁、数据区分度不高的字段上不宜建立索引
    
    更新会变更 B + 树,更新频繁的字段建立索引会大大降低数据库性能。
    「性别」这种区分度不大的属性,建立索引没有意义,不能有效过滤数据,性能与全表扫描类似。
    区分度可以使用 count (distinct (列名))/count (*) 来计算,在 80% 以上的时候就可以建立索引。
    索引列不允许为 null
    
    单列索引不存 null 值,复合索引不存全为 null 的值,如果列允许为 null,可能会得到不符合预期的结果集。
    
    避免使用 or 来连接条件
    应该尽量避免在 where 子句中使用 or 来连接条件,因为这会导致索引失效而进行全表扫描,
    虽然新版的 MySQL 能够命中索引,但查询优化耗费的 CPU 比 in 多。
    
    
    模糊查询
    前导模糊查询不能使用索引,非前导查询可以。
    
    

    “查询SQL”优化总结

    1)可通过开启慢查询日志来找出较慢的SQL;
    2)不做列运算:SELECT id WHERE age + 1 = 10,任何对列的操作都将导致表扫描,
    它包括数据库教程函数、计算表达式等等,查询时要尽可能将操作移至等号右边;
    3)sql语句尽可能简单:一条sql只能在一个cpu运算;大语句拆小语句,减少锁时间;一条大sql可以堵死整个库;
    4)不用SELECT *;
    5)OR改写成IN:OR的效率是n级别,IN的效率是log(n)级别,in的个数建议控制在200以内;
    6)不用函数和触发器,在应用程序实现;
    7)避免%xxx式查询;
    8)少用JOIN;
    9)使用同类型进行比较,比如用'123'和'123'比,123和123比;
    10)尽量避免在WHERE子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描;
    11)对于连续数值,使用BETWEEN不用IN:SELECT id FROM t WHERE num BETWEEN 1 AND 5;
    12)列表数据不要拿全表,要使用LIMIT来分页,每页数量也不要太大。
    

    “引擎”的选择

    1分钟了解MyISAM与InnoDB的索引差异

    目前广泛使用的是MyISAM和InnoDB两种引擎。
    
    【MyISAM】:
    
    MyISAM引擎是MySQL 5.1及之前版本的默认引擎,它的特点是:
    
    1)不支持行锁,读取时对需要读到的所有表加锁,写入时则对表加排它锁;
    2)不支持事务;
    3)不支持外键;
    4)不支持崩溃后的安全恢复;
    5)在表有读取查询的同时,支持往表中插入新纪录;
    6)支持BLOB和TEXT的前500个字符索引,支持全文索引;
    7)支持延迟更新索引,极大提升写入性能;
    8)对于不会进行修改的表,支持压缩表,极大减少磁盘空间占用。
    
    【InnoDB】:
    
    InnoDB在MySQL 5.5后成为默认索引,它的特点是:
    
    1)支持行锁,采用MVCC来支持高并发;
    2)支持事务;
    3)支持外键;
    4)支持崩溃后的安全恢复;
    5)不支持全文索引。
    
    总体来讲,MyISAM适合SELECT密集型的表,而InnoDB适合INSERT和UPDATE密集型的表。
    

    系统调优参数、升级硬件、读写分离、缓存、垂直拆分、水平拆分

    CobarAtlasMyCat

    相关文章

      网友评论

          本文标题:17.MySQL优化

          本文链接:https://www.haomeiwen.com/subject/yhldrctx.html