B-Tree

  1. 核心特点:

    1. 多路,非二叉树
    2. 每个节点既保存索引,又保存数据
    3. 搜索时相当于二分查找

B+Tree

  1. 核心特点

    1. 多路非二叉
    2. 只有叶子节点保存数据
    3. 搜索时相当于二分查找
    4. 增加了相邻接点的指向指针。

B-Tree VS B+Tree

  1. B+树查询时间复杂度固定是log n,B-树查询复杂度最好是 O(1)。
  2. B+树相邻接点的指针可以大大增加区间访问性,可使用在范围查询等,而B-树每个节点 key 和 data 在一起,则无法区间查找。
  3. B+树更适合外部存储,也就是磁盘存储。由于中间节点无data 域,每个节点能索引的范围更大更精确。

MySQL InnoDB

数据存储:

  1. 数据结构按照B+树存储,本身就是索引,又叫聚簇索引
  2. key为主键
  3. InnoDB要求表必须要有主键
  4. 若未显示指定,则自动选择唯一标识记录列为主键,若不存在则自动创建

普通索引:

  1. 叶子节点存放的主键,而不是行的物理地址
  2. 需要两次检索,(1)检索主键(2)根据主键检索数据
  3. 存主键好处:页分裂或数据移动时不需要变动
  4. 主键要设计的尽可能小,原因:每个索引都会存,过大浪费空间
  5. 主键最好有序,减少索引维护开销

MySQL InnoDB页大小:

SHOW VARIABLES LIKE 'innodb_page_size';

查找关键字=8的数据:

  1. 根页在表空间中位置固定。
  2. 根页装入内存,查找到指针P6
  3. P6指向的页装入内存
  4. 二分查找找到8

InnoDB中高度为3的B+树存放:

  1. 假设数据表中一行数据为1K。
  2. 假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,这样一共1占用14字节。
  3. 一个页中存放指针数目(索引个数):
  4. 16KB(16*1024=16384 byte)16384/14=1170
  5. 高度为2的B+树,能存放1170*16=18720条数据记录。
  6. 高度为3的B+树,能存放:
  7. 1170(索引个数)*1170(索引个数)*16(每页行数)=21902400(2千万)条这样的记录

高性能索引策略:

  1. 独立的列

    1. 索引列不能是表达式的一部分,也不能是函数的参数。
    2. 如:select x ,y,z from table where x+1 = 2;
    3. 假如x是索引,那上述sql无法利用索引,应写成:select x ,y,z from table where x = 1;
  2. 索引选择性:不重复的索引个数(X,X<=T)和数据表的记录总数(T)的比值,范围在 X/T 到 1 之间。索引的选择性越高则查询效率越高。唯一索引的X=T,其选择性为1,所以唯一索引的性能最好。
  3. 前缀索引
    1. 对于TEXT或是VARCHAR类型的列,当这个列中的值长度很大又必须利用其进行查询时,就必须使用这个列的前几位值以作索引,即前缀索引,因为整个列的值当做索引时B+tree会占用非常大的空间,查找也不方便。
    2. 前缀索引的制定原则:前缀索引的选择性需要和整个列的选择性接近,这样性能不会影响太多,同时还不能太长而占用太多空间。
    3. 如何寻找最佳前缀索引?
      1. 假设:有一个表中的某一列,名为testcol,类型为varchar(100)
      2. 计算完整列的选择性: SELECT COUNT(DISTINCT testcol) / COUNT( * ) FROM table;
      3. 计算前缀长度为x的选择性:SELECT COUNT(DISTINCT LEFT( testcol, x )) / COUNT( * ) FROM table;
      4. 改变x的值来计算不同前缀的选择性,最后在多个值中,综合考虑选择性接近性和前缀长度的两个方面,可以选出一个较为合适的前缀索引。
  4. 多列索引
    1. select x,y,z from table where x=1 and y=1;
    2. 在Mysql执行查询时,如果是使用多列索引key(x,y),则会先查询符合第一列索引的数据集,然后再在这一部分数据集中查询出符合第二列的数据,以此类推,这样在不用扫描数据的情况下就能选出数据;
    3. 而如果一个多列索引拆分成多个单列索引(key(x),key(y))的话,Mysql在执行查询时,只会从中选出一个限制最严格的索引以供使用,其他的索引就浪费了,所以在上述情况中多列索引性能要好。
  5. 索引顺序
    1. select x,y,z from table where x=1 and y=1;
    2. x=1 and y = 1 还是 y=1 and x=1?
    3. 将选择性高的索引列放在前面;索引列按照选择性从高到低放置
  6. 覆盖索引
    1. 如果一个索引包含了所有需要查询的字段的值,就称之为“覆盖索引”
    2. InnoDB存储引擎使用聚簇索引,覆盖索引可避免回表查询。因为InnoDB的二级索引的B-Tree的叶结点存储的是对应的一级索引,所以如果二级索引覆盖了所要查询的值则会少一次利用一级索引查询,提升效率。
    3. 当发起一个索引覆盖查询时,在执行计划的Extra列中可见“Using index”的信息。
  7. 索引冗余
    1. 当存在key (a, b)索引时,如果再创建一个key (a)就是多余的,因为它只是多列索引的前缀而已。
    2. 但是当创建key (b)时,就不属于冗余索引了,因为上述的多列索引是无法单独使用b作索引查询
  8. 索引相关问题
    1. 索引越多越好? 数据更新时需要维护索引,带来开销,按需创建。
    2. **哪些列适合建索引?**选择性较高的列,一些常量和枚举的字段(如:性别)不适合建索引,选择性较低还增加维护成本,得不偿失。
    3. **索引字段类型?**自增字段,表比较大时,uuid等没有规律的字段不太适合作为主键

MySQL执行计划

  1. select_type

    id select_type description
    1 SIMPLE 不包含任何子查询或union等查询
    2 PRIMARY 包含子查询最外层查询就显示为 PRIMARY
    3 SUBQUERY 在select或 where字句中包含的查询
    4 DERIVED from字句中包含的查询
    5 UNION 出现在union后的查询语句中
    6 UNION RESULT 从UNION中获取结果集
  2. type

    type description
    ALL 扫描全表数据,不走索引
    index 遍历索引,需扫描索引的全部数据,如:select count(*) from tableA
    range 索引范围查找
    index_merge 索引合并,多个单列索引,如and条件,or条件
    index_subquery 在子查询中使用 ref
    unique_subquery 在子查询中使用 eq_ref
    ref_or_null 对Null进行索引的优化的 ref
    fulltext 使用全文索引,分词搜索
    ref 使用非唯一索引查找数据,类似eq_ref,区别是索引非唯一
    eq_ref 在join查询中使用PRIMARY KEY or UNIQUE NOT NULL索引关联。
    const 使用主键或者唯一索引,且匹配的结果只有一条记录。
    system const 连接类型的特例,查询的表为系统表,往往不需要进行磁盘IO。
  3. possible_keys: 可能使用的索引,注意不一定会使用。查询涉及到的字段上若存在索引,则该索引将被列出来。当该列为 NULL时就要考虑当前的SQL是否需要优化了。

  4. key

    1. 显示MySQL在查询中实际使用的索引,若没有使用索引,显示为NULL。
    2. TIPS: 查询中若使用了覆盖索引(覆盖索引:索引的数据覆盖了需要查询的所有数据),则该索引仅出现在key列表中。
    3. select_type为index_merge时,这里可能出现两个以上的索引,其他的select_type这里只会出现一个
  5. key_length:索引字段长度

    1. char()、varchar()索引长度的计算公式:

      (Character Set:utf8mb4=4,utf8=3,gbk=2,latin1=1) * 列长度 + 1(允许null) + 2(变长列)

    2. int索引长度的计算公式:4+ 1(允许null)

  6. extra: extra的信息非常丰富,常见的有:

    1. Using index 使用覆盖索引
    2. Using where 使用了用where子句来过滤结果集
    3. Using filesort 使用文件排序,使用非索引列进行排序时出现,非常消耗性能,尽量优化。
    4. Using temporary 使用了临时表。

sql优化建议

  1. SQL语句不要写的太复杂:一个SQL语句要尽量简单,不要嵌套太多层。
  2. 使用『临时表』缓存中间结果:简化SQL语句的重要方法就是采用临时表暂存中间结果,这样可以避免程序中多次扫描主表,也大大减少了阻塞,提高了并发性能。
  3. 使用like的时候要注意是否会导致全表扫描:有的时候会需要进行一些模糊查询比如select id from table where username like ‘%abc%’。关键词%abc%,由于abc前面用到了“%”,因此该查询会使用全表扫描,除非必要,否则不要在关键词前加%,
  4. 尽量避免使用 not in,!=或<>操作符:在where语句中使用not in,!=或<>,引擎将放弃使用索引而进行全表扫描。
  5. 尽量避免使用 or 来连接条件:
    1. 用 or 分割开的条件, 如果 or 前的条件中的列有索引, 而后面的列中没有索
      引, 那么涉及到的索引都不会被用到。
    2. 应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如: 假设num1有索引,num2没有索引,查询语句select id from t where num1=10 or num2=20会放弃使用索引,可以改为这样查询: select id from t where num1=10 union all select id from t where num2=20,这样虽然num2没有使用索引,但至少num1会使用索引,提高效率
  6. 尽量使用数字型字段:若只含数值信息的字段尽量不要设计为字符型,这会降低查询和连接的性能,并会增加存储开销。
  7. 尽量不要让字段的默认值为NULL:
    1. 在MySQL中,含有空值的列很难进行查询优化,因为它们使得索引、索引的统计信息以及比较运算更加复杂。
    2. 索引不会包含有NULL值的列,只要列中包含有NULL值都将不会被包含在索引中,复合索引中只
      要有一列含有NULL值,那么这一列对于此复合索引就是无效的。
    3. 所以我们在数据库设计时尽量不要让字段的默认值为NULL,应该指定列为NOT NULL,除非你想存储NULL。你应该用0、一个特殊的值或者一个空串代替空值。
  8. 如果列类型是字符串,那么一定记得在 where 条件中把字符常量值用引号引起来,否则的话即便这个列上有索引,MySQL 也不会用到的,因为MySQL 默认把输入的常量值进行转换以后才进行检索。如:select * from t_student where std_name = 3;
  9. 慎用insert into select。
    1. 语句:insert into tableA select * from tableB where date_time > ‘2020- 07-31’
    2. 问题分析:该语句会导致tableB逐步被锁定,其他操作无法进行的问题。
    3. 解决方案:data_time字段添加索引
  10. 索引null值问题
    1. 唯一索引null值

      1. 唯一索引中允许存在多行值为NULL的数据存在
      2. 联合唯一索引中存在null值,将丢失唯一性,如unique key(email,phone),若phone为空将导致email相同的多条记录存在
      3. 对 NULL 值的检索只能使用 is null / is not null / <=>,不能使用=,<,>这样的运算符
    2. 普通索引null值:null值存在仍然可以走索引

MySql索引分析及查询优化相关推荐

  1. MySQL索引分析扩展理解

    MySQL索引分析扩展理解 看了很多网上的一些资料,感觉MySQL的索引知识还是很多的,这一篇文章就用来自己对MySQL索引的其他理解和以前模糊的地方的一些总结. 1.MySQL的常见索引模型 有序数 ...

  2. MySQL索引分析和优化(转)

    MySQL索引分析和优化(转) 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记 录,直至找到符 ...

  3. MySQL 索引分析除了 EXPLAIN 还有什么方法?

    作者 | adrninistrat0r 责编 | 夕颜 出品 | CSDN(ID:CSDNnews) 前言 对于非数据库开发人员而言,难以对MySQL源码进行分析或调试,接近一个黑盒,但MySQL提供 ...

  4. php mysql索引原理_加速PHP动态网站 关于MySQL索引分析优化

    本文主要讲述了如何加速动态网站的MySQL索引分析和优化. 一.什么是索引? 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第 ...

  5. mysql索引原理及查询优化

    一.介绍 1.什么是索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语 ...

  6. mysql索引原理与查询优化

    阅读目录 一 介绍 二 索引的原理 三 索引的数据结构 四 聚集索引与辅助索引 五 MySQL索引管理 六 测试索引 七 正确使用索引 八 联合索引与覆盖索引 九 查询优化神器-explain 十 慢 ...

  7. Mysql索引优化与查询优化

    索引优化与查询优化 都有哪些维度可以进行数据库调优?简言之: 索引失效.没有充分利用到索引--索引建立 关联查询太多JOIN (设计缺陷或不得已的需求)--SQL优化 服务器调优及各个参数设置(缓冲. ...

  8. mysql索引分析_MySQL索引分析和优化

    什么是索引? 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面 ...

  9. mysql索引分析和优化_MySQL索引分析和优化

    什么是索引? 索 引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的 所有记录,直至找到符合要求的记录.表 ...

最新文章

  1. 六 Lync Server 2013 部署指南-OWA服务器部署
  2. Java虚拟机学习(7):对象内存分配与回收
  3. [pasecactf_2019]tornado_casino
  4. mysql online ddl和pt_online ddl与pt-osc详解
  5. scala中使用特质中的抽象字段和实际字段
  6. linkedin爬虫_重新设计Linkedin的指导功能-用户体验案例研究
  7. 正则表达式之 贪婪与非贪婪模式详解
  8. electron-vue解决打包错误、无法调用出开发者工具(亲测有效)
  9. coredump_filter的设置
  10. SharePoint服务器端对象模型 之 访问文件和文件夹(Part 4)
  11. Python实现计算机屏幕任意区域截图
  12. 用户虚拟地址转换成物理地址
  13. 关于hbase安装出现的问题
  14. scrapy爬虫框架实现简单案例:爬取阳光平台内容
  15. es6中 使用class里面的set和get 用法
  16. 用环状天线测向电压表鉴相器电路定位的无线电测向仪
  17. POJ:3276-Face The Right Way(线性反转)
  18. 制作ubuntu18.04启动盘 + 安装ubuntu18.04
  19. Eclipse IDE for Java EE Developers 去哪里了?
  20. 【拜读】HTTPS和SSL/TLS 协议

热门文章

  1. 【腾讯出品】2019互联网行业趋势报告
  2. 北京市通信管理局对3·15晚会曝光的北京企业作出行政处罚
  3. Apple新品京东到家、小时购首发开售 超1400家门店“小时送达”
  4. 9999元起!荣耀Magic V今日首销:首款骁龙8折叠屏旗舰
  5. 微博:第二批共处置10106个账号 十万粉丝到一百万粉丝的账号8个
  6. 广电总局拟规定设立未成年人频道
  7. RedmiK40系列首销5分钟破30万台 旗舰焊门员实至名归
  8. 男子拒绝春节带电脑回家工作被开除,最后结果十分舒适...
  9. 微信8.0来了!黄脸表情会动了,还能扔炸弹...一大波新功能上线!
  10. 特斯拉召回部分进口Model S、Model X电动汽车