zoukankan      html  css  js  c++  java
  • MySQL 查询优化

    1、MySQL 查询统计数据表行数三种方式:select count(*) 、select count(1) 、select count(具体字段),三者查询效率是怎么样的呢?

    解答:

    在MySQL InnoDB 存储引擎中,count(*) 和count(*) 都是对所有结果进行count。如果有where 子句,则是对所有筛选条件的数据行进行统计;如果没有where子句,则是对数据表的数据行数进行统计。

    因此count(*) 和 count(1) 本质上并没有区别,执行的复杂度都是O(N),也就是采用全表扫描,进行循环+计数的方式进行统计。

    如果是MySQL MyISAM 存储引擎,统计数据表的行数只需要O(1)的复杂度,这是因为每张MyISAM的数据表都有一个meta信息存储了row_count值,而一致性则由表级锁来保证,因为InnoDB支持事务,采用行级锁和MVCC机制,所以无法像MyISAM一样,只维护一个row_count变量,因此采用扫描全表,进行循环+计数的方式来完成统计;

    在执行过程中,count(*) 和 count(1)执行时间略有差别,不过效率可以基本看成是相等的。

    一般情况,三者的执行效率count(1) = count(*) >count(字段)。我们尽量使用count(*),当然如果你知道你要统计的是某个字段的非空数据行数,则另当别论,毕竟比较执行效率的前提是结果一样才可以。

    如果统计count(*),尽量在数据表上建立二级索引,系统会自动采用key_len小的二级索引,这样当我们使用select count(*) 的时候效率会提升。

    2、limit 关键词是最后执行的,如果只有一条结果,limit 还有用吗?

    解答:

    如果你确认结果集只有一条,加上limit 1,当找到一条结果的时候就不会继续扫描了,这样会加快查询速度,这里指的查询优化针对的是会扫描全表的sql语句,如果数据表已经对字段建立了唯一索引,那么可以通过索引进行查询,不会全表扫描的话,就不需要加limit了。

    3、可以理解在where 条件字段上加索引,但是为什么在order by 字段上还要加索引呢?这个时候已经通过where条件过滤得到了数据,已经不需要再筛选过滤数据了,只需要根据字段排序就好了。

    解答:

    在MySQL中支持两种排序方式,分别是FileSort 和 Index 排序。在Index中,索引可以保证数据的有序性,不需要再进行排序,效率更高。filesort 排序则一般再内存中进行排序,占用cpu较多,如果待排结果较大,会产生临时文件I/O到磁盘进行排序的情况,效率较低。

    所以使用Order by 子句时,应该尽量使用Index 排序,避免使用File Sort排序,当然你可以使用explain 来查看执行计划。

    优化建议:

    1)SQL中,可以在where 子句和order by 子句中使用索引,目的在where子句中避免全表扫描,在order by子句避免使用File sort排序,当然某些情况下全表扫描,或者filesort排序不一定比索引慢。

    2)尽量使用index 完成order by排序,如果where 和order by 后面是相同的列就使用单列索引,不是则使用联合索引。

    3)无法使用index 时,需要对filesort方式进行调优。

    4、order by 是对分的组排序还是对分组中的记录排序呢?

    解答:

    order by 就是对记录进行排序,如果你在order by 前面用了group by,实际上这是一种分组的聚合方式,已经把一组的数据聚合成为了一条记录,再进行排序的时候,相对于对分的组进行了排序。

    5、一条完整的select 语句内部的执行顺序是这样的:

    1、from 子句组装数据(包括通过on进行连接);

    2、where 子句进行条件筛选;

    3、group by 分组;

    4、使用聚合函数进行计算;

    5、having 筛选分组;

    6、计算所有的表达式;

    7、select 的字段;

    8、order by 排序;

    9、limit 筛选。

    6、不太理解哪种情况下应该使用exists,哪种情况使用in。选择的标准是看能否使用表的索引吗?

    解答:

    索引是个前提,其实选择与否还是要看表的大小,你可以将选择的标准理解为小表驱动大表,这种方式是效率最高的。

    比如:

    SELECT * FROM A WHERE cc IN (SELECT cc FROM B)
    SELECT * FROM A WHERE EXISTS (SELECT cc FROM B WHERE B.cc=A.cc)
    

      当A<B时,用 EXISTS。因为 EXISTS 的实现,相当于外表循环,实现的逻辑类似于:

    for i in A
      for j in B
        if j.cc == i.cc then ...
    

     当B<A时,用in,因为实现的逻辑类似于:

    for i in B
        for j in A
            if j.cc == i.cc then    
    

     哪个表小就用哪个表来驱动,A表小就用exists,B表小就用in 

     

  • 相关阅读:
    配置sql server 2000以允许远程访问
    SQLServer大数据量插入BULK INSERT
    【项目经理之修炼(5)】《基础篇》别把项目成功当目标(转)
    C#XML文件操作类
    winform窗体总在所有窗体最上层
    配置VSS2005的Internet访问(转)
    U盘引导盘制作
    【项目经理之修炼(4)】《基础篇》故事的主角是你吗?(转)
    SQLServer收缩数据库日志
    【项目经理之修炼(1)】《序章》关于要写给谁看的问题(转)
  • 原文地址:https://www.cnblogs.com/Camiluo/p/11679126.html
Copyright © 2011-2022 走看看