举例说明聚集索引和非聚集索引

数据库索引深入解析

数据库的索引,听起来挺神秘的,仔细想想。这些索引,其实就是平时咱们查东西时候常用的两种手段。无非就是为了提高我们找东西的效率而已。那么我们平时又是怎么查东西呢? 

聚集索引:

       聚集索引,来源于生活尝试。这中索引可以说是按照数据的物理存储进行划分的。对于一堆记录来说,使用聚集索引就是对这堆记录 进行 堆划分。即主要描述的是物理上的存储。


举个例子:

       比如图书馆新进了一批书。那么这些书需要放到图书馆内。书如何放呢?一般都有一个规则,杂志类的放到101房间,文学类的放到102房间,理工类的放到103房间等等。这些存储的规则决定了每本书应该放到哪里。而这个例子中聚集索引为书的类别。 
       正式因为这种存储规则,才导致 聚集索引的唯一性。


误区:

       有的人认为,聚集索引的字段是唯一的。这是因为sql server 中添加主键的时候,自动给主键所在的字段生成一个聚集索引。所以人们会认为聚集索引所加的字段是唯一的。 
       思考一下上面这个问题。杂志类的书放到101房间。那么如果杂志类的书太多,一个101房间存放不下。那么可能101,201两个房间来存放杂志类的书籍。如果这样分析的话,那么一个杂志类对应多个房间。放到表存储的话,那么这个类别字段 就不是唯一的了。 


非聚集索引:

       非聚集索引,也可以从生活中找到映射。非聚集索引强调的是逻辑分类。可以说是定义了一套存储规则,而需要有一块控件来维护这个规则,这个被称之为索引表。


继续使用上述提到的例子:

       同学如果想去图书馆找一本书,而不知道这本书在哪里?那么这个同学首先应该找的就是 检索室吧。对于要查找一本书来说,在检索室查是一个非常快捷的的途径了吧。但是,在检索室中你查到了该书在XX室XX书架的信息。你的查询结束了吗?没有吧。你仅仅找到了目的书的位置信息,你还要去该位置去取书。


对于这种方式来说,你需要两个步骤: 
       1、查询该记录所在的位置。 
       2、通过该位置去取要找的记录。


区别:

       聚集索引:可以帮助把很大的范围,迅速减小范围。但是查找该记录,就要从这个小范围中Scan了。 
       非聚集索引:把一个很大的范围,转换成一个小的地图。你需要在这个小地图中找你要寻找的信息的位置。然后通过这个位置,再去找你所需要的记录。

索引与主键的区别

       主键:主键是唯一的,用于快速定位一条记录。 
       聚集索引:聚集索引也是唯一的。(因为聚集索引的划分依据是物理存储)。而聚集索引的主要是为了快速的缩小查找范围,即记录数目未定。 
       主键和索引没有关系。他们的用途相近。如果聚集索引加上唯一性约束之后,他们的作用就一样了。

使用场景

基于上述的两种规则,那么在什么时候适合聚集索引,什么时候适合非聚集索引? 

试用场景

转载于https://blog.youkuaiyun.com/zc474235918/article/details/50580639

通俗易懂,大家可以去他主页看看

<think>好的,我现在需要详细解释聚集索引二级索引的区别及使用场景。首先,我得回顾一下用户提供的引用内容,确保准确引用相关信息。用户引用了多个来源,其中[^3][^5]特别提到了聚集索引二级索引的结构特点,可能需要重点参考。 首先,聚集索引的定义。根据引用[^3],聚集索引在InnoDB中通常是主键索引,数据按索引顺序物理存储。这意味着表中的数据行实际上按照聚集索引的键值排序,并且叶子节点直接存储数据行。例如,用户表中的id字段作为主键,数据按id顺序存储。然后是二级索引,也称为非聚集索引。引用[^3]提到,二级索引如idx_username的叶子节点存储的是索引列的值对应的主键值。当使用二级索引查询时,如果需要获取其他列的数据,必须通过主键值回到聚集索引中查找,这就是回表查询。例如,查询username='Alice'时,先找到id,再用id去聚集索引拿完整数据。接下来需要比较两者的区别。结构上,聚集索引数据存储紧密相关,而二级索引独立存储,仅保存主键引用。查询效率方面,聚集索引对于范围查询高效,因为数据连续;二级索引可能需回表,但覆盖索引可以避免。数量上,每个表只能有一个聚集索引,但可以有多个二级索引。主键的选择会影响聚集索引的结构,如果没主键,InnoDB会生成隐藏的ROWID作为聚集索引。 使用场景方面,引用[^5]中的表格指出聚集索引适合经常分组排序、返回范围数据、主键外键列。而二级索引适用于高频条件查询、大数目不同值的情况。例如,用户表的主键id用聚集索引加速ID查询,而用户名上的二级索引用于快速按用户名搜索,但需要回表。 还需要考虑覆盖索引的概念,引用[^4]提到创建包含多列的索引可以避免回表。例如,索引包含(column3, column1,column2)时,查询这些列可直接从索引获取数据,无需回表,提升效率。 可能的问题点:用户可能混淆主键索引聚集索引,虽然InnoDB中主键索引就是聚集索引,但其他数据库可能不同。需要明确说明这一点。另外,回表查询的开销如何通过覆盖索引优化,这也是使用二级索引时需要注意的地方。 总结结构时,应分点列出定义、结构区别、查询过程差异、数量限制、使用场景,并举例说明。同时,数学公式部分需要正确使用LaTeX,比如B+树的时间复杂度计算。最后生成相关问题,如覆盖索引的应用、如何选择主键等。</think>### 聚集索引与二级索引核心解析 --- #### 一、基本定义 1. **聚集索引(Clustered Index)** - **数据即索引**:叶子节点直接存储完整数据行,数据在磁盘上按索引键顺序物理存储[^3] - **默认主键**:在 InnoDB 中,主键索引即为聚集索引;若无主键,则自动生成隐藏 ROWID 作为聚集索引[^3][^5] - **唯一性**:每个表仅允许存在一个聚集索引 2. **二级索引(Secondary Index,非聚集索引)** - **指针式索引**:叶子节点存储索引列值 + 对应主键值(或 ROWID),需通过**回表查询**获取完整数据[^3] - **数量灵活**:一个表可创建多个二级索引(如用户名、邮箱等字段) - **覆盖索引优化**:若索引包含查询所需全部字段,可跳过回表操作直接返回结果[^4] --- #### 二、核心区别对比 | 特性 | 聚集索引 | 二级索引 | |---------------------|-----------------------------------|-----------------------------------| | **数据存储方式** | 数据行按索引顺序物理存储 | 独立存储,仅保存主键引用 | | **叶子节点内容** | 完整数据行 | 索引列值 + 主键值 | | **索引数量** | 1个/表 | 多个/表 | | **查询效率** | 范围查询高效(数据连续) | 需回表时效率较低,覆盖索引可优化 | | **典型应用场景** | 主键查询、范围扫描、排序操作[^5] | 高频条件查询、联合索引优化[^3] | --- #### 三、查询过程示例 **用户表结构**: ```sql CREATE TABLE users ( id INT PRIMARY KEY, -- 聚集索引 username VARCHAR(50), email VARCHAR(50), INDEX idx_username (username) -- 二级索引 ) ENGINE=InnoDB; ``` 1. **通过聚集索引查询** ```sql SELECT * FROM users WHERE id = 100; ``` - 直接定位到 id=100 的叶子节点,获取完整数据行 - **时间复杂度**:$O(\log_m n)$(B+Tree 层级搜索)[^3] 2. **通过二级索引查询** ```sql SELECT * FROM users WHERE username = 'Alice'; ``` - **步骤1**:通过 `idx_username` 找到 username='Alice' 对应的主键 id - **步骤2**:通过 id 回到聚集索引获取完整数据行(回表)[^3] - **总时间复杂度**:$O(\log_m n) + O(\log_m n)$ --- #### 四、使用场景建议 1. **聚集索引适用场景** - **主键查询**:如 `WHERE id=123` - **范围查询**:如 `WHERE id BETWEEN 100 AND 200` - **排序操作**:如 `ORDER BY id DESC` - **频繁更新的列**:避免二级索引频繁更新主键引用[^5] 2. **二级索引适用场景** - **高频条件查询**:如 `WHERE username='Alice'` - **覆盖索引优化**:如 `SELECT username FROM users WHERE username LIKE 'A%'` - **联合索引**:如 `INDEX (age, city)` 优化 `WHERE age>20 AND city='北京'`[^4] - **大字段检索**:对 `TEXT` 类型字段建立全文索引(特殊二级索引)[^1] --- #### 五、性能优化技巧 1. **减少回表查询** - 使用覆盖索引: ```sql CREATE INDEX idx_covering ON users(username, age); -- 包含查询所需字段 SELECT username, age FROM users WHERE username = 'Alice'; -- 无需回表 ``` - 避免 `SELECT *`,仅查询必要字段[^4] 2. **索引选择性优化** - **选择性公式**: $$ \text{选择性} = \frac{\text{不同值数量}}{\text{总行数}} $$ - 选择性 > 0.1 的字段适合建索引(如唯一性高的用户名)[^2] 3. **自适应哈希索引** - InnoDB 自动为高频使用的二级索引构建哈希索引,将查询复杂度降至 $O(1)$[^1] --- ### 数学分析:索引效率模型 对于 $n=10^6$ 条记录的表,B+Tree 索引(假设阶数 $m=500$)的查询复杂度为: $$ \text{层级深度} = \log_{500} 10^6 \approx 3 $$ 而全表扫描复杂度为 $O(n)$。使用二级索引时,若需回表,总复杂度为: $$ 2 \times O(\log_m n) \approx 6 \text{次磁盘 I/O} $$ 但通过覆盖索引可优化为 $O(\log_m n)$[^3][^4]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值