zoukankan      html  css  js  c++  java
  • Python全栈之路-MySQL(六)

    1 索引:

    1.1 索引类型

    • 普通索引 特性:加速查找
    • 主键索引 特性:加速查找 + 不能为空 + 不能重复
    • 唯一索引 特性:加速查找 + 不能重复
    • 联合索引 特性:加速查找
      • 联合普通索引
      • 联合主键索引
      • 联合唯一索引
    • 全文索引:会借助第三方工具做

    索引存储种类(某种格式存储):

    • hash索引:存储的顺序和数据表不一致,找单值速度快
    • btree索引(mysql常用索引):一般用于数据库的索引综合效率较高

    1.2 索引操作

    创建普通索引:

    create index index_email on user(email);
    

    删除普通索引:

    drop index index_email on user;
    

    创建唯一索引:

    create unique index index_name on user(name);
    

    删除唯一索引:

    drop index index_name on user;
    

    创建联合索引:

    create index index_email_name on user(email,name);
    

    注:联合索引遵循最左前缀匹配原则

    select * from user where email='abc123431@qq.com'; -- 走索引
    select * from user where email='abc123431@qq.com' and name='alex3423'; -- 走索引
    select * from user where name='alex3423' and email='abc123431@qq.com'; -- 不走索引
    select * from user where name='alex3423'; -- 不走索引
    注意:联合索引效率 > 索引合并
    

    删除联合索引:

    drop index index_email_name on user;
    

    有索引和无索引的区别:

    无索引:从前到后依次查找
    有索引:创建额外文件(某种格式存储),会占用磁盘空间
    

    1.3 索引补充

    建立索引:

    • 额外的文件保存特殊的数据结构
    • 查询快,插入更新删除慢
    • 命中索引

    索引名词补充

    • 覆盖索引 在索引文件中直接获取数据
      select * from user where email='alex3423@qq.com';
    • 索引合并 把多个单列索引合并使用
      select * from user where email='abc123431@qq.com' and id =123432;

    1.4 命中索引

    只有满足下面两点索引才能加速查询(假设nid和email是索引列)
    - 创建索引
    - 命中索引

    以下几种情况不能命中索引:

    • like '%xx'
      select * from tb1 where name like '%cn';

    • 使用函数
      select * from tb1 where reverse(name) = 'wupeiqi';

    • or
      select * from tb1 where nid = 1 or name = 'seven@live.com';
      特别的:当or条件中有未建立索引的列才失效,以下会走索引
      select * from tb1 where nid = 1 or email = 'seven';
      select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'

    • 类型不一致
      如果列是字符串类型,传入条件是必须用引号引起来,不然...
      select * from tb1 where email = 999;

    • !=
      select * from tb1 where email != 'abc123431@qq.com'
      特别的:如果是主键,则还是会走索引
      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 name from tb1 order by email desc; -- 根据哪一列order by就取select哪一列的值
      当根据索引排序时候,选择的映射如果不是索引,则不走索引
      特别的:如果对主键排序,则还是走索引:
      select * from tb1 order by nid desc;

    • 组合索引最左前缀
      如果组合索引为:(name,email)
      name and email -- 使用索引
      name -- 使用索引
      email -- 不使用索引

    其他注意事项:

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

    1.5 执行计划

    查询时的访问方式,性能: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  可能使用的索引
    

    1.6 慢查询日志配置

    • 执行时间大于1s(自定义)的
    • 执行语句未走索引的

    global变量在线配置,立即生效

    修改配置文件重启MySQL生效

    1.7 分页实战

    select * from user limit 200000,10;

    当起始位置越大时,查询效率越低

    实战:提高博客中的页码翻页查询效率
    解决方案:

        - 不让看
        - 索引表中扫(效率提升不是很大)
            select * from user where id in (select id from user limit 200000,10);
    
        - 记录当前页的起始id和结束id
            max_id 当前页最大id
            min_id 当前页最小id
            每页显示10条数据
            情况1:页面只有上一页下一页
            select * from user where id > max_id limit 10;
            select * from user where id < max_id order by id desc limit 10;
            情况2:用户进行翻页时可跳转几页
            例如,用户跳转了3页向后翻页
            select * from user where id 
            in (select id from user where id > max_id limit 30) as N order by N.id desc limit 10 order by N.id asc;
            例如,用户跳转了3页向前翻页
            select * from user where id 
            in (select id from user where id < min_id order by id desc limit 30) as N order by N.id desc limit 10 order by N.id asc;
    
        
        ps:id不连续,所以无法直接使用id范围进行查找
    
  • 相关阅读:
    iOS之蓝牙开发—CoreBluetooth详解
    iOS-GCD使用详解
    iOS—Mask属性的使用
    idea导入eclipse中的maven项目
    SQL Server 查找字符串中指定字符出现的次数
    lLinux的常用命令
    从excel表中生成批量SQL
    ORA-00911: invalid character 错误解决
    sqlserver sp_who2和inputbuffer的使用,连接数
    如果存在这个表,则删除这个表的sql
  • 原文地址:https://www.cnblogs.com/wanyuetian/p/7008376.html
Copyright © 2011-2022 走看看