• mysql优化


    explain

    通过explain查看sql执行计划

    Image

    1. type列,连接类型。一个好的sql语句至少要达到range级别,杜绝all级别
    2. key列,使用到的索引名。如果没有选择索引,值是NULL。可以采取强制索引方式
    3. key_len列,索引长度
    4. rows列,扫描行数。该值是个预估值
    5. extra列,详细说明。常见的不友好的值有:Using filesort,Using temporary

    SQL中in包含的值不宜过多

    mysql对in做了相应的优化,即将in中的常量全部存储到一个数组里,而且这个数组是排好序的。但是如果值过多,产生的消耗也是较大的。

    select id from t where num in (1,2,3)

    优化后

    select id from t where num between 1 and 3

    select语句务必要指明字段名称

    select * 增加很多不必要的消耗(cpu,io,内存,网络带宽等);增加了使用覆盖索引的可能行;当表的结构发生修改时,前端也需要更新。所以要求直接在select后面接上字段名。

    当只要一条数据的时候,用limit 1

    这是为了使explain中type列达到const类型

    如果排序字段没有用到索引,就尽量少排序

    如果限制条件中其他字段没有索引,尽量少用or

    or两边的字段中,如果有一个不是索引字段,而其他

    尽量用union all而不是union

    union和union all的差异主要是前者需要将结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的CPU运算,加大资源消耗和延迟。
    前提:union all是在两个结果集没有重复条件下,否则会有重复数据的。

    不使用order by rand()

    从结果集中随机抽选一些数字。

    select id from table_a order by rand() limit 10

    优化为

    select id from table_a t1 join (select rand() * (select max(id) from table_a) as nid) t2 on t1.id > t2.nid limit 1000;

    区分in和exists,not in 和 not exists

    select * from table_a where id in (
        select id from table_b
    )

    相当于

    select * from table_a where exists(select * from table_b where table_b.id=table_a.id)

    区别in和exists主要是造成了驱动顺序的改变(提高性能的关键),如果是exists,那么以外层表为驱动表,先被访问。如果是in,那么先执行子查询。所以in适合外表大而内表小的情况;exists适合外表小而内表大的情况。
    关于not in和not exists,推荐使用not exists,不仅仅是效率问题,not in可能存在逻辑问题。

    select colname …  from A表 where a.id not in (select b.id from B表)

    优化后

    select colname …  from A表 Left join B表 on where a.id = b.id where b.id is null

    使用合理的分页方式以提高分页的效率

    select id,name from product limit 866613, 20

    随着表的数据量增大,直接使用limit只会越来越慢

    优化后
    select id,name from product where id> 866612 limit 20

    避免在where子句中对字段进行null的判断

    对于null的判断会导致引擎放弃索引而进行全表扫描

    不建议使用%前缀的模糊查询

    如果要使用like %name% ,这种查询会导致索引失效而进行全表扫描。但是可以使用like 'name%'
    如果真的要%name%,建议使用全文索引
    创建全文索引的sql语句

    ALTER TABLE table_a ADD  FULLTEXT INDEX  `idx_user_name` (`user_name`);

    使用全文索引的sql语句:

    select id,fnum,fdst from dynamic_201606 where match(user_name) against('zhangsan' in boolean mode);

    注意:在需要创建全文索引之前,要联系DBA确定是否能创建。同时还要注意查询语句的写法和普通索引的区别

    避免在where子句中对字段进行表达式操作

    比如在where进行算术运算,会造成引擎放弃索引

    select user_id,user_project from user_base where age*2=36;

    优化为

    select user_id,user_project from user_base where age=36/2;

    避免隐式类型转换

    比如a=1还是a='1'
    要提前确认数据格式,避免转换格式

    注意范围查询语句

    对于联合索引来说,如果存在查询范围,比如between,>,<等条件时,会造成后面的索引字段失效。

    关于join优化

    Image [1]

    • left join A表为驱动表
    • inner join mysql会自动找出数据了少的表作为驱动表
    • right join B表为驱动表
    多利用小表去驱动大表
    Image [2][4]
    从原理图能够直观的看出如果能减少驱动表的话,减少嵌套循环中的循环次数,以减少IO总量及CPU运算的次数
  • 相关阅读:
    [Luogu P3626] [APIO2009] 会议中心
    杭电 1869 六度分离 (求每两个节点间的距离)
    杭电 1874 畅通工程续 (求某节点到某节点的最短路径)
    最短路径模板
    杭电 2544 最短路径
    POJ 1287 Networking (最小生成树模板题)
    NYOJ 1875 畅通工程再续 (无节点间距离求最小生成树)
    POJ 2485 Highways (求最小生成树中最大的边)
    杭电 1233 还是畅通工程 (最小生成树)
    杭电 1863 畅通工程 (最小生成树)
  • 原文地址:https://www.cnblogs.com/starzy/p/11146119.html
Copyright © 2020-2023  润新知