zoukankan      html  css  js  c++  java
  • DQL:data query language用来查询数据库表中的数据

    对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引

    如果没有查询条件,则每次查询所有的行。实际应用中,一般要指定查询的条件。对记录进行过滤。

    查询的语法:

    select
            字段列表
        from
            表名列表
        where
            条件列表
        group by
            分组字段
        having
            分组之后的条件
        order by
            排序
        limit
            分页限定

    1、基础查询

    SELECT * FROM 表名;

    Select的优化:

    任何地方都不要使用 select * from t ,用具体的字段列表代替“*”不要返回用不到的任何字段学习阶段偷懒才写*号。

    2、where条件查询(null,or,in,like,!=)

    我们也不能为了优化而束手束脚,如果有些表数据了非常少,而且各种特殊的历史原因或者极端的需求下面,即便索引失效了,我们也要不得已而为之。即不要为了避免索引失效而不敢写sql,你要知道这种情况下会导致失效,但是该写的时候也要写。具体要看生产环境和业务,具体问题具体分析。

    Type:访问类型排列。区间索引,这是重要的列,显示查询使用了何种类型。从最好到最差的连接类型为:

    system > const > eq_ref > ref > ref_or_null > index_merge > unique_subquery > index_subquery >range > index > ALL

    一般来说,得保证查询至少达到range级别,最好能达到ref

    只要type是All,且数据量是百万以上的,请一定优化,因为All是最差的,表明是全表扫描。其实最好的程序是不优化。如果数据量有上百万了,且type为All,就需要跟经理DBA协商是否需要建索引。

    SELECT 字段名 FROM 表名 WHERE 条件;

    注意:

    *尽量将表字段定义为not null约束,这样不需要判断是否为null,如:int not null default -1,这是由于在mysql中含有空值的列很难进行查询优化,null值会使索引以及索引的统计信息变得很复杂。

    *通常使用特殊的数据进行占位,如:int not null default 0,String not null default ‘’,但是会产生歧义,如果数据恰好是一个空字符串,就会和默认值空字符串一样,如果数据恰好是0的话也是一样的,尽量使用不会出现在常规业务逻辑行中的数据作为默认,表示null数据,如用:int not null default -1,如年龄的话,可能有0,所以不用0来表示默认,而用-1,因为年龄不会出现-1。

    *尽量使用覆盖索引(只访问索引的查询(索引列和查询列一致)),减少select *。我们写sql的原则:最好是按需取数据,用多少取多少,尽量跟索引重合。尽量少用*

    使用*的话,共有四个字段,除了name,age,pos,还有入职时间add_time。

    Using where:表示使用了where过滤,去表中检索。

    用到了Using index,表示使用了索引覆盖,避免了访问表的数据行从索引中取数据,性能更加优秀,更好一些

     

    范围之后的索引会失效Using index表示去索引上拿,key_len为74而不是78,没有用到range,

    上面的例子中,你建的索引是name,age,pos,而你查的刚好是name,age,pos,一一吻合。而如果你只查询索引字段的一部分,此时也会用到Using index

    *应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描如:select id from t where num is null, 可以在num上设置默认值-1,确保表中num列没有null值,然后这样查询:select id from t where num=-1

     由于在网站注册的时候,name不能为null。大家都知道,实在不行,关键字段也要写default值等于-1或者其他,避免null值。

    而对于is not null,理论上用到索引,实际上没有用到索引。

    *尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫可以使用union all.如果使用Or,则要保证两边的条件都有索引可以用如:select id from t where num=10 or num=20,可以这样查询:

    select id from t where num=10 union all select id from t where num=20

    少用or,用它来连接时会索引失效。注意是少用而不是不用。

    *in 和 not in 也要慎用,否则会导致全表扫描,如:select id from t where num in(1,2,3);

    状态值即使在字段上增加了索引,往往索引不能起作用,如:gender 01,2表示男、女、保密,select * from student where gender in 1,2)。故状态值一般不使用索引,因为使用状态值时会导致一个状态值同时能够匹配到大量的记录;对于大量的记录,mysql有时会认为使用索引的开销比全表扫描还要大,从而主动放弃索引。即当你的条件容易匹配大量数据时,索引不一定能用得上。 对于连续的数值,能用 between 就不要用 in 了

    *Like查询不能以通配符开头,如:user like ‘%’,否则索引不会被使用字符串比较时,不能使用包含逻辑,如:subject like ‘%PHP%’,因为这将导致全表扫描,效率太低了,若要提高效率,可以考虑全文检索Mysql中全文索引不支持中文,用第三方提供的全文索引。

     

    解决like “%字符串%”时索引不被使用的方法:用覆盖索引来解决结论:没建索引之前,都是全表扫描。用覆盖索引来防止索引失效,从而避免全表扫描。

    覆盖索引就是:你建的索引和我查的字段个数和顺序完全一致。你建的索引是复合索引(name,age,

    *应尽量避免在 where 子句中使用!=或<>操作符,否则将放弃使用索引而进行全表扫描。mysql在使用不等于!=或者<><>也表示不等于)!=或者<,>的时候无法使用索引会导致全表扫描

    type为all,即全表扫描。Key:实际使用到的索引。如果为NULL,则没有使用索引。如果为primary的话,表示使用了主键。

    *字符串不加单引号索引失效。如果varchar类型写错了,一定会被项目经理骂死,即varchar类型绝对不能忘记单引号

     

     

    Name是varchar类型,name=2000仍然能查出结果,Mysql功能很强大,整数的2000String的2000一个是int类型,一个是varchar类型,name是varchar类型,而你写成整数的时候,这是mysql将会在底层自动的做一次类型转换,实现了从数字到String,从而帮你查出来。前面讲过,不要在索引列上做任何操作(自动类型转换),否则会导致索引失效。

    *存储引擎不能使用索引中范围条件右边的列

     

    Type由ref变为了range,范围之后的索引全失效。但是范围本身的字段age有被用到。Age与name还有点区别:name用于了查询,但是age只给了一个范围,age也用到了,否则不会给range,但是age用于去排序,而不是像name一样着重检索(查询),

    下图的key_len证明用到了age字段

    *不在索引列上做任何操作(计算、函数、自动或手动类型转换),会导致索引失效而转向全表扫描

    Left是mysql自带的函数,有点类似于java的subString函数。Left(name,4)表示从左边开始选四位。此时在索引列name上包了一个函数。·

    仍然能够查出来,但是索引会失效。

     

    3、分组查询

    语法:group by 分组字段

    注意:分组之后查询的字段,要么是分组字段,要么是聚合函数,不能写其他字段,因为写其他字段没有任何意义,我们现在把男生或女生当成一个整体看,故不应该出现个人的信息,而应该是整体的共性内容

    分组之前的条件用where,分组之后的条件用having。

    Where和having的区别

    1、 where在分组之前进行限定,如果不满足条件,则不参与分组Having是在分组之后进行限定,如果不满足结果就不会被查询出来。

    2、 where后不可以进行聚合函数的判断,having可以进行聚合函数的判断。我们可以给聚合函数取别名,having后进行判断时使用别名进行判断。

    4、排序查询

    语法:order by 排序字段1 排序方式1,排序字段2 排序方式2…

    经常作为查询条件在where或order by 语句中出现的列要建立索引。

    当使用两个排序条件时,只要当第一排序条件一样时,才会使用第二排序条件。每一个排序条件都可以指定不同的排序方式。

    5、分页查询

    语法:limit 开始的索引 每页查询的条数

     

    分页查询:limit 起始值从 0 开始, 长度

    第一个参数注意是开始的索引,不是当前页。

    开始的索引(当前页码-1*每页显示的条数

    limit是一个“方言”,limit关键字只能在mysql中使用

    LIMIT 子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT 接受一个或两个数字参数

    SELECT * FROM table LIMIT 5,10; // 检索记录行 6-15

    如果只给定一个参数,它表示返回最大的记录行数目,换句话说,LIMIT n 等价于 LIMIT 0,n

    mysql> SELECT * FROM table LIMIT 5; //检索前 5 个记录行

     

  • 相关阅读:
    uva 1606 极角扫描
    Codeforces Round #304 (Div. 2) 题解
    Codeforces Round #306 (Div. 2) 题解
    Codeforces Round #299 (Div. 2) 题解
    树链剖分专题
    bzoj 1036: [ZJOI2008]树的统计Count
    bzoj 1007: [HNOI2008]水平可见直线
    bzoj 1003: [ZJOI2006]物流运输trans
    Codeforces Round #301 (Div. 2) 题解
    bzoj 1026: [SCOI2009]windy数
  • 原文地址:https://www.cnblogs.com/zwh0910/p/14395194.html
Copyright © 2011-2022 走看看