zoukankan      html  css  js  c++  java
  • 让你的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大。

  • 相关阅读:
    Do You See Me? Ethical Considerations of the Homeless
    ELDER HOMELESSNESS WHY IS THIS AN ISSUE?
    Endoflife support is lacking for homeless people
    html内联框架
    html字体
    html块 div span
    html列表
    html表格
    SQL Server管理员专用连接的使用   作为一名DBA,经常会处理一些比较棘手的服务无响应问题,鉴于事态的严重性,多数DBA可能直接用“重启”大法,以便尽快的恢复生产环境的正常运转,但是多数情况
    如何配置最大工作线程数 (SQL Server Management Studio)
  • 原文地址:https://www.cnblogs.com/xcgShare/p/11791889.html
Copyright © 2011-2022 走看看