• MySql之索引


    一.索引

        是数据库中专门用于帮助用户快速查询数据的一种数据结构。类似于字典中的目录,查找字典内容时可以根据目录查找到数据的存放位置,然后直接获取即可。

     二 索引使用

    1、主键索引

    create table in1(
        nid int not null auto_increment primary key,
        name varchar(32) not null,
        email varchar(64) not null,
        extra text,
        index ix_name (name)
    )
    
    OR
    
    create table in1(
        nid int not null auto_increment,
        name varchar(32) not null,
        email varchar(64) not null,
        extra text,
        primary key(ni1),
        index ix_name (name)
    )
    创建表 + 创建主键
    alter table 表名 add primary key(列名);
    创建主键
    alter table 表名 drop primary key;
    alter table 表名  modify  列名 int, drop primary key;
    删除主键

    2.普通索引

    create table in1(
        nid int not null auto_increment primary key,
        name varchar(32) not null,
        email varchar(64) not null,
        extra text,
        index ix_name (name)
    )
    创建表+索引
    create index index_name on table_name(column_name)
    创建索引
    create index index_name on table_name(column_name)
    删除索引
    show index from table_name;
    查看索引

    注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。

    create index ix_extra on in1(extra(32));
    View Code

    3.唯一索引

    create table in1(
        nid int not null auto_increment primary key,
        name varchar(32) not null,
        email varchar(64) not null,
        extra text,
        unique ix_name (name)
    )
    View Code
    create unique index 索引名 on 表名(列名)
    View Code
    drop unique index 索引名 on 表名
    View Code

    4.组合索引

    组合索引是将n个列组合成一个索引

    其应用场景为:频繁的同时使用n列来进行查询,如:where n1 = 'alex' and n2 = 666。

    create table in3(
        nid int not null auto_increment primary key,
        name varchar(32) not null,
        email varchar(64) not null,
        extra text
    )
    创建表
    create index ix_name_email on in3(name,email);
    创建组合索引

    如上创建组合索引之后,查询:

    • name and email  -- 使用索引
    • name                 -- 使用索引
    • email                 -- 不使用索引

    注意:对于同时搜索n个条件时,组合索引的性能好于多个单一索引合并。

    主键索引:            
    普通索引:
        - create index 索引名称 on 表名(列名,)
        - drop index 索引名称 on 表名
    唯一索引:
        - create unique index 索引名称 on 表名(列名)
        - drop unique index 索引名称 on 表名
    
    组合索引(最左前缀匹配):
        - create  index 索引名称 on 表名(列名,列名)
        - drop    index 索引名称 on 表名
        
        - create index ix_name_email on userinfo3(name,email,)
        - 最左前缀匹配
                select  * from userinfo3 where name='Tom';
                select  * from userinfo3 where name='Tom' and email='asdf';
                
                select  * from userinfo3 where email='Tom@qq.com';
            
        组合索引效率 > 索引合并 
            组合索引
                - (name,email,)
                    select  * from userinfo3 where name='Tom' and email='asdf';
                    select  * from userinfo3 where name='Tom';
            索引合并:
                - name
                - email
                    select  * from userinfo3 where name='Tom' and email='asdf';
                    select  * from userinfo3 where name='Tom';
                    select  * from userinfo3 where email='Tom';
    
    名词:
        覆盖索引:
            - 在索引文件中直接获取数据
        
        索引合并:
            - 把多个单列索引合并使用

    三. 正确使用索引

    数据库表中添加索引后确实会让查询速度起飞,但前提必须是正确的使用索引来查询,如果以错误的方式使用,则即使建立索引也会不奏效。
    即使建立索引,索引也不会生效:

    #--- id,email 是创建的索引
                
        - like '%xx'
            select * from tb1 where email like '%cn';
            
            
        - 使用函数
            select * from tb1 where reverse(email) = 'Tom';
            
            
        - or
            select * from tb1 where nid = 1 or name = 'seven@live.com';  # name不是 索引字段,无法命中
            
            
            特别的:当or条件中有未建立索引的列才失效,以下会走索引
    
                    select * from tb1 where id = 1 or name = 'seven@live.com' and email = 'Tom'   #会忽略 name
                    
                    
        - 类型不一致
            如果列是字符串类型,传入条件是必须用引号引起来,不然...
            select * from tb1 where email = 999;
            
            
        - !=
            select * from tb1 where email != 'Tom'
            
            特别的:如果是主键,则还是会走索引
                select * from tb1 where nid != 123
        - >
            select * from tb1 where email > 'Tom'
            
            
            特别的:如果是主键或索引是整数类型,则还是会走索引
                select * from tb1 where nid > 123
                select * from tb1 where num > 123
                
                
        - order by
            select name from tb1 order by email desc;
            
            当根据索引排序时候,选择的映射如果不是索引,则不走索引
            特别的:如果对主键排序,则还是走索引:
                select * from tb1 order by nid desc;
         
        - 组合索引最左前缀
            如果组合索引为:(name,email)
            name and email       -- 使用索引
            name                 -- 使用索引
            email                -- 不使用索引

     四.其他注意事项

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

    五. limit分页

    - 索引表中扫:(依然不快)
            select * from userinfo3 where id in(select id from userinfo3 limit 200000,10)
    
    #-- 方案:
            记录当前页最大或最小ID
            1. 页面只有上一页,下一页
                # max_id
                # min_id
                下一页:
                    select * from userinfo3 where id > max_id limit 10;
                上一页:
                    select * from userinfo3 where id < min_id order by id desc limit 10;
            2. 上一页 192 193  [196]  197  198  199 下一页
                               当前             要到
                select * from userinfo3 where id in (
                    select id from (select id from userinfo3 where id > max_id limit 30) as N order by N.id desc 
    limit 10 )

    六. 执行计划

    explain + 查询SQL - 让mysql预估执行操作(一般正确)

    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)
    all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
        #-- id,email 是索引
        
        慢:
            select * from userinfo3 where name='Tom'
            
            explain select * from userinfo3 where name='Tom'
            type: ALL(全表扫描)
                select * from userinfo3 limit 1; (依然快--因为特殊情况)
        快:
            select * from userinfo3 where email='Tom'
            type: const(走索引)
        
    介绍
  • 相关阅读:
    如何给swing加上alt+x和ctrl+x快捷键
    java基础之登录程序
    RFID UHF(EPC)标签使用常识
    史密斯圆图
    C# DataTable Operations
    温度测量【RTD】
    温度测量【温度传感器类型】
    C# Debug
    c# ComboBox绑定枚举
    c# 隐藏Tab控件的标签
  • 原文地址:https://www.cnblogs.com/zhaochangbo/p/6993455.html
Copyright © 2020-2023  润新知