• 关于


    MySQL 数据库存储数据最终是以文件的形式存储到硬盘的,在程序中使用要把磁盘文件中的数据读到内存中
    执行一次IO的时间可以执行40万条指令(如果以 CPU 的指令执行效率来比较的话) 数据库量百万千万级数据,如每次io 9毫秒的时间显然是个灾难
    所以查找数据时把磁盘IO次数控制在一个很小的数量级,一个高度可控的多路搜索树就是 B + 树
    树的高度决定着io的次数,如果没有索引 没有索引则检索过程变成了顺序查找,O(n)的时间复杂度几乎是不能忍受 ,每个磁盘块都要发生一次IO(单个磁盘块中不可能存储太多数据) 效率会特别差

    一、底层实现原理和优化
          在数据结构中,最常见的搜索结构就是二叉搜索树和AVL树(高度平衡的二叉搜索树,,当数据量比较大时,都会由于树的深度过大而造成I/O读写过于频繁,进而导致查询效率低下
          mysql的索引数据结构采取的是B+树
          B+树索引并不能根据键值找到具体的行数据,B+树索引只能找到行数据锁在的页,然后通过把页读到内存,再在内存中查找到行数据
          B+树,它的树高是恒定(可以控制在3到5层),它的渐进复杂度是恒定的
         索引若采用哈希:
             可以通过hash值定位具体的位置,效率高,但是不能进行模糊查询 范围查询
         一个索引的是否优秀判断的依据是 IO渐进复杂度
         索引若采用二叉树:
             若是一个斜二叉树,查询速度和全表扫描没有区别,树高
         索引若采用平衡二叉树:
             太深了:深度决定者io的次数,而io耗时大
             太小了:结点存储的信息太小了,从而导致频繁的io操作
         索引若采用红黑树:
              比二叉树相对来说会好一些。它会有一个因子会控制树高,无论二叉搜索树还是AVL树,当数据量比较大时,都会由于树的深度过大而造成I/O读写过于频繁
         索引若采用多路平衡二叉树:(B-Tree B树):
            (1)每个节点中有key,也有data,而每一个页的存储空间是有限的,如果data数据较大时就会导致每个节点(即一个页)能存储的key的数量很小
            (2)当存储的数据量很大时,同样1会导致B-Tree的深度较大,增加查询时的磁盘I/O次数,进而影响查询效率
         B+Tree叶子结点是顺序的,相邻结点存在顺序引用
             1:B+Tree拥有B-Tree的优点,深度浅,数据块大
             2:因为只在叶子结点存储数据,从而导致扫全表的能力强,因为叶子结点是顺序的,从而导致排序功能更强

    二、B+树更适合B树
          磁盘读写代价更低:
              B+tree的内部结点相对B 树更小,相对来说IO读写次数也就降低了
          查询效率更加稳定:
              任何关键字的查找必须走一条从根结点到叶子结点的路,所有关键字查询的路径长度相同,导致每一个数据的查询效率相当
          主要原因:
              B+树只要遍历叶子节点就可以实现整棵树的遍历 方便扫库,而且在数据库中基于范围的查询是非常频繁的,而B树只能中序遍历所有节点,效率太低

    三、文件索引和数据库索引使用B+树的原因
          文件与数据库都是需要较大的存储,也就是说,它们都不可能全部存储在内存中,故需要存储到磁盘上
          数据库系统巧妙利用了局部性原理与磁盘预读原理,将一个节点的大小设为等于一个页,这样每个节点只需要一次I/O就可以完全载入
          而红黑树这种结构,高度明显要深的多,并且由于逻辑上很近的节点(父子)物理上可能很远,无法利用局部性。
          B+树最大的好处:只要遍历叶子节点就可以实现整棵树的遍历 方便扫库,而且在数据库中基于范围的查询是非常频繁的。
                                    而B树只能中序遍历所有节点,效率太低

    四、索引的优点
         加快数据的检索速度
         加速表和表之间的连接;
         通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性
         使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间;(有序)

    五、索引的缺点
         时间方面:创建索引和维护索引要耗费时间 ,R U D时,索引也要动态的维护,这样就降低了数据的维护速度;
         空间方面:索引需要占物理空间

    六、索引类型
         普通索引、唯一索引、组合索引 、全文索引 。不一一介绍了
         HASH 哈希索引 (MEMORY支持)

    七、什么数据应该添加索引 (索引干两件事:检索和排序)
         1.频繁作为查询条件的字段
         2.查询中排序的字段 (有序)
         3.主外键关系的字段 (可以加快连接的速度)
         4.经常需要根据范围进行搜索的列上 (索引已经排序,其指定的范围是连续的)
         5.经常需要排序的列上
         注意:对于大的文本字段甚至超长字段 可以用前缀索引

    八、索引注意事项
         1.注意组合索引键列顺序
         2.正确使用索引 遵循SARG规则
            SARG 用于限制搜索的一个操作,是一个值的范围内的匹配或者两个以上条件的AND连接
            SARG规则 如果使用not 或者 <>,最好转换成别的方法
            不满足SARG形式的语句最典型的情况就是包括非操作符的语句,如:NOT、!=、<>;、!<;、!>;、NOT EⅪSTS、NOT IN、NOT LIKE等,
           另外还有索引字段不能用函数.
           如:Name=’张三’ and 价格>5000 符号SARG,
           而:Name=’张三’ or 价格>5000 则不符合SARG。
           使用or会引起全表扫描。尽量不要对建立了索引的字段,作任何的直接处理

           2.1.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,表字段时不能允许为null的列 可设置默认值
               select id from t where num is null 可以在num上设置默认值0
               应改为:
               select id from t where num=0
          2.2.应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。
          2.3.应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描 (少用or)
               select id from t where num=10 or num=20
               应改为:
               select id from t where num=10    union all     select id from t where num=20
         2.4.in 和 not in 也要慎用,因为IN会使系统无法使用索引,而只能直接搜索表中的数据
               select id from t where num in(1,2,3)   对于连续的数值,能用 between 就不要用 in 了
               应改为:
               select id from t where num between 1 and 3
         2.5.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描
               select id from t where substring(name,1,3)='abc'--name以abc开头的id
               select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id
               应改为:
               select id from t where name like 'abc%' (通配符 前缀索引)
               select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'
         2.5.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引
         2.6.用not exists都比not in要快
               not in 那么内外表都进行全表扫描,没有用到索引;
               not extsts 的子查询依然能用到表上的索引
         2.7.能用UNION ALL就不要用UNION
               UNION ALL不执行SELECT DISTINCT函数(去重),这样就会减少很多不必要的资源
         2.8.前缀索引
               char/varchar太长全部做索引的话,效率太差,存在浪费
               无法使用其前缀索引做ORDER BY和GROUP BY,也无法使用前缀索引做覆盖扫描

    群交流(262200309)
  • 相关阅读:
    Java的Object类
    java中String、StringBuffer、StringBuilder的区别
    Java正则表达式
    《java编程思想》P160-P180(第八章部分+第九章部分)
    《java编程思想》P140-P160(第七章复部+第八章部分)
    《java编程思想》P125-P140(第七章复用类部分)
    Servlet 工作原理解析
    大型高性能网站的十项规则
    Java 理论与实践: 并发在一定程度上使一切变得简单
    Java并发基础构建模块简介
  • 原文地址:https://www.cnblogs.com/webster1/p/12404805.html
Copyright © 2020-2023  润新知