• 让你的sql开启氮气加速


    事情的过程是:公司有一个上百行的sql 运行在MySQL数据库,速度奇慢无比,逻辑乱七八糟,我就不贴出来了,经过这次修改想总结一下如何写一个不被人骂的sql。

    说一些被人诟病的问题:

    一、子查询

      把你的子查询全部改为join!!! 把你的子查询全部改为join!!! 把你的子查询全部改为join!!!  不要搞子查询,因为子查询的速度真的很慢。

    把你用到的表先准备出来,找好关联关系做成 left join 或者 inner join 别问我为什么不用 right join mysql里面没有啊~

    二、没索引

      几个必须加索引的地方:

      1.主键自动建立唯一索引

      2. 频繁作为where条件语句查询的字段

      3. 关联字段需要建立索引,比如join表 on的字段

      4. 排序字段可以建立索引

      5. 分组字段可以建立索引,因为分组的前提是排序

      6. 统计字段,聚合函数 可以建立索引,例如count(),max()

      当然索引也不是哪都合适的:

      1.频繁更新的字段不适合建立索引

      2.where条件中用不到的字段不适合建立索引

      3.表数据可以确定比较少的不需要建索引 少于1000条

      4.数据重复且发布比较均匀的的字段不适合建索引(唯一性太差的字段不适合建立索引),例如性别,状态

      5. 参与列计算的列不适合建索引

      索引什么时候会失效:

      1. 索引中不能有列的值是null 所以 is null 或者 not null 索引不起作用

      2. 单独引用复合索引里非第一位置的索引列:比如索引是a,b,c  那么 a / a,b / a,b,c 都可以使用索引,而 b / b,c 则不行

      3. 对索引列运算 运算包括(+、-、*、/、!、<>、%、like’%_’(%放在前面)、or、in、exist等),导致索引失效。

      4. 对索引应用内部函数 比如: select * from table_A  where ROUND(id) = 1 此时应该建ROUND(id)为索引。

      5. 类型错误,如字段类型为varchar,where条件用number。

    例:id字段是varchar类型。

    错误写法:select * from table where id= 1

    正确写法:select * from table where id = ‘1’

      6. 当or 条件时 必须所有的条件都是独立索引才能走索引

      7. mysql查询只能使用一个索引,如果where中已经使用了索引,那么order by 中就无法使用。前半句举例:select * from table where xxx= '1' and yyy =2 如果 xxx,yyy都时独立索引 那么只能xxx走了索引,其实已经很快了,如果想更快就建组合索引。

      创建索引

      1. 普通索引:create index '索引名'  on '表名' ('字段名‘(length));  alter table '表名' add index '索引名' ('字段名 (ength));

      2. 唯一索引 可以为空 :create unique index '索引名'  on '表名' (字段名(length));

      3. 主键索引 唯一切不为空:alter table ‘表名’ add primary key(‘列名’);

      4. 组合索引:create index '索引名'  on '表名'('字段名1’,'字段名2’);  

     三、正确选择 in , exists 和inner join 

      1. 如果集合比较小的时候,选择in 因为 in 先查询子集

      2. 如果集合比较大的时候,选择exists 因为 exists 先查询主查询 exists 简单使用:

      SELECT c.CustomerId,CompanyName FROM Customers c WHERE EXISTS( SELECT OrderID FROM Orders o WHERE o.CustomerID=c.CustomerID) 

      这里面的EXISTS是如何运作呢?子查询返回的是OrderId字段,可是外面的查询要找的是CustomerID和CompanyName字段,这两个字段肯定不在OrderID里面啊,这是如何匹配的呢? 

      EXISTS用于检查子查询是否至少会返回一行数据,该子查询实际上并不返回任何数据,而是返回值True或False 。

      EXISTS 指定一个子查询,检测 行 的存在。

      语法: EXISTS subquery

      参数: subquery 是一个受限的 SELECT 语句 (不允许有 COMPUTE 子句和 INTO 关键字)。

      结果类型: Boolean 如果子查询包含行,则返回 TRUE ,否则返回 FLASE 。

      3. 如果是not 就选exists 吧 。

      4. inner joiin 如果你用 in 或者 exists 是会返回主表的行  但是inner join 如果子查询有重复值的话 就会返回重复行 。

    四、其他

      1. 减少order by 的使用,order by 、group by 、distinct 耗CPU大。

  • 相关阅读:
    微信小程序promise解决onload异步
    小程序中使用 Less (VScode)
    Vue中使用less
    小程序获取 图片宽高
    ssh 登录出现Are you sure you want to continue connecting (yes/no)?解决方法
    SQL SERVER 收缩日志
    SQL SERVER-日期时间
    oracle判断查询结果是否为空
    修改Tomcat默认JDK版本
    Microsoft SQL Server Management Studio ------- 附加数据库 对于 服务器“xxx&amp;amp;quot;失败(错误码5120)
  • 原文地址:https://www.cnblogs.com/xcgShare/p/11791889.html
Copyright © 2020-2023  润新知