ChatGPT3.5使用体验

MySQL 中的索引 前言
上篇文章聊完了 MySQL 中的锁,这里接着来看下 MySQL 中的索引 。
一般当我们数据库中的某些查询比较慢的时候,正常情况下,一顿分析下来,大多数我们会考虑对这个查询加个索引,那么索引是如何工作的呢?为什么索引能加快查询的速度,下面来具体的分析下 。
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单 。
索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容 。
索引的优点:
1、索引大大减少了服务器需要扫描的数据量;
2、索引可以帮助服务器避免排序和临时表;
3、索引可以将随机 I/O 变成顺序 I/O 。
如何评价一个索引,Indexand the 一书介绍了如何评价一个索引是否符合某个查询的三个星际判断标准:
1、一星:索引将相关的记录放在一起就评定为一星;
2、二星:如果索引中的数据顺序和查找中的排序顺序一致就评定为二星;
3、三星:如果索引中的列包含了查询中需要的全部列就评定为三星 。
建索引的几大原则
1、最左前缀匹配原则,非常重要的原则,mysql 会一直向右匹配直到遇到范围查询(>、 3andd = 4如果建立(a,b,c,d)顺序的索引,d 是用不到索引的,如果建立(a,b,d,c)的索引则都可以用到,a,b,d的顺序可以任意调整;
2、= 和 in 可以乱序,比如a = 1 and b = 2 and c = 3建立(a,b,c)索引可以任意顺序,mysql的查询优化器会帮你优化成索引可以识别的形式;
3、尽量选择区分度高的列作为索引,区分度的公式是count( col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要 join 的字段我们都要求是 0.1 以上,即平均 1 条扫描 10 条记录;
4、索引列不能参与计算,保持列“干净”,比如() = ’2014-05-29’就不能使用到索引,原因很简单,b+ 树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大 。所以语句应该写成 = (’2014-05-29’);
5、尽量的扩展索引,不要新建索引 。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可 。
索引的实现
支持三种索引模型:
1、哈希索引;
2、全文索引;
3、B+ 树索引 。
哈希索引
哈希表也称为散列,是一种以键-值 (key-value) 存储数据的结构 。输入查询的 key,就能找到对应的 value 。哈希的思路很简单,把值放在数组里,用一个哈希函数把 key 换算成一个确定的位置,然后把 value 放在数组的这个位置 。
当然会存在哈希冲突,对个 key 在经过哈希算法处理后可能出现在哈希表中的同一个槽位,当出现哈希冲突的时候,可以使用链表来解决 。这样发生冲突的数据都放入到链表中 。在进行数据查询的时候,首先找到哈希表中的槽位,然后在链表中依次遍历找到对应的值 。
哈希表的这种结构适合于等值查询的场景,在最优场景的下的时间复杂度能达到O(1) 。
哈希索引的缺点
1、因为是哈希表存储的是 Hash 运算之后的 Hash值,所以它只能用于等值的查询,范围查询在哈希索引中不支持;
2、无法利用索引排序,索引中存储的只是 Hash 计算之后的 Hash 值,对于排序,索引本身无法支持;