索引的介绍

 转自:http://www.blueidea.com/tech/program/2005/3010.asp   

    表的索引与字典中的索引非常相似。它可以极大地提高查询的速度。对一个较大的表来说,通过加索引,一个通常要花费几个小时来完成的查询只要几分钟就可以完成。(对于包含索引的数据库,SQL Sever需要一个可观的额外空间。例如,要建立一个聚簇索引,需要大约1.2倍于数据大小的空间。速度是需要付出代价的。)

聚簇索引和非聚簇索引

       假设你已经通过字典的索引找到了一个字所在的页码。一旦已经知道了页码后,你很可能随机的翻寻字典,直至找到正确的页码。这里还有一种找到页码的更有效的方法。
      首先,把字典翻到大概一半的地方,如果要找的页码比半本字典处的页码小,就翻到四分之一处,否则,就把书翻到四分之三的地方。通过这种方法,你可以继续把字典分成更小的部分,直至找到正确的页码附近。这是找到书页的非常有效的一种方法。(呵呵,到处都是这个例子,跟Hello world有一拼)SQL Sever的表索引以类似的方式工作。一个表索引由一组页组成,这些页构成了一个树形结构。根页通过指向另外两个页,把一个表的记录从逻辑上分成和两个部分。而根页所指向的两个页又分别把记录分割成更小的部分。每个页都把记录分成更小的分割,直至到达叶级页。

索引有两种类型:聚簇索引和非聚簇索引。

在聚簇索引中,索引树的叶级页包含实际的数据:记录的索引顺序与物理顺序相同。
在非聚簇索引中,叶级页指向表中的记录:记录的物理顺序与逻辑顺序没有必然的联系。

聚簇索引非常象目录表,目录表的顺序与实际的页码顺序是一致的。非聚簇索引则更象书的标准索引表,索引表中的顺序通常与实际的页码顺序是不一致的。一本书也许有多个索引。例如,它也许同时有主题索引和作者索引。同样,一个表可以有多个非聚簇索引。

通常情况下,你使用的是聚簇索引,但是你应该对两种类型索引的优缺点都有所理解。

每个表只能有一个聚簇索引,因为一个表中的记录只能以一种物理顺序存放。通常你要对一个表按照标识字段建立聚簇索引。但是,你也可以对其它类型的字段建立聚簇索引,如字符型,数值型和日期时间型字段。
从建立了聚簇索引的表中取出数据要比建立了非聚簇索引的表快。当你需要取出一定范围内的数据时,用聚簇索引也比用非聚簇索引好。例如,假设你用一个表来记录访问者在你网点上的活动。如果你想取出在一定时间段内的登录信息,你应该对这个表的DATETIME型字段建立聚簇索引。
对聚簇索引的主要限制是每个表只能建立一个聚簇索引。但是,一个表可以有不止一个非聚簇索引。实际上,对每个表你最多可以建立249个非聚簇索引。你也可以对一个表同时建立聚簇索引和非聚簇索引。
假如你不仅想根据日期,而且想根据用户名从你的网点活动日志中取数据。在这种情况下,同时建立一个聚簇索引和非聚簇索引是有效的。你可以对日期时间字段建立聚簇索引,对用户名字段建立非聚簇索引。如果你发现你需要更多的索引方式,你可以增加更多的非聚簇索引。
非聚簇索引需要大量的硬盘空间和内存。另外,虽然非聚簇索引可以提高从表中 取数据的速度,它也会降低向表中插入和更新数据的速度。每当你改变了一个建立了非聚簇索引的表中的数据时,必须同时更新索引。因此你对一个表建立非聚簇索引时要慎重考虑。如果你预计一个表需要频繁地更新数据,那么不要对它建立太多非聚簇索引。另外,如果硬盘和内存空间有限,也应该限制使用非聚簇索引的数量。

索引属性

这两种类型的索引都有两个重要属性:
你可以用两者中任一种类型同时对多个字段建立索引(复合索引);
两种类型的索引都可以指定为唯一索引。
你可以对多个字段建立一个复合索引,甚至是复合的聚簇索引。假如有一个表记录了你的网点访问者的姓和名字。如果你希望根据完整姓名从表中取数据,你需要建立一个同时对姓字段和名字字段进行的索引。这和分别对两个字段建立单独的索引是不同的。当你希望同时对不止一个字段进行查询时,你应该建立一个对多个字段的索引。如果你希望对各个字段进行分别查询,你应该对各字段建立独立的索引。
两种类型的索引都可以被指定为唯一索引。如果对一个字段建立了唯一索引,你将不能向这个字段输入重复的值。一个标识字段会自动成为唯一值字段,但你也可以对其它类型的字段建立唯一索引。假设你用一个表来保存你的网点的用户密码,你当然不希望两个用户有相同的密码。通过强制一个字段成为唯一值字段,你可以防止这种情况的发生。



本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/heromanji/archive/2007/07/07/1681617.aspx

<think>好的,我现在要介绍一下MySQL索引。首先,我需要确认用户已经了解数据库的基本概念,比如表、行、列,以及查询的基本操作。用户之前询问过脏读、幻读等问题,可能对数据库的并发控制有一定了解,但索引是另一个重要的话题。 接下来,我需要明确索引的定义和作用。索引是什么?简单来说,索引是帮助MySQL高效获取数据的数据结构,类似于书籍的目录。没有索引的话,数据库可能需要进行全表扫描,效率低下。 然后,需要介绍索引的类型。常见的索引类型包括B-Tree索引、哈希索引、全文索引等。其中,B-Tree索引是MySQL中最常用的,适用于大部分场景。哈希索引则适用于等值查询,但不支持范围查询。全文索引用于文本搜索,比如MATCH AGAINST语句。 接下来要讲索引的数据结构,比如B+树的结构和优势。B+树是一种平衡多路搜索树,适合磁盘存储,能够减少IO次数。叶子节点存储数据,并且有指针连接,方便范围查询。 然后,需要说明索引的分类。主键索引、唯一索引、普通索引、联合索引等。主键索引是唯一的,不允许NULL值;唯一索引要求列值唯一,但允许NULL;普通索引则没有这些限制。联合索引指的是多个列组合的索引,需要注意最左前缀原则。 还要提到覆盖索引的概念,即查询的列都在索引中,无需回表,提高效率。以及索引下推(Index Condition Pushdown, ICP),这是MySQL 5.6之后的优化,可以在索引层面过滤数据,减少回表次数。 然后,需要讨论索引的优点和缺点。优点包括加快查询速度,特别是WHERE、JOIN、ORDER BY等操作。缺点则是占用存储空间,降低写操作(INSERT、UPDATE、DELETE)的速度,因为索引需要维护。 接下来,可能需要讲解如何创建索引,比如使用CREATE INDEX语句,或者在创建表时指定。同时,要给出一些最佳实践,比如选择合适的列作为索引(高选择性、频繁查询的列),避免过度索引,以及如何分析索引的使用情况(EXPLAIN命令)。 还需要注意索引失效的情况,比如使用函数、类型转换、OR条件、前导通配符LIKE查询等,这些可能导致索引无法使用,需要全表扫描。 最后,可能需要对比不同存储引擎的索引实现,比如InnoDB和MyISAM的区别。InnoDB使用聚簇索引,数据存储在叶子节点,而MyISAM是非聚簇索引,数据和索引分开存储。 在思考过程中,可能会遗漏一些细节,比如全文索引的具体使用场景,或者空间索引介绍。另外,关于索引的维护,比如碎片整理、统计信息更新等,也可能需要提及。 需要确保解释清晰,避免术语混淆,比如B树和B+树的区别,或者覆盖索引和复合索引的不同。同时,结合实例说明会更易于理解,比如创建联合索引的例子,以及如何通过EXPLAIN分析查询计划。 可能还需要提到自适应哈希索引(Adaptive Hash Index)在InnoDB中的使用,这是MySQL自动为频繁访问的索引页创建的哈希索引,以加速查询。 总结时,要强调合理使用索引的重要性,根据实际查询需求设计合适的索引结构,平衡读写性能,并通过监控和优化工具持续调整。</think>### **MySQL 索引详解** #### **1. 索引的作用** 索引数据库中**快速查找数据**的数据结构,类似于书籍的目录。它通过减少磁盘 I/O 次数,显著提升查询效率,尤其是在大数据量场景下。 --- #### **2. 索引类型** | **类型** | **说明** | **适用场景** | |------------------|-------------------------------------------------------------------------|---------------------------| | **B+Tree 索引** | MySQL 默认索引结构,支持范围查询、排序、模糊匹配(如 `LIKE 'abc%'`) | 大多数场景(如主键、普通索引) | | **哈希索引** | 基于哈希表,仅支持等值查询(`=`),不支持排序或范围查询 | 内存表(如 MEMORY 引擎) | | **全文索引** | 对文本内容分词索引,支持自然语言搜索(`MATCH ... AGAINST`) | 大文本字段的搜索(如文章、日志) | | **空间索引** | 支持地理空间数据类型(如 `GEOMETRY`) | GIS 系统、地理位置查询 | --- #### **3. 索引分类** | **分类** | **特点** | |------------------|-------------------------------------------------------------------------| | **主键索引** | 唯一标识每行,不允许 `NULL`,表只能有一个主键索引(`PRIMARY KEY`) | | **唯一索引** | 确保列值唯一,允许 `NULL`(但只能有一个 `NULL`),可存在多个唯一索引(`UNIQUE`) | | **普通索引** | 无唯一性约束,仅加速查询(`INDEX` 或 `KEY`) | | **联合索引** | 多列组合的索引,需遵循**最左前缀原则**(如 `INDEX (a, b, c)`) | --- #### **4. B+Tree 索引结构** - **特点**: - 平衡多叉树,所有数据存储在叶子节点,非叶子节点仅存储键值。 - 叶子节点通过指针连接,支持高效的范围查询(如 `WHERE id > 100`)。 - **InnoDB 的聚簇索引**: - 主键索引的叶子节点直接存储行数据,因此**主键查询极快**。 - 若未定义主键,InnoDB 会自动生成隐藏的聚簇索引。 --- #### **5. 索引优化策略** - **覆盖索引**:查询的字段全部包含在索引中,无需回表(`EXPLAIN` 的 `Extra` 列显示 `Using index`)。 ```sql -- 假设有联合索引 (name, age) SELECT age FROM users WHERE name = '张三'; -- 覆盖索引 ``` - **索引下推(ICP)**:在存储引擎层过滤数据,减少回表次数(MySQL 5.6+ 支持)。 - **最左前缀原则**:联合索引按列顺序生效,如 `(a, b, c)` 支持 `a`, `a AND b`, `a AND b AND c`,但不支持 `b` 或 `c` 单独使用。 - **前缀索引**:对长文本字段(如 `VARCHAR(200)`)的前 N 个字符建索引,节省空间。 ```sql CREATE INDEX idx_email_prefix ON users(email(10)); -- 取前10个字符 ``` --- #### **6. 索引失效场景** 以下操作可能导致索引失效,触发全表扫描: - **对索引列使用函数或计算**: ```sql SELECT * FROM users WHERE YEAR(create_time) = 2023; -- 失效 ``` - **类型转换**(如字符串列用数字查询): ```sql SELECT * FROM users WHERE id = '100'; -- 若 id 是 INT,会隐式转换导致失效 ``` - **前导通配符 `LIKE`**: ```sql SELECT * FROM users WHERE name LIKE '%abc%'; -- 无法使用索引 ``` - **OR 条件包含非索引列**: ```sql SELECT * FROM users WHERE age = 20 OR address = '北京'; -- 若 address 无索引,整体失效 ``` --- #### **7. 索引管理** - **创建索引**: ```sql CREATE INDEX idx_name ON users(name); -- 普通索引 ALTER TABLE users ADD UNIQUE (email); -- 唯一索引 ``` - **删除索引**: ```sql DROP INDEX idx_name ON users; ``` - **查看索引**: ```sql SHOW INDEX FROM users; ``` --- #### **8. 索引的优缺点** | **优点** | **缺点** | |----------------------------|-----------------------------| | 加速查询(WHERE、JOIN、ORDER BY) | 占用额外磁盘空间 | | 减少服务器排序和临时表的使用 | 降低写操作性能(需维护索引) | | 加速表连接操作 | 不合理的索引设计会拖慢查询 | --- #### **9. 最佳实践** 1. **选择性高的列建索引**:区分度高的列(如用户 ID)比性别更适合索引。 2. **避免冗余索引**:联合索引 `(a, b)` 可替代单独的 `a` 索引。 3. **监控索引使用**:通过 `SHOW INDEX_STATISTICS` 或 `INFORMATION_SCHEMA` 分析索引利用率。 4. **定期优化表**:重建索引减少碎片(`OPTIMIZE TABLE users`)。 --- #### **10. 示例:EXPLAIN 分析查询** ```sql EXPLAIN SELECT * FROM users WHERE name = 'Alice' AND age > 20; ``` - **结果字段**: - `type`:访问类型(`ref` 表示索引查找,`ALL` 表示全表扫描)。 - `key`:实际使用的索引。 - `rows`:预估扫描行数。 - `Extra`:额外信息(如 `Using where`, `Using index`)。 --- **总结**:索引数据库性能优化的核心手段之一,需根据业务查询模式合理设计,兼顾查询效率与写入成本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值