B树与索引

目录

一, 索引与B树介绍

1. B树 ,B+树 ,B*树

2. 聚集索引

3. 辅助索引

3.1 普通辅助索引
3.2 覆盖辅助索引

4. 唯一索引

二. 索引管理命令

1. 索引的增删查(重点*******)

2. 查看执行计划explain(desc)

三. 不走索引的情况(开发规范, 重点*******)

四. 建立索引的原则(运维规范)

=======================================================================.
建索引与不建索引, 在数据量50w条时, 性能差距近1w倍, 亲测
https://www.jianshu.com/p/7939a78e9088
=======================================================================

一, 索引与B树介绍

1. B树 ,B+树 ,B*树:

如图(蓝色部分先不看):

第一排为根节点, 蓝色部分存的是下面一个子节点存储的最小值, 黄色为对应子节点的指针

第二排为子节点(可能有多个子节点), 蓝色部分存的是下面数据页存储的最小值, 黄色为对应数据页的指针

第三排为数据页存的是正正的数据,

每一个框规定存的大小为16K, 索引存的数据越多, 子节点就越多, 树就越高. 对应的性能就会变差

举例: 查找数字 63

1\. 在根节点找, 63在28-65之间, 进入p2节点
2\. 63比56大,进入p3数据页
3\. 找到63

这就是B树(把图中蓝色部分不看就是)

如果要查找大于63的数字怎么办? 在每个数据页中存入旁边的指针, 这样就可以在数据页上直接跳转了, 这就是B+树

在子节点存旁边的指针叫B*

2. 聚集索引:

基于主键,自动生成的,一般是建表时创建主键.如果没有主键,自动选择唯一键做为聚集索引

在图中, 将数字改为表的主键的值, 根节点与子节点只存主键的值, 数据页上存主键的值与对应的一条记录

根据主键查询的时候效率会大大提高

如果业务中很少根据主键 , 而是根据其他字段查的最多呢, 例如name?

这就需要用到辅助索引了

3. 辅助索引:

人为创建的(普通,覆盖)

3.1 普通辅助索引:

​ 将表的某个字段设为索引, 图中的数字就替换为这个字段的值, 数据页中存的是这个字段的值与对应的主键, 根据这个字段的某个值, 找到对应的主键, 再去聚集索引拿到数据(这一步叫回表)

​ 例如根据name字段找到一条数据, 就可以将name字段设为辅助索引

​ 如果数据页中除了主键还存了其他值呢, 那就不需要再去回表了, 这就是覆盖辅助索引了

3.2 覆盖辅助索引:

​ 如果需要根据name字段拿到phone与sex的值, 可以将sex, phone一并存到数据页中, 这样就不用回表了

4. 唯一索引:

人为创建(普通索引,聚集索引)

二. 索引管理命令

1. 索引键(key),表中的某个列

1. 辅助索引(BTREE)
    怎么生成的:
        根据创建索引时,指定的列的值,进行排序后,存储的叶子节点中
    好处:
        1.优化了查询,减少cpu mem IO消耗
        2.减少的文件排序

    创建普通辅助索引(MUL)
        # 给表blog_userinfo的email字段添加索引
        alter table blog_userinfo add key idx_email(email);
        # 给表blog_userinfo的phone字段添加索引
        create index idx_phone on blog_userinfo(phone);
    查看索引
        desc blog_userinfo;
        show index from blog_userinfo;
    删除索引
        alter table blog_userinfo drop index idx_email;
        drop index idx_phone on   blog_userinfo;

2. 前缀索引: 
    有时候需要用很长的字符串作为索引, 这会让索引变得大且慢, 通常可以索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率。
    # 查看password字段的前20个字符是否重复
    select count(*),substring(password,1,20) as sbp  from blog_userinfo group by sbp;
    # 将password前10个字符设为索引
    alter table blog_userinfo add index idx(password(10));

3. 唯一键索引(UNI,如果有重复值是创建不了的)
    alter table blog_userinfo add unique key uni_email(email);

4. 覆盖索引(联合索引)
    作用:不需要回表查询,不需要聚集索引,所有查询的数据都从辅助索引中获取
    alter table t1 add index idx_gam(gender,age,money);
    当where   gender age money 这三个条件时, 效率就会变得很高
    注意, 设索引时的字段顺序与where条件的字段顺序, 最好一样, 
        第一个条件不一样就不走索引
        第二个条件不一样效率就会降低
    好处:
        减少回表查询的几率

2. 查看执行计划explain(desc)

在需要执行的select语句前面加上 explain 或者 desc

返回的结果字段分析

type字段: 索引类型
    值(性能从上往下为越来越高):
        ALL:全表扫描
            例如: select  *  from  t1;
        Index:全索引扫描
            例如: select 索引字段 from city ;
        range:索引范围扫描
            例如: 在where中用了 >  <  >=  <=  in or  between and like 'CH%'
        ref:辅助索引的等值查询
            select * from city where 辅助索引字段='XXX'
        eq_ref: 多表链接查询(join on )

        const ,system :主键或唯一键等值查询

Extra字段:额外信息
    using filesort: 文件排序
    将order by , group by , distinct 后的列和where条件列建立联合索引
        注意, 必须将where条件里的字段放在前面

possible_keys: 可能会走的索引

key: 真正走的索引

三. 不走索引的情况(开发规范)

1. 重点关注

  1. 没有查询条件,或者查询条件没有建立索引

    select * from tab;   全表扫描。
    select  * from tab where 1=1;
    改为:
    select  * from tab where id=1;
    
    
  2. 查询结果集是原表中的大部分数据

    查询的结果集,超过了总数行数25%,优化器觉得就没有必要走索引了。

    假如: tab表有数据100w条, id有索引,要查后50w条, 
     select * from tab  where id>500000;
    改为:
        select * from city where id > 500000 and id < 600000
        union all 
        select * from city where id >= 600000 and id < 700000
        union all 
        select * from city where id >= 700000 and id < 700000
         ...;
    
    
  3. 索引本身失效,统计数据不真实

    索引有自我维护的能力。
    对于表内容变化比较频繁的情况下,有可能会出现索引失效。

  4. 查询条件使用函数在索引列上,或者对索引列进行运算,运算包括(+,-,*,/,! 等), 子查询

    错误的例子:select * from test where id-1=9; 
    正确的例子:select * from test where id=10;
    
    
  5. 隐式转换

导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误.

t1表的telnum字段为char类型
错误的例子: select * from t1 where telnum=110;
改正: select * from t1 where telnum='110';

原因, 用数字110去查,其实使用了函数将数字转为字符串

  1. <> ,not in , !=不走索引, like "%_" 百分号在最前面不走索引

  2. 单独引用联合索引里非第一位置的索引列.作为条件查询时不走索引.

四. 建立索引的原则(运维规范)

  1. 选择唯一性索引
  2. 经常需要排序、分组和联合操作的字段建立联合索引
  3. 为常作为where查询条件的字段建立索引
  4. 尽量使用前缀来索引
  5. 限制索引的数目, 尽量的少
  6. 索引维护要避开业务繁忙期
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容