建立索引的原则 - 以innodb为例

本文介绍了MySQL中的索引原理及优化方法,详细解释了B+Tree索引结构,并提出了建立高效索引的具体原则,帮助读者理解如何提升SQL查询效率。

一、写在前面

        随着开发、测试任务进入尾声,大家都在整理一些项目发布前的一些准备工作,其中一个重要的工作就是为之前写的一些sql语句建立索引,这高并发、高访问量的环境下是非常有必要的,建立一个好的索引能够极大地提高sql语句的查询效率,那么问题来了,到底什么是索引,怎样才能建立一个好的索引呢?本文以mysql Innodb存储引擎为例,结合实际的项目来看一下,如何建立一个好的而索引。

二、索引定义

        MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。提取句子主干,就可以得到索引的本质:索引是数据结构。
        我们知道,数据库查询是数据库的最主要功能之一,例如下面的SQL语句:SELECT * FROM test_table WHERE id = 99 ;可以从表test_table中获得id为99的数据记录。
        我们都希望查询数据的速度能尽可能的快,因此数据库系统的设计者会从查询算法的角度进行优化。最基本的查询算法当然是顺序查找(linear search),遍历test_table然后逐行匹配id的值是否是99,这种复杂度为O(n)的算法在数据量很大时显然是糟糕的,好在计算机科学的发展提供了很多更优秀的查找算法,例如二分查找(binary search)、二叉树查找(binary tree search)等。如果稍微分析一下会发现,每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树上,但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不可能同时将两列都按顺序进行组织),所以,在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。
        举上面的例子主要是为了简单说明地说明索引的作用,包括mysql Innodb在内的大部分数据库系统及文件系统并没有选择二叉树结构作为索引,而是采用了B-Tree或其变种B+Tree作为索引结构,这种索引结构可以最大限度地减少查找过程中磁盘I/O的存取次数,关于什么是B-Tree或B+Tree以及选择它们做数据库索引结构的原因,大家可以自行去学习。下面我们首先介绍下mysql Innodb引擎的两种B+Tree索引。

三、Mysql Innodb B+Tree索引

  1. 一种是主键索引,主键索引即聚集索引(Cluster Index),它不仅有主键,而且有主键所属的全部数据,所以在Innodb中,主键索引即数据;
  2. 一种是列值为Key,主键位置为Value即 (列值, 主键位置) 的非主键索引(Secondary Index) 1 2         Innodb属于索引组织表,所有的数据全部挂在主键叶子节点下。所以如果不能保证主键的插入顺序,那么会发生大量的主键节点分裂,产生大量的I/O操作。另外Innodb规定单个索引字段的长度不得超过768字节,否则截断超出长度不放入索引。         Innodb的非主键索引全部都指向主键索引,查找非主键索引无法获得整行数据,需要通过叶子节点的指针查到其主键索引的位置才能获得整行数据,所以主键索引必须设计得尽可能小,否则非主键索引将会非常的大。

四、建立索引的原则

        下面我们看一下建立一个好的索引需要遵循的原则,并结合具体的例子来做说明;
1. 最左前缀匹配原则,非常重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就停止匹配,比如a = 1 and b = 2 and c > 3 and d = 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(distinct col)/count(*),表示字段不重复的比例,比例越大我们扫描的记录数越少,唯一键的区分度是1,而一些状态、性别字段可能在大数据面前区分度就是0,那可能有人会问,这个比例有什么经验值吗?使用场景不同,这个值也很难确定,一般需要join的字段我们都要求是0.1以上,即平均1条扫描10条记录
4. 索引列不能参与计算,保持列“干净”,比如from_unixtime(create_time) = ‘2015-08-14’就不能使用到索引,原因很简单,b+树中存的都是数据表中的字段值,但进行检索时,需要把所有元素都应用函数才能比较,显然成本太大。所以语句应该写成create_time = unix_timestamp(‘2015-08-14’)。
5. 尽量的扩展索引,不要新建索引。比如表中已经有a的索引,现在要加(a,b)的索引,那么只需要修改原来的索引即可。
6. 在order by或者group by子句中,如果想通过索引来进行排序,所建索引列的顺序必须与order by或者group by子句的顺序一致,并且所有列的排序方向(倒序或者正序)都一样;如果查询关联多张表,则只有order by子句引用的字段全部来自第一张表时,才能利用索引来排序;order by或者group by语句与查询型语句的限制是一样的:需要满足索引的最左前缀原则;否则mysql就要执行排序操作,无法利用索引来排序;(有一种情况order by或者group by子句可以不满足最左前缀原则,就是其前导为常量的时候,如果where或者join对这些列指定了常量,就可以弥补索引的不足)。

五、举例

        语句1:
3
        语句2:
4
        对于这两条语句,如果单独进行考虑的话,大家可能会建立两个索引;
针对语句1建立(status,netting_batch_no,debtor_agent_member_id);
针对语句2建立(netting_batch_no,debtor_agent_member_id,transaction_currency);
如果综合考虑来看的话,其实一个索引就够了,即(netting_batch_no,debtor_agent_member_id),这里没必要将status或者transaction_currency字段放到索引中,因为这两个字段的区分度太差;
根据建立索引的原则2,语句1是可以走到这个索引的;
根据建立索引的原则1,语句2也是可以走到这个索引的;
索引不是越多越好,建立过多的索引会增加数据库内存或者磁盘的消耗,并且会影响到得插入、删除等操作的性能,索引在建立索引时要遵循索引建立的原则,通盘考虑;

<think>好的,我需要帮助用户了解如何构数据库索引及目录结构,特别是在数据库和文件系统中。首先,我需要回顾相关的引用内容,确保回答准确。 根据引用[1]和[2],索引的核心是数据结构,如B树和B+树,它们帮助高效查询。用户的问题涉及创索引和目录结构,这可能包括索引的设计步骤、数据结构选择以及目录的组织方式。此外,引用[3]提到了页目录中使用二分法定位数据,说明物理存储结构也很重要。 接下来,我需要将内容分步骤组织。首先解释索引的基本原理,然后讨论数据结构的选择,比如B+树的特点。接着,创索引的具体步骤可能包括分析查询模式、选择字段、确定类型等。目录结构部分需要说明页目录如何组织,比如双向链表和槽的分组。文件系统方面可能需要提及分层结构,如目录项和索引节点。 还要注意用户可能的深层需求,比如性能优化和实际应用中的注意事项,比如索引的优缺点和维护。需要结合引用中的子,如InnoDB的页目录结构,让回答更具体。 最后,生成相关问题时要围绕索引设计、优化、结构比较和应用场景,确保问题有针对性,帮助用户进一步学习。</think>### 如何构数据索引及目录结构? #### 1. **索引的构原理** 索引的核心是通过特定数据结构(如$B+$树)对数据字段进行排序和组织,以加速查询。如,数据库索引类似于书籍目录,通过快速定位关键词对应的页码来减少全表扫描的时间[^2]。 **关键步骤**: - **选择索引字段**:高频查询或筛选条件的字段(如主键、外键、时间戳)。 - **确定数据结构**:常见结构包括哈希表(精确匹配)、$B$树(平衡多路搜索树)、$B+$树(优化范围查询)[^2]。 - **维护索引**:数据增删改时同步更新索引,保证数据一致性查询效率。 #### 2. **目录结构的设计** 在文件系统或数据库存储引擎中,目录通常通过分层结构管理数据位置。以InnoDB- **页目录**:每个数据页(默认16KB)划分为若干记录组,通过槽(Slot)记录组的位置。查找时先用二分法定位槽,再在组内顺序遍历[^3]。 - **双向链表**:数据页之间通过双向链表连接,支持高效的范围扫描。 #### 3. **具体实现示** **数据库索引(以SQL为)**: ```sql CREATE INDEX idx_user_email ON users(email); -- 在users表的email字段创B+树索引 ``` **文件系统目录结构**: - **目录项(Directory Entry)**:存储文件名对应索引节点(Inode)的映射。 - **索引节点(Inode)**:记录文件元数据(权限、大小、数据块地址)。 #### 4. **优化权衡** - **优点**:加速查询,减少I/O次数[^2]。 - **缺点**:占用额外存储空间,增删改操作变慢。 - **设计原则**: - 避免过度索引(如频繁更新的字段)。 - 联合索引需考虑字段顺序(最左匹配原则)。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值