美文网首页
索引优化笔记!

索引优化笔记!

作者: DragonersLi | 来源:发表于2021-03-15 13:39 被阅读0次

    索引可以理解为书的目录。方便快速查询。索引不是万能的,在有些情况下使用索引反而会让效率变低。比如占用存储空间、降低数据库写操作的性能、多个索引增加索引选择的时间

    功能逻辑区分:普通索引唯一索引主键索引全文索引

    普通索引:基础的索引,没有任何约束,主要用于提高查询效率。
    唯一索引:在普通索引的基础上增加了数据唯一性的约束。
    主键索引:在唯一索引的基础上增加了不为空的约束,也就是 NOT NULL+UNIQUE
    全文索引:MySQL 自带的全文索引只支持英文。我们通常可以采用专门的全文搜索引擎
    
    其实前三种索引(普通索引、唯一索引和主键索引)都是一类索引,只不过对数据的约束性逐渐提升。
    在一张数据表中只能有一个主键索引,这是由主键索引的物理实现方式决定的,
    因为数据存储在文件中只能按照一种顺序进行存储。但可以有多个普通索引或者多个唯一索引。
    

    物理实现区分:聚集索引非聚集索引(二级索引或者辅助索引)

    聚集索引的叶子节点存储的就是我们的数据记录,非聚集索引的叶子节点存储的是数据位置。非聚集索引不会影响数据表的物理存储顺序。
    一个表只能有一个聚集索引,因为只能有一种排序存储的方式,但可以有多个非聚集索引,也就是多个索引目录提供数据检索。
    使用聚集索引的时候,数据的查询效率高,但如果对数据进行插入,删除,更新等操作,效率会比非聚集索引低。
    

    字段个数进行划分:单一索引联合索引
    ①数据量少使用索引反而执行更耗时。
    ②比如性别字段,取值少通常是不需要创建索引的。

     show profiles; #查看sql执行的query_id和持续时间(单位:毫秒)
    
    show profile for query 2; #根据sql查询的query_id
    
     set profiling=1; #开启profile
    show variables like "%profiling%";
    show processlist;
    

    组合索引有效性:show index from table from database查看database库中table表的所有索引
    用户表user有字段ABC,创建了普通组合索引 uni_a_b_c 根据最左匹配原则,只有先确定了前一个(左侧的值)后,才能确定下一个值。所有以A开头的where条件sql都能使用到该索引。但根据如下所有情况的组合表格测试发现,包含A非A开头的sql也能使用到索引。这就是mysql的优化器的效果。最终不包含A的使用不到该组合索引,非A开头的AC使用不到索引!
    in 和 = 都可以乱序,mysql优化器会调整顺序;当遇到范围查询(>、<、between、like)会停止匹配
    ①如果创建了组合索引ABC,那还有必要单独创建A的索引么?根据explain sql语句发现,possible_keys可能用到的索引有ABC,A。但key实际用到的索引是ABC。也就是说没必要再单独创建了。
    ②如果组合索引ABC和另一个字段的索引D在一条sql中使用到。是怎样的呢?根据测试发现, 索引约束强则优先级高。

    A开头(name B开头(email C开头(mobile
    A B(× C(×
    AB BA CA(
    AC( BC(× CB(×
    ABC BAC CAB
    ACB BCA CBA

    创建索引有哪些规律?

    
    字段的数值有唯一性的限制
    频繁作为 WHERE 查询条件的字段(包括select、update、delete的where)
    需要经常 GROUP BY 和 ORDER BY 的列(若创建组合索引group字段要在order字段前,否则失效)
    DISTINCT 去重字段需要创建索引
    做多表 JOIN 连接操作时,创建索引需要注意以下的原则:
        连接表的数量尽量不要超过 3 张,因为每增加一张表就相当于增加了一次嵌套的循环,数量级增长会非常快,严重影响查询的效率
        对用于连接的字段 和 WHERE 条件创建索引,连接字段类型要保持一致
    

    什么时候不需要创建索引?

    WHERE 条件(包括 GROUP BY、ORDER BY)里用不到的字段不需要创建索引
    表记录太少,索引反而加大开销
    字段中如果有大量重复数据,也不用创建索引
    频繁更新的字段不一定要创建索引。因为更新数据的时候,也需要更新索引,如果索引太多,在更新索引的时候也会造成负担,从而影响效率。
    

    什么情况下索引失效?

    ①如果对索引使用函数或表达式计算,则会失效。
    `WHERE id+1 = 101`改成`WHERE id = 100`
    `WHERE SUBSTRING(name, 1,3)='abc'`改成`WHERE name LIKE 'abc%'
    
    ②在 WHERE 子句中,如果在 OR 前的条件列进行了索引,而在 OR 后的条件列没有进行索引,那么索引会失效。
    
    ③当我们使用 LIKE 进行模糊查询的时候,后面不能是 %
    `where like '%xxx%' # 左边有%不走索引
    `where >= a and <= b`改成`where between and`
    
    ④索引列与 NULL 或者 NOT NULL 进行判断的时候也会失效。
    索引并不存储空值,所以最好在设计数据表的时候就将字段设置为 NOT NULL 约束
    

    理想索引设计:三星索引 最小化碎片、避免排序、避免回表查询
    三星索引会让索引变宽,好处就是不需要进行回表查询,减少了磁盘 I/O 的次数,弊端就是会造成频繁的页分裂和页合并,对于数据的插入和更新来说,效率会降低不少。

    在 WHERE 条件语句中,找到所有等值谓词中的条件列,将它们作为索引片中的开始列;
    将 GROUP BY 和 ORDER BY 中的列加入到索引中;
    将 SELECT 字段中剩余的列加入到索引片中。
    
    回表就是通过索引找到了数据行,但是还需要通过主键的方式在数据表中查找完成的记录。
    这是因为 SELECT 所需的字段并不都保存在索引中,
    因此我们可以将 SELECT 中的字段都保存在索引中避免回表的情况,从而提升查询效率。
    
    索引概览 索引的使用原则
    索引的数据结构
    Hash索引
    理想索引
    mysql通配符:_表示一个字符,%表示一个或多个字符! 通配符不出现开头可走索引,出现在开头则不走索引,走全表扫描。
    例如要模糊查询一个脱敏的用户信息:己方存的是未脱敏数据,对方提供查询的数据是脱敏数据,这时简单做法是,己方该表新建查询字段的冗余字段,存脱敏冗余数据。这样就可以直接根据对方提供的脱敏数据直接查
    脱敏数据:
    name: 李**
    mobile: 188****8888
    idcard: 3412************3411
    
    通配符匹配:
    name: 李__  或 李%
    mobile: 188____8888 或 188%8888
    idcard: 3412__________3411 或 3412%3411
    
    优化之前写法
    select * from users
     where  name like '李%' 
    and mobile like '188%' 
    and idcard like '3412%' 
    and mobile like '%8888' 
    and idcard like '%3411';
    
    
    利用通配符_%优化sql语句,使之能尽量走索引提升查询效率。
    
    
    select * from users
     where  name like '李%'
    and mobile like '188%8888'
    and idcard like '3412%3411';
    
    select * from users
     where  name like '李__'
    and mobile like '188____8888'
    and idcard like '3412__________3411';
    

    数据库查询脱敏数据时,可以考虑建冗余字段存脱敏数据。不使用like而是=。例如像查手机号188****8888,数据库存的是18888888888,多存一个冗余字段188****8888

    相关文章

      网友评论

          本文标题:索引优化笔记!

          本文链接:https://www.haomeiwen.com/subject/scuayxtx.html