MySQL

MySQL索引

2019-02-25  本文已影响5人  慧鑫coming

索引的常见模型

索引的实现

InnoDB索引模型

相关概念

普通索引、唯一索引

数据更新,change buffer

基于change buffer和索引,说说InnoDB引擎的表,在表中插入新记录时的处理流程?

change buffer使用场景

change buffer、redo log

给字符串类型添加索引

    select
       count(distinct left(email,4)) as L4,
       count(distinct left(email,5)) as L5,
       count(distinct left(email,6)) as L6,
       count(distinct left(email,7)) as L7
    from t;

函数的对索引的影响

常见破坏索引树搜索的操作

    -- 前提,表t,created_at datetime default null,index
    -- bad case对索引字段做函数操作,破坏了索引的有序性,会放弃树搜索功能,遍历索引树created_at。
    select count(*) from t where month(created_at)=7;  
    -- 修正,使查询仍走created_at树搜索
    select count(*) from t where
      (created_at >= '2016-7-1' and created_at < '2016-8-1') or
      (created_at >= '2017-7-1' and created_at < '2017-8-1'); 
    -- 前提,表t,phone varchar(12) default null,index
    -- bad case 使用整型条件而非字符串,优化器做了隐式类型转换,也就是对索引字段进行了函数操作。
    select * from t where phone=123456;  
    -- 对优化器来说相当于执行
    select * from t where CAST(phone AS signed int) = 123456;
    -- 修正,使用正确的类型作为条件
    select * from t where phone='123456';

    -- CAST函数加载输入参数上,不会破坏索引
    select * from t where id='99';
  -- bad case
  select a.* from A as a,B as b where a.phone=b.phone and a.id=2;
  -- 这里表A是驱动表,表B是被驱动表,phone是关联字段,执行流程如下:
  -- 1、根据id从表A找到 L2 这一行。
  -- 2、从 L2 中取出phone字段。
  -- 3、根据取出的phone字段去表B中查找匹配条件的行。
  -- 当执行到第三步时,单独改成SQL如下,问题出现了。
  select * from B where phone=$L2.phone.value;
  -- 上面这句SQL中条件的编码是utf8mb4,而表B字符集编码是utf8,需要函数转化,等同于: 
  select * from B where CONVERT(phone USING utf8mb4)=$L2.phone.value;
  -- 同样地,对索引字段做函数操作,优化器放弃走树搜索功能。
  
  -- 如果反过来,表A作为被驱动表,不会对索引造成破坏
  select a.* from A a,B b where a.phone=b.phone and a.id=2;
  -- 此时执行流程步骤3相当于
  select * from a where phone=CONVERT($R2.phone.value USING utf8mb4);
  -- 可见,函数是加在输入参数上的,所以可以用上被驱动表的索引。

  -- 对bad case的修正
  -- 1、将表B的phone字段改为utf8mb4编码,表大的话不推荐使用
  alter table B modify phone varchar(12) CHARACTER SET utf8mb4 default null;
  -- 2、主动将a.phone转化为utf8编码,避免被驱动表上的字符串编码转换
  select a.* from A as a, B as b where b.phone=CONVERT(a.phone USING utf8) and a.id=2;
上一篇 下一篇

猜你喜欢

热点阅读