# 索引原理（mssql与mysql）


# 简介
## 为什么要有索引？
对于通用系统而言，大部分数据读操作比例远高于写入操作，针对查询进行优化的时候，优先需要考虑索引优化。
## 什么是索引？
索引在MySQL中也叫是一种“键”，是存储引擎用于快速找到记录的一种**数据结构**。索引对于良好的性能非常关键，尤其是当表中的数据量越来越大时，索引对于性能的影响愈发重要。
索引优化应该是对查询性能优化最有效的手段了。
## 常见误区
- 索引是不是越多越好？X

> - 索引会增加数据库服务器写入操作的成本（INNODB对这个 做了一个优化：插入缓存 将多次插入合并成一次插入）
> - 太多的索引会影响mysql查询优化器的选择时间（影响查询效率）

- 索引的过度设计问题 
> - 索引应该属于专事专办，大部分情况下是"**私人定制**"款，针对特定sql的索引优化未必适用于其他sql，针对特定业务的索引优化未必适合其他业务；
> - ** 索引不是万能的，使用索引的初衷是解决查询问题，如果存在其他方案解决的话，应该优先考虑方案的可用性，而不是一定要把问题限制在db内解决**
> -  索引的适用性问题，blob,img,text这些数据类型不适合用来做索引；


# 索引原理
>索引是一种利用某种规则的数据结构与实际数据的关系加快数据查找的功能；
>索引数据节点中有着实际文件的位置，因为索引是根据特定的规则和算法构建的,在查找的时候遵循索引的规则可以快速查找到对应数据的节点，从而达到快速查找数据的效果；其实宏观来说索引其实是一种概念而不是具体的某项技术，只是我们在某个技术中运用得比较广泛和鲜明（比如说数据库）渐渐的有了特定领域的标签，其实在生活中索引的使用无处不在，比如说：书本里的目录；读书时的座位号，考试编号都有类似索引的功能; 
> 总结来所有通过某规则数据结构和实际目标关联，根据特定规则算法快速寻址的功能都可以称之为索引；

索引通过特定的数据结构来实现快速数据查找。
## 索引的数据结构
### BTree 
 可以被用在=,>,>=,<,<=和between这些比较操作符上，而且还可以用于like操作符，只要它的查询条件是一个不以通配符开头的常量
- B-Tree
- B+Tree
### Hash
Hash索引只能用于对等比较，例如=,<=>（相当于=）操作符。由于是一次定位数据，不像BTree索引需要从根节点到枝节点，最后才能访问到页节点这样多次IO访问，所以检索效率远高于BTree索引。
#### 弊端
- Hash索引仅仅能满足“=”,“IN”,“<=>”查询，不能使用范围查询。
- 联合索引中，Hash索引不能利用部分索引键查询。
> 对于联合索引中的多个列，Hash是要么全部使用，要么全部不使用，并不支持BTree支持的联合索引的最优前缀，也就是联合索引的前面一个或几个索引键进行查询时，Hash索引无法被利用。
- Hash索引无法避免数据的排序操作
> 由于Hash索引中存放的是经过Hash计算之后的Hash值，而且Hash值的大小关系并不一定和Hash运算前的键值完全一样，所以数据库无法利用索引的数据来避免任何排序运算。
- Hash索引任何时候都不能避免表扫描
> Hash索引是将索引键通过Hash运算之后，将Hash运算结果的Hash值和所对应的行指针信息存放于一个Hash表中，由于不同索引键存在相同Hash值，所以即使满足某个Hash键值的数据的记录条数，也无法从Hash索引中直接完成查询，还是要通过访问表中的实际数据进行比较，并得到相应的结果。
- Hash索引遇到大量Hash值相等的情况后性能并不一定会比BTree高
> 对于选择性比较低的索引键，如果创建Hash索引，那么将会存在大量记录指针信息存于同一个Hash值相关联。这样要定位某一条记录时就会非常麻烦，会浪费多次表数据访问，而造成整体性能底下。
### 关于hash索引
1. hash索引查找数据基本上能一次定位数据，当然有大量碰撞的话性能也会下降。而btree索引就得在节点上挨着查找了，很明显在数据精确查找方面hash索引的效率是要高于btree的；
2. 那么不精确查找呢，也很明显，因为hash算法是基于等值计算的，所以对于“like”等范围查找hash索引无效，不支持；
3. 对于btree支持的联合索引的最优前缀，hash也是无法支持的，联合索引中的字段要么全用要么全不用。 
4. hash不支持索引排序，索引值和计算出来的hash值大小并不一定一致。
