zoukankan      html  css  js  c++  java
  • mysql性能优化之数据库级别优化--优化sql语句

    一  优化SELECT语句

    1.1 WHERE子句优化

      本文暂时只讨论可以处理WHERE子句的优化,下面的一些实例使用SELECT语句,但是相同的优化同样适用DELETE和UPDATE语句中的WHERE子句,同样文中有些作者也不理解的地方,希望路过的大神指教

     你或许会重写你的查询来让计算操作更快,或许会牺牲一些可读性.你通常可以不用浪费这个时间,因为MySQL会自动执行相同的优化,
    而且会让查询更加容易理解,更加容易维护.MySQL会执行如下优化:

      1 删除不必要的括号

        ((a and b ) and c or (((a and b ) and ( c and d ))))

        --->  (a and b and c ) or (a and b and c and d)

      2 恒定折叠(尽量使用常量,不使用变量)

        ( a > b and b = c) and a = 5  

        --> b > 5 and b = c and a = 5

      3 恒定条件去除 (去除无用的sql条件)

        ( b >=5 and b = 5 ) or ( b = 6 and 5 = 5 ) or ( b = 7 and 5 = 6 )

        ---> b = 5 or b = 6

      4 索引使用的常量表达式仅计算一次  ?

      5 COUNT(*)优化

        COUNT(*)在没有WHERE的单个表上时直接从Myisam和MEMORY表的表信息中检索. 当仅与一个表使用时,这也适用于任何 NOT NULL表达式。

        对于诸如Innodb之类的事务型存储引擎,不会存储确切的行数,因为可能正在发生多个事务,每个事务都可能影响计数,

      6 尽早检测无效的常量表达式

        MySQL快速检测到一些select语句是不可能的,并且不返回任何的行。

      7 尽量将WHERE、HAVING合并

        如果不使用GROUP  BY 或聚合函数 (COUNT() MIN() AVG()等),尽量将HAVING与WHERE合并

        select * from t1 (select * from tab where id > 10) as t2 where t1.age > 10 and t2.age < 25

        --> select * from t1,tab as t2 where t1.age > 10 and t2.id > 10 and t2.age < 25.

        具体步骤:

        1)from与form合并,修改相应的参数

        2)where与where合并,用and连接

        3)修改相应的谓词(in改=)

      8  对于连接中的每个表,构造一个更简单的WHERE条件,以便快速的对表的条件进行评估,并尽可能快的跳过行。(连接的时候  join on 的列要简单)

      9  在查询任何其他表之前,首先读取的是常量表;常量表可以是下面的任何一种

        1) 空的表或只有一行的表

        2) 在主键或唯一索引上使用where子句的表,其中所有索引部件都与常量表达式比较,并被定义为  NOT NULL

        下面所有表都被用作常量表

         select * from t where primary_key = 1;

         select * from t1,t2 where t1.primary_key = 1 and t2.primary_key = t1.id;

      10  通过尝试join的所有组合来找到最好的组合方式。如果ORDER BY,GROUP BY 语句里面所有的列都来自同一个数据表,这个数据表回应该是join的第一个数据表

      11  如果ORDER BY和GROUP BY语句不同,或者如果ORDER BY和GROUP BY 包含列来自的数据表和join队列里第一个数据表不同,一个临时表将会被创建

      12  如果你使用了SQL_SMALL_REDULT选项,MySQL使用内存临时表

      13  每个数据表的索引都会被查询,会使用一个最好的索引,除非优化器相信当前选择直接表扫描更加高效.从前,最佳索引判断是索引是否能够过滤表的
      百分之30的数据.但是固定的百分比将不会是决定使用索引还是表扫描的因素. 当前的优化器现在更加复杂,基于包含其他因素的估价模型,比如表的大小,行的数目,
      I/O块数目.

      14 在有些样例下,MySQL能够从索引中直接读取行并且不用读取数据文件,如果索引中所有的行都是数字类型,仅使用索引书来解决查询

      15  在每一行输出前,跳过与HAVING子句不匹配的行

      16 优化选择条件的排列顺序, 把能够过滤更多数据的条件放在前面,过滤少的条件放在后面

      例如: select * from user

        where id = 1                     // 条件1 过滤数据较多

        and class_id > 1000;        // 条件2 过滤数据较少

    下面是一些查询速度较快的示例:

    select count(*) from t1;

    SELECT MIN(key_part1),MAX(key_part1) FROM tbl_name;

    SELECT MAX(key_part2) FROM tbl_name
    WHERE key_part1=constant;

    SELECT ... FROM tbl_name
    ORDER BY key_part1,key_part2,... LIMIT 10;

    SELECT ... FROM tbl_name
    ORDER BY key_part1 DESC, key_part2 DESC, ... LIMIT 10;

    如果索引列是数字型的,MySQL仅使用二级索引解决以下查询:

    SELECT key_part1,key_part2 FROM tbl_name WHERE key_part1=val;

    SELECT COUNT(*) FROM tbl_name
    WHERE key_part1=val1 AND key_part2=val2;

    SELECT key_part2 FROM tbl_name GROUP BY key_part1;

    以下查询使用索引数据按排序顺序检索行,而无需单独的排序传递:

    SELECT ... FROM tbl_name
    ORDER BY key_part1,key_part2,... ;

    SELECT ... FROM tbl_name
    ORDER BY key_part1 DESC, key_part2 DESC, ... ;

  • 相关阅读:
    关于程序员认知和编程学习,没有任何一篇文章会讲得如此透彻
    Found 1 slaves: Use of uninitialized value in printf at /usr/local/percona-toolkit/bin/pt-online-schema-change line 8489
    alert 多语言的处理
    #!/bin/sh & #!/bin/bash区别
    mysql 常用
    java.io.FileNotFoundException
    struts1 & jquery form 文件异步上传
    简单的数据库连接池实例(java语言)
    null id in com.rocky.** entry 错误处理
    java unsupported major.minor version 51.0 解决
  • 原文地址:https://www.cnblogs.com/skl-bobo/p/10698191.html
Copyright © 2011-2022 走看看