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 

     

  • 相关阅读:
    108. Convert Sorted Array to Binary Search Tree
    107. Binary Tree Level Order Traversal II
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    104. Maximum Depth of Binary Tree
    103. Binary Tree Zigzag Level Order Traversal
    102. Binary Tree Level Order Traversal
    系统和进程相关信息
    文件I/0缓冲
    系统编程概念(文件系统mount等函数的使用)
  • 原文地址:https://www.cnblogs.com/Camiluo/p/11679126.html
Copyright © 2011-2022 走看看