您的位置:澳门新葡8455最新网站 > 数据库管理 > 正确使用索引,mysql索引补充

正确使用索引,mysql索引补充

发布时间:2019-12-01 12:31编辑:数据库管理浏览(148)

    科学使用索引

    数据库表中增加索引后的确会让查询速度起飞,但前提必需是不易的使用索引来查询,如若以错误的不二诀要利用,则便是创立目录也会不看到成效。
    便是建设构造目录,索引也不会收效:

     1 - like '%xx'
     2     select * from tb1 where name like '%cn';
     3 - 使用函数
     4     select * from tb1 where reverse(name) = 'wupeiqi';
     5 - or
     6     select * from tb1 where nid = 1 or email = 'seven@live.com';
     7     特别的:当or条件中有未建立索引的列才失效,以下会走索引
     8             select * from tb1 where nid = 1 or name = 'seven';
     9             select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'
    10 - 类型不一致
    11     如果列是字符串类型,传入条件是必须用引号引起来,不然...
    12     select * from tb1 where name = 999;
    13 - !=
    14     select * from tb1 where name != 'alex'
    15     特别的:如果是主键,则还是会走索引
    16         select * from tb1 where nid != 123
    17 - >
    18     select * from tb1 where name > 'alex'
    19     特别的:如果是主键或索引是整数类型,则还是会走索引
    20         select * from tb1 where nid > 123
    21         select * from tb1 where num > 123
    22 - order by
    23     select email from tb1 order by name desc;
    24     当根据索引排序时候,选择的映射如果不是索引,则不走索引
    25     特别的:如果对主键排序,则还是走索引:
    26         select * from tb1 order by nid desc;
    27  
    28 - 组合索引最左前缀
    29     如果组合索引为:(name,email)
    30     name and email       -- 使用索引
    31     name                 -- 使用索引
    32     email                -- 不使用索引
    

    目录补充

     

    1、索引
      索引是表的目录,在搜索内容前边能够先在目录中查找索引地方,以此一点也不慢牢固查询数据。对于索引,会保留在附加的公文中。

    2、索引系列

    • 平时索引:仅加快查询
    • 独一索引:加快查询 + 列值唯风流浪漫(能够有null)
    • 主键索引:加速查询 + 列值唯黄金年代+ 表中只有三个(不得以有null)
    • 组合索引:多列值组成贰个索引,
                    特意用于组合寻觅,其功用超过索引归总
    • 全文索引:对文本的内容实行分词,实行搜索 

    索引归拢,使用七个单列索引组合寻觅
    覆盖索引,select的数据列只用从索引中就可以知道得到,不必读取数据行,换句话说查询列要被所建的目录覆盖

    3、相关命令

    ?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    - 查看表结构
        desc 表名
     
    - 查看生成表的SQL
        show create table 表名
     
    - 查看索引
        show index from  表名
     
    - 查看执行时间
        set profiling = 1;
        SQL...
        show profiles;

    4、使用索引和不应用索引

    ?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    由于索引是专门用于加速搜索而生,所以加上索引之后,查询效率会快到飞起来。
     
    # 有索引
    mysql> select * from tb1 where name = 'wupeiqi-888';
    +-----+-------------+---------------------+----------------------------------+---------------------+
    | nid | name        | email               | radom                            | ctime               |
    +-----+-------------+---------------------+----------------------------------+---------------------+
    | 889 | wupeiqi-888 | wupeiqi888@live.com | 5312269e76a16a90b8a8301d5314204b | 2016-08-03 09:33:35 |
    +-----+-------------+---------------------+----------------------------------+---------------------+
    1 row in set (0.00 sec)
     
    # 无索引
    mysql> select * from tb1 where email = 'wupeiqi888@live.com';
    +-----+-------------+---------------------+----------------------------------+---------------------+
    | nid | name        | email               | radom                            | ctime               |
    +-----+-------------+---------------------+----------------------------------+---------------------+
    | 889 | wupeiqi-888 | wupeiqi888@live.com | 5312269e76a16a90b8a8301d5314204b | 2016-08-03 09:33:35 |
    +-----+-------------+---------------------+----------------------------------+---------------------+
    1 row in set (1.23 sec)

    5、正确运用索引

    数据库表中增加索引后着实会让查询速度起飞,但前提必得是对的的使用索引来查询,如若以错误的办法使用,则就是建设结构目录也会不奏效。
    固然建设布局目录,索引也不会立见成效:

    ?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    - like '%xx'
        select * from tb1 where name like '%cn';
    - 使用函数
        select * from tb1 where reverse(name) = 'wupeiqi';
    - or
        select * from tb1 where nid = 1 or email = 'seven@live.com';
        特别的:当or条件中有未建立索引的列才失效,以下会走索引
                select * from tb1 where nid = 1 or name = 'seven';
                select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'
    - 类型不一致
        如果列是字符串类型,传入条件是必须用引号引起来,不然...
        select * from tb1 where name = 999;
    - !=
        select * from tb1 where name != 'alex'
        特别的:如果是主键,则还是会走索引
            select * from tb1 where nid != 123
    - >
        select * from tb1 where name > 'alex'
        特别的:如果是主键或索引是整数类型,则还是会走索引
            select * from tb1 where nid > 123
            select * from tb1 where num > 123
    - order by
        select email from tb1 order by name desc;
        当根据索引排序时候,选择的映射如果不是索引,则不走索引
        特别的:如果对主键排序,则还是走索引:
            select * from tb1 order by nid desc;
     
    - 组合索引最左前缀
        如果组合索引为:(name,email)
        name and email       -- 使用索引
        name                 -- 使用索引
        email                -- 不使用索引

    6、别的注意事项

    ?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    - 避免使用select *
    - count(1)或count(列) 代替 count(*)
    - 创建表时尽量时 char 代替 varchar
    - 表的字段顺序固定长度的字段优先
    - 组合索引代替多个单列索引(经常使用多个条件查询时)
    - 尽量使用短索引
    - 使用连接(JOIN)来代替子查询(Sub-Queries)
    - 连表时注意条件类型需一致
    - 索引散列值(重复少)不适合建索引,例:性别不适合

    7、limit分页

    无论是或不是有目录,limit分页是叁个值得关怀的主题材料

    图片 1图片 2

    每页显示10条:
    当前 118 120, 125
    
    倒序:
                大      小
                980    970  7 6  6 5  54  43  32
    
    21 19 98     
    下一页:
    
        select 
            * 
        from 
            tb1 
        where 
            nid < (select nid from (select nid from tb1 where nid < 当前页最小值 order by nid desc limit 每页数据 *【页码-当前页】) A order by A.nid asc limit 1)  
        order by 
            nid desc 
        limit 10;
    
    
    
        select 
            * 
        from 
            tb1 
        where 
            nid < (select nid from (select nid from tb1 where nid < 970  order by nid desc limit 40) A order by A.nid asc limit 1)  
        order by 
            nid desc 
        limit 10;
    
    
    上一页:
    
        select 
            * 
        from 
            tb1 
        where 
            nid < (select nid from (select nid from tb1 where nid > 当前页最大值 order by nid asc limit 每页数据 *【当前页-页码】) A order by A.nid asc limit 1)  
        order by 
            nid desc 
        limit 10;
    
    
        select 
            * 
        from 
            tb1 
        where 
            nid < (select nid from (select nid from tb1 where nid > 980 order by nid asc limit 20) A order by A.nid desc limit 1)  
        order by 
            nid desc 
        limit 10;
    

    View Code

    8、试行计划

    explain + 查询SQL - 用于体现SQL实施消息参数,根据华日报方可开展SQL优化

    ?

    1
    2
    3
    4
    5
    6
    7
    mysql> explain select * from tb2;
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    |  1 | SIMPLE      | tb2   | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
    +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    1 row in set (0.00 sec)

    图片 3图片 4

        id
            查询顺序标识
                如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
                +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
                | id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
                +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
                |  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL |    9 | NULL        |
                |  2 | DERIVED     | tb1        | range | PRIMARY       | PRIMARY | 8       | NULL |    9 | Using where |
                +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
            特别的:如果使用union连接气值可能为null
    
    
        select_type
            查询类型
                SIMPLE          简单查询
                PRIMARY         最外层查询
                SUBQUERY        映射为子查询
                DERIVED         子查询
                UNION           联合
                UNION RESULT    使用联合的结果
                ...
        table
            正在访问的表名
    
    
        type
            查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
                ALL             全表扫描,对于数据表从头到尾找一遍
                                select * from tb1;
                                特别的:如果有limit限制,则找到之后就不在继续向下扫描
                                       select * from tb1 where email = 'seven@live.com'
                                       select * from tb1 where email = 'seven@live.com' limit 1;
                                       虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。
    
                INDEX           全索引扫描,对索引从头到尾找一遍
                                select nid from tb1;
    
                RANGE          对索引列进行范围查找
                                select *  from tb1 where name < 'alex';
                                PS:
                                    between and
                                    in
                                    >   >=  <   <=  操作
                                    注意:!= 和 > 符号
    
    
                INDEX_MERGE     合并索引,使用多个单列索引搜索
                                select *  from tb1 where name = 'alex' or nid in (11,22,33);
    
                REF             根据索引查找一个或多个值
                                select *  from tb1 where name = 'seven';
    
                EQ_REF          连接时使用primary key 或 unique类型
                                select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;
    
    
    
                CONST           常量
                                表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
                                select nid from tb1 where nid = 2 ;
    
                SYSTEM          系统
                                表仅有一行(=系统表)。这是const联接类型的一个特例。
                                select * from (select nid from tb1 where nid = 1) as A;
        possible_keys
            可能使用的索引
    
        key
            真实使用的
    
        key_len
            MySQL中使用索引字节长度
    
        rows
            mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值
    
        extra
            该列包含MySQL解决查询的详细信息
            “Using index”
                此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
            “Using where”
                这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
            “Using temporary”
                这意味着mysql在对查询结果排序时会使用一个临时表。
            “Using filesort”
                这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
            “Range checked for each record(index map: N)”
                这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。
    

    详细

    越来越多参见:
      
      

    9、慢日志查询

    a、配置MySQL自动记录慢日志

    slow_query_log = OFF                            是或不是开启慢日志记录
    long_query_time = 2                              时间范围,当先那时候间,则记录
    slow_query_log_file = /usr/slow.log        日志文件
    log_queries_not_using_indexes = OFF     为利用索引的搜索是或不是记录

    注:查看当前安插信息:
           show variables like '%query%'
         改革当前铺排:
        set global 变量名 = 值

    b、查看MySQL慢日志

    mysqldumpslow -s at -a  /usr/local/var/mysql/MacBook-Pro-3-slow.log

    ?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    """
    --verbose    版本
    --debug      调试
    --help       帮助
     
    -v           版本
    -d           调试模式
    -s ORDER     排序方式
                 what to sort by (al, at, ar, c, l, r, t), 'at' is default
                  al: average lock time
                  ar: average rows sent
                  at: average query time
                   c: count
                   l: lock time
                   r: rows sent
                   t: query time
    -r           反转顺序,默认文件倒序拍。reverse the sort order (largest last instead of first)
    -t NUM       显示前N条just show the top n queries
    -a           不要将SQL中数字转换成N,字符串转换成S。don't abstract all numbers to N and strings to 'S'
    -n NUM       abstract numbers with at least n digits within names
    -g PATTERN   正则匹配;grep: only consider stmts that include this string
    -h HOSTNAME  mysql机器名或者IP;hostname of db server for *-slow.log filename (can be wildcard),
                 default is '*', i.e. match all
    -i NAME      name of server instance (if using mysql.server startup script)
    -l           总时间中不减去锁定时间;don't subtract lock time from total time
    """

      

    此外注意事项

    1 - 避免使用select *
    2 - count(1)或count(列) 代替 count(*)
    3 - 创建表时尽量时 char 代替 varchar
    4 - 表的字段顺序固定长度的字段优先
    5 - 组合索引代替多个单列索引(经常使用多个条件查询时)
    6 - 尽量使用短索引
    7 - 使用连接(JOIN)来代替子查询(Sub-Queries)
    8 - 连表时注意条件类型需一致
    9 - 索引散列值(重复少)不适合建索引,例:性别不适合
    

    limit分页

    不管是或不是有目录,limit分页是一个值得关怀的主题素材

    图片 5图片 6

     1 每页显示10条:
     2 当前 118 120, 125
     3 
     4 倒序:
     5             大      小
     6    970  7 6  6 5  54  43  32
     7 19 98     
     8 下一页:
     9 
    10     select 
    11         * 
    12     from 
    13         tb1 
    14     where 
    15         nid < (select nid from (select nid from tb1 where nid < 当前页最小值 order by nid desc limit 每页数据 *【页码-当前页】) A order by A.nid asc limit 1)  
    16     order by 
    17         nid desc 
    18     limit 10;
    19 
    20 
    21 
    22     select 
    23         * 
    24     from 
    25         tb1 
    26     where 
    27         nid < (select nid from (select nid from tb1 where nid < 970  order by nid desc limit 40) A order by A.nid asc limit 1)  
    28     order by 
    29         nid desc 
    30     limit 10;
    31 
    32 
    33 上一页:
    34 
    35     select 
    36         * 
    37     from 
    38         tb1 
    39     where 
    40         nid < (select nid from (select nid from tb1 where nid > 当前页最大值 order by nid asc limit 每页数据 *【当前页-页码】) A order by A.nid asc limit 1)  
    41     order by 
    42         nid desc 
    43     limit 10;
    44 
    45 
    46     select 
    47         * 
    48     from 
    49         tb1 
    50     where 
    51         nid < (select nid from (select nid from tb1 where nid > 980 order by nid asc limit 20) A order by A.nid desc limit 1)  
    52     order by 
    53         nid desc 
    54     limit 10;
    

    View Code

    实行安排

    explain + 查询SQL - 用于体现SQL推行音讯参数,根据中新社方可开展SQL优化

    1 mysql> explain select * from tb2;
    2 +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    3 | id | select_type | table | type | possible_keys | key  | key_len | ref  | rows | Extra |
    4 +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    5 |  1 | SIMPLE      | tb2   | ALL  | NULL          | NULL | NULL    | NULL |    2 | NULL  |
    6 +----+-------------+-------+------+---------------+------+---------+------+------+-------+
    7 1 row in set (0.00 sec)
    

    图片 7图片 8

     1 id
     2         查询顺序标识
     3             如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
     4             +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
     5             | id | select_type | table      | type  | possible_keys | key     | key_len | ref  | rows | Extra       |
     6             +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
     7             |  1 | PRIMARY     | <derived2> | ALL   | NULL          | NULL    | NULL    | NULL |    9 | NULL        |
     8             |  2 | DERIVED     | tb1        | range | PRIMARY       | PRIMARY | 8       | NULL |    9 | Using where |
     9             +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
    10         特别的:如果使用union连接气值可能为null
    11 
    12 
    13     select_type
    14         查询类型
    15             SIMPLE          简单查询
    16             PRIMARY         最外层查询
    17             SUBQUERY        映射为子查询
    18             DERIVED         子查询
    19             UNION           联合
    20             UNION RESULT    使用联合的结果
    21             ...
    22     table
    23         正在访问的表名
    24 
    25 
    26     type
    27         查询时的访问方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
    28             ALL             全表扫描,对于数据表从头到尾找一遍
    29                             select * from tb1;
    30                             特别的:如果有limit限制,则找到之后就不在继续向下扫描
    31                                    select * from tb1 where email = 'seven@live.com'
    32                                    select * from tb1 where email = 'seven@live.com' limit 1;
    33                                    虽然上述两个语句都会进行全表扫描,第二句使用了limit,则找到一个后就不再继续扫描。
    34 
    35             INDEX           全索引扫描,对索引从头到尾找一遍
    36                             select nid from tb1;
    37 
    38             RANGE          对索引列进行范围查找
    39                             select *  from tb1 where name < 'alex';
    40                             PS:
    41                                 between and
    42                                 in
    43                                 >   >=  <   <=  操作
    44                                 注意:!= 和 > 符号
    45 
    46 
    47             INDEX_MERGE     合并索引,使用多个单列索引搜索
    48                             select *  from tb1 where name = 'alex' or nid in (11,22,33);
    49 
    50             REF             根据索引查找一个或多个值
    51                             select *  from tb1 where name = 'seven';
    52 
    53             EQ_REF          连接时使用primary key 或 unique类型
    54                             select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;
    55 
    56 
    57 
    58             CONST           常量
    59                             表最多有一个匹配行,因为仅有一行,在这行的列值可被优化器剩余部分认为是常数,const表很快,因为它们只读取一次。
    60                             select nid from tb1 where nid = 2 ;
    61 
    62             SYSTEM          系统
    63                             表仅有一行(=系统表)。这是const联接类型的一个特例。
    64                             select * from (select nid from tb1 where nid = 1) as A;
    65     possible_keys
    66         可能使用的索引
    67 
    68     key
    69         真实使用的
    70 
    71     key_len
    72         MySQL中使用索引字节长度
    73 
    74     rows
    75         mysql估计为了找到所需的行而要读取的行数 ------ 只是预估值
    76 
    77     extra
    78         该列包含MySQL解决查询的详细信息
    79         “Using index”
    80             此值表示mysql将使用覆盖索引,以避免访问表。不要把覆盖索引和index访问类型弄混了。
    81         “Using where”
    82             这意味着mysql服务器将在存储引擎检索行后再进行过滤,许多where条件里涉及索引中的列,当(并且如果)它读取索引时,就能被存储引擎检验,因此不是所有带where子句的查询都会显示“Using where”。有时“Using where”的出现就是一个暗示:查询可受益于不同的索引。
    83         “Using temporary”
    84             这意味着mysql在对查询结果排序时会使用一个临时表。
    85         “Using filesort”
    86             这意味着mysql会对结果使用一个外部索引排序,而不是按索引次序从表里读取行。mysql有两种文件排序算法,这两种排序方式都可以在内存或者磁盘上完成,explain不会告诉你mysql将使用哪一种文件排序,也不会告诉你排序会在内存里还是磁盘上完成。
    87         “Range checked for each record(index map: N)”
    88             这个意味着没有好用的索引,新的索引将在联接的每一行上重新估算,N是显示在possible_keys列中索引的位图,并且是冗余的。
    

    详细

    慢日志查询

    a、配置MySQL自动记录慢日志

    1 slow_query_log = OFF                            是否开启慢日志记录
    2 long_query_time = 2                              时间限制,超过此时间,则记录
    3 slow_query_log_file = /usr/slow.log        日志文件
    4 log_queries_not_using_indexes = OFF     为使用索引的搜索是否记录
    

    注:查看当前配备新闻:
           show variables like '%query%'
         纠正当前铺排:
        set global 变量名 = 值

    b、查看MySQL慢日志

    mysqldumpslow -s at -a  /usr/local/var/mysql/MacBook-Pro-3-slow.log

     1 """
     2 --verbose    版本
     3 --debug      调试
     4 --help       帮助
     5  
     6 -v           版本
     7 -d           调试模式
     8 -s ORDER     排序方式
     9              what to sort by (al, at, ar, c, l, r, t), 'at' is default
    10               al: average lock time
    11               ar: average rows sent
    12               at: average query time
    13                c: count
    14                l: lock time
    15                r: rows sent
    16                t: query time
    17 -r           反转顺序,默认文件倒序拍。reverse the sort order (largest last instead of first)
    18 -t NUM       显示前N条just show the top n queries
    19 -a           不要将SQL中数字转换成N,字符串转换成S。don't abstract all numbers to N and strings to 'S'
    20 -n NUM       abstract numbers with at least n digits within names
    21 -g PATTERN   正则匹配;grep: only consider stmts that include this string
    22 -h HOSTNAME  mysql机器名或者IP;hostname of db server for *-slow.log filename (can be wildcard),
    23              default is '*', i.e. match all
    24 -i NAME      name of server instance (if using mysql.server startup script)
    25 -l           总时间中不减去锁定时间;don't subtract lock time from total time
    26 """
    

     

    本文由澳门新葡8455最新网站发布于数据库管理,转载请注明出处:正确使用索引,mysql索引补充

    关键词:

上一篇:没有了

下一篇:CUBENCOREID学习笔记,Server函数之空值管理