一、 什么是Mysql的索引?

1. Mysql索引是一种方便Mysql数据查询和排序的数据结构,一般分为Hash和B+Tree;

2. Mysql索引在数据结构上分为Hash和B+Tree;

3. 在数据存储上分为聚集(聚簇)索引和非聚集索引;

4. 在逻辑上分为主键索引,唯一索引,普通索引,覆盖索引,组合索引,全文索引;


二、BTree和B+Tree以及Hash:

    1、BTree:

                        

         1. BTree是多叉平衡树,尽可能的在树的每一层放更多数据,这样树的高度就越低,

                更能节省查询次数(如果是文件存储则节省 IO次数),BTree每个节点都会关联存放数据;

         2. 叶子节点具有相同的深度,叶子节点指针为空;

          3. 所有索引元素不重复;

         4. 节点中的数据索引从左到右递增排列;


    2、B+Tree:

        1. 非叶子节点不存储数据,只存储索引,子节点同样的空间可以放更多的索引;

        2. 叶子节点包含所有索引字段;

        3. 叶子节点使用指针链接,提高区间访问效率;

         4. B+Tree是BTree的变种;

    

    3、BTree和B+Tree的区别:

         1. BTree每个节点都会存放数据,而B+Tree将所有数据放在叶子节点,非叶子节点不存放数据,只做冗余索引指向

                子节点的索引地址;

         2. B+Tree非叶子节点存储数据只存放索引,为了组成树结构会把子节点的第一个元素抽取到父节点作为冗余索引;

         3. B+Tree非叶子节点存储数据只存放索引,每个节点同样的空间可以放更多的索引,节点存放元素越多,分叉就越多,

                同样的数据量B+Tree的高度要比BTree低很多;

         4. BTree叶子节点上的数据之间存在地址链接,叶子节点之间指针为空,而B+Tree的叶子节点上的数据之间不需要地址链接

                而是直接按照索引从小到大紧密排列,节省了存放地址链接的空间,叶子节点之间通过双向指针关联索引文件地址,

                有利于提交区间访问效率;


    4、MyISAM索引存储结构:


  

    5、InnoDB索引存储结构


   6、HASH索引

                                


    7、为什么不用二叉树或者二叉平衡树存储索引?

        1.因为容易造成IO频繁,影响效率,mysql数据动则几百万甚至上千万数据,如果使用二叉树或者二次平衡树存储,

            此时的树会达到一个相对较大的高度,

         2.而mysql索引和数据一般放在磁盘上,如果树的高度太大会大大增加IO的次数,最坏情况IO次数就是树的高度次,

            频繁的IO会消耗大量时间;


三、使用索引的优化和注意事项:


  1. 创建索引的原则

     1. 最左前缀匹配原则;

     2. 频繁作为查询条件的字段才去创建索引;

     3. 频繁更新的字段不适合创建索引;

     4. 索引列不能参与计算,不能有函数操作;

     5. 优先考虑扩展索引,而不是新建索引,避免不必要的索引;

     6. 在order by或者group by子句中,创建索引需要注意顺序;

     7. 区分度低的数据列不适合做索引列(如性别);

     8. 定义有外键的数据列一定要建立索引;

     9. 对于定义为text、image数据类型的列不要建立索引;

     10. 删除不再使用或者很少使用的索引;

    2. 索引有哪几种类型?

         1. 主键索引: 数据列不允许重复,不允许为NULL,一个表只能有一个主键;

         2. 唯一索引: 数据列不允许重复,允许为NULL值,一个表允许多个列创建唯一索引;

         3. 普通索引: 基本的索引类型,没有唯一性的限制,允许为NULL值;

         4. 全文索引:是目前搜索引擎使用的一种关键技术,对文本的内容进行分词、搜索;

         5. 覆盖索引:查询列要被所建的索引覆盖,不必读取数据行;

         6. 组合索引:多列值组成一个索引,用于组合搜索,效率大于索引合并;

    3. 一条sql执行过长的时间,你如何优化,从哪些方面入手?

        1. 查看是否涉及多表和子查询,优化Sql结构,如去除冗余字段,是否可拆表等;

        2. 优化索引结构,看是否可以适当添加索引;

         3. 数量大的表,可以考虑进行分离/分表(如交易流水表);

        4. 数据库主从分离,读写分离;

        5. explain分析sql语句,查看执行计划,优化sql;

        6. 查看mysql执行日志,分析是否有其他方面的问题;


    4. Hash索引和B+树区别是什么?设计索引时如何抉择?

         1. B+树可以进行范围查询,Hash索引不能;

         2. B+树支持联合索引的最左侧原则,Hash索引不支持;

        3. B+树支持order by排序,Hash索引不支持;

        4. Hash索引在等值查询上比B+树效率更高;

        5. B+树使用like 进行模糊查询的时候,like后面(比如%开头)的话可以起到优化的作用,Hash索引根本无法进行模糊查询;


    5. 为什么Mysql数据库InnerDB表建议必须设置主键,不设置会怎样?

         1. 如果不设置主键,mysql会推导使用不重复不为null的字段作为主键;

         2. 如果没有这样的字段,会隐式维护一个字段作为主键;

         3. 如果没有设置主键会增加Mysql维护聚集索引带来的额外开销,而数据库资源是非常宝贵的,

              建议能让Mysql少操作的内容就尽可能节省下来,以提高读写效率;

    6. Mysql主键为什么使用自增Number类型数据要比非Number类型的无序数据好?

         1. Mysql主键一般是B+Tree数据结构,B+Tree节点中的数据索引从左到右递增排列;

         2. 如果使用非Number数据类型数据作为索引,在查找匹配和插入时需要为了保持有序性需要做大小比较,

              效率远不如Number类型数据高,如字符串匹配需要逐一字符ASCII码比较;

        3. 如果使用无序的数据作为索引,在插入时为了保持有序性需要比较大小,如果发现是需要存放到节点上中间的

              索引位置,则会使得节点分裂,且需要做树的平衡操作,效率不如有自增数据直接追加到节点右侧高;

    7. 索引是建的越多越好吗?

         1. 答案自然是否定的;

         2. 数据量小的表不需要建立索引,建立会增加额外的索引开销;

         3. 不经常引用的列不要建立索引,因为不常用,即使建立了索引也没有多大意义;

         4. 经常频繁更新的列不要建立索引,因为肯定会影响插入或更新的效率;

         5. 数据重复且分布平均的字段,因此他建立索引就没有太大的效果(例如性别字段,只有男女,不适合建立索引);

        6. 数据变更需要维护索引,意味着索引越多维护成本越高;

        7. 更多的索引也需要更多的存储空间;


    8. 为什么使用联合索引是需要遵循最左前缀匹配原则?

         1. 联合索引为了保证索引从左到右递增排列,会根据联合索引每个字段挨个顺序比较大小排列;

         2. 此时排除索引第一列数据是有序的,其他列的数据都将是无需的,而要匹配无序数据就需要遍历查找所有的索引簇;

         3. 既然都是遍历查找自然就发挥不了索引查询的优势;