MySQL索引完全手册:真实业务图文讲解17种索引运用技巧(必须收藏)

10 篇文章 0 订阅
2 篇文章 0 订阅

在这里插入图片描述

MySQL索引是数据库中用于提高数据检索效率的重要技术。它通过在数据表列上创建索引结构,如B+Tree、Hash索引等,加速查询速度。索引类型包括主键索引、唯一索引、普通索引、全文索引、空间索引等,各适用于不同的查询场景。合理设计索引可以显著提升数据库性能,但过多索引也会导致维护成本增加和写操作变慢。索引优化需考虑查询模式、数据量和存储引擎特性。

肖哥弹架构 跟大家“弹弹” 代码设计技巧,需要代码关注

欢迎 点赞,关注,评论。

关注公号Solomon肖哥弹架构获取更多精彩内容

历史热点文章

1. B+Tree索引

在这里插入图片描述

B+Tree索引是MySQL中最常用的索引类型,适用于快速定位、顺序访问和范围查询。

构建原理:基于B+Tree数据结构,节点包含数据键值和子节点指针,叶子节点包含数据记录或指针。

设计目标:快速数据访问,支持顺序和范围查询。

业务场景:电商平台商品信息检索。

  • 场景表结构
CREATE TABLE products (
    product_id INT NOT NULL AUTO_INCREMENT COMMENT '商品ID',
    product_name VARCHAR(255) NOT NULL COMMENT '商品名称',
    price DECIMAL(10, 2) NOT NULL COMMENT '商品价格',
    create_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    PRIMARY KEY (product_id),
    INDEX idx_product_name (product_name) COMMENT '商品名称索引'
) COMMENT '商品信息表';
  • 场景索引代码
-- 创建商品名称的B+Tree索引
CREATE INDEX idx_product_name ON products (product_name);
  • 索引不起作用条件
-- 索引列参与了函数操作
SELECT * FROM products WHERE LOWER(product_name) = 'iphone'; -- 索引不起作用,因为使用了函数LOWER

-- 索引列使用了范围查询
SELECT * FROM products WHERE product_name > 'iphone'; -- 索引部分起作用,只能用于>操作,不能用于全名匹配

-- 查询条件中使用了不同的列顺序
SELECT * FROM products WHERE price = 1299; -- 索引不起作用,因为没有为price列创建索引

2. Hash索引

在这里插入图片描述

Hash索引通过哈希函数快速定位键值,适合等值查询,不适合范围查询

构建原理:基于哈希表,快速定位键值。

设计目标:快速等值查询。

业务场景:用户登录系统,快速验证用户名或邮箱。

  • 场景表结构
CREATE TABLE users (
    user_id INT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
    username VARCHAR(255) NOT NULL COMMENT '用户名',
    email VARCHAR(255) NOT NULL COMMENT '用户邮箱',
    UNIQUE INDEX idx_email (email) COMMENT '邮箱唯一索引'
) COMMENT '用户信息表';
  • 场景索引代码
-- MySQL的Memory引擎自动将所有唯一索引和主键索引创建为Hash索引,无需手动创建
  • 索引不起作用条件
-- 索引列参与了范围查询
SELECT * FROM users WHERE email > 'user@example.com'; -- 索引不起作用,Hash索引不支持范围查询

-- 索引列使用了LIKE操作且以通配符开头
SELECT * FROM users WHERE email LIKE '%example.com'; -- 索引不起作用,Hash索引不支持LIKE查询

3. Full-Text索引

在这里插入图片描述

全文索引用于文本字段的高效搜索,支持复杂的查询语句。

构建原理:基于倒排索引,用于全文检索。

设计目标:优化全文搜索效率。

业务场景:文章内容搜索。

  • 场景表结构
CREATE TABLE articles (
    article_id INT NOT NULL AUTO_INCREMENT COMMENT '文章ID',
    title VARCHAR(255) NOT NULL COMMENT '文章标题',
    content TEXT NOT NULL COMMENT '文章内容',
    FULLTEXT(idx_title_content) (title, content) COMMENT '标题和内容的全文索引'
) COMMENT '文章信息表';
  • 场景索引代码
-- 创建全文索引
ALTER TABLE articles ADD FULLTEXT(idx_title_content) (title, content);
  • 索引不起作用条件
-- 查询中使用了全文索引不支持的列
SELECT * FROM articles WHERE article_id = 1; -- 索引不起作用,因为article_id没有包含在全文索引中

-- 查询中使用了全文索引不支持的操作符
SELECT * FROM articles WHERE title LIKE '%keyword'; -- 索引不起作用,全文索引不支持LIKE操作符

4. 主键索引(PRIMARY KEY)

在这里插入图片描述

主键索引确保数据表中每条记录的唯一性,通常是B+Tree索引

构建原理:自动在主键上创建的B+Tree索引。

设计目标:唯一标识表中的每一行。

业务场景:用户账户信息管理。

  • 场景表结构
CREATE TABLE user_accounts (
    account_id INT NOT NULL AUTO_INCREMENT COMMENT '账户ID',
    account_name VARCHAR(255) NOT NULL COMMENT '账户名称',
    PRIMARY KEY (account_id) COMMENT '账户ID主键索引'
) COMMENT '用户账户表';
  • 场景索引代码
-- 主键索引在定义主键时自动创建,无需额外SQL代码
  • 索引不起作用条件
-- 查询使用了非主键的其他列
SELECT * FROM user_accounts WHERE account_name = '用户名'; -- 索引不起作用,因为account_name不是主键

5. 唯一索引(UNIQUE)

在这里插入图片描述

唯一索引保证键值的唯一性,允许有空值

构建原理:基于B+Tree,不允许重复键值。

设计目标:保证列值的唯一性。

业务场景:确保用户邮箱地址的唯一性。

  • 场景表结构
CREATE TABLE user_emails (
    email_id INT NOT NULL AUTO_INCREMENT COMMENT '邮箱ID',
    user_id INT NOT NULL COMMENT '用户ID',
    email VARCHAR(255) NOT NULL COMMENT '用户邮箱',
    UNIQUE INDEX idx_email (email) COMMENT '邮箱唯一索引'
) COMMENT '用户邮箱表';
  • 场景索引代码
-- 在创建唯一索引
ALTER TABLE user_emails ADD UNIQUE(idx_email) (email);
  • 索引不起作用条件
-- 插入重复的邮箱地址
INSERT INTO user_emails (user_id, email) VALUES (1, 'existing_email@example.com'); -- 索引阻止插入,因为邮箱已存在

-- 使用了非唯一索引的列进行查询
SELECT * FROM user_emails WHERE user_id = 1; -- 索引不起作用,因为user_id没有定义唯一索引

6. 普通索引(INDEX)

在这里插入图片描述

普通索引用于加速查询,没有唯一性约束。

构建原理:基于B+Tree,允许键值重复。

设计目标:提高普通查询的效率。

业务场景:订单状态查询。

  • 场景表结构
CREATE TABLE orders (
    order_id INT NOT NULL AUTO_INCREMENT COMMENT '订单ID',
    order_status VARCHAR(50) NOT NULL COMMENT '订单状态',
    INDEX idx_order_status (order_status) COMMENT '订单状态索引'
) COMMENT '订单信息表';
  • 场景索引代码
-- 创建订单状态的普通索引
ALTER TABLE orders ADD INDEX idx_order_status (order_status);
  • 索引不起作用条件
-- 使用了索引列上的非等值查询
SELECT * FROM orders WHERE order_status LIKE '%完成'; -- 索引不起作用,因为使用了LIKE操作

-- 查询中使用了非索引列的排序
SELECT * FROM orders ORDER BY order_id; -- 索引不起作用,因为排序列不是order_status

7. 联合索引(Composite Index)

在这里插入图片描述

联合索引跨多个列,提高多条件查询效率。

构建原理:跨多个列的B+Tree索引。

设计目标:提高多列查询的效率。

业务场景:按日期和用户ID查询交易记录。

  • 场景表结构
CREATE TABLE transactions (
    transaction_id INT NOT NULL AUTO_INCREMENT COMMENT '交易ID',
    user_id INT NOT NULL COMMENT '用户ID',
    transaction_date DATE NOT NULL COMMENT '交易日期',
    amount DECIMAL(10, 2) NOT NULL COMMENT '交易金额',
    INDEX idx_user_date (user_id, transaction_date) COMMENT '用户ID和交易日期的联合索引'
) COMMENT '交易记录表';
  • 场景索引代码
-- 创建用户ID和交易日期的联合索引
ALTER TABLE transactions ADD INDEX idx_user_date (user_id, transaction_date);
  • 索引不起作用条件
-- 查询没有使用最左前缀
SELECT * FROM transactions WHERE transaction_date = '2024-08-01'; -- 索引不起作用,因为没有包括user_id

-- 查询中包含了索引列之外的条件
SELECT * FROM transactions WHERE user_id = 1 AND amount > 100; -- 索引部分起作用,amount条件未用到索引

8. 空间索引(Spatial Index)

在这里插入图片描述

空间索引用于地理空间数据,优化区域查询

构建原理:基于R-Tree,用于空间数据索引。

设计目标:优化空间数据查询效率。

业务场景:地理信息系统中地点检索。

  • 场景表结构
CREATE TABLE geospatial_data (
    geo_id INT NOT NULL AUTO_INCREMENT COMMENT '地理空间数据ID',
    location POINT NOT NULL COMMENT '地理位置',
    INDEX spatial_idx_location (location) COMMENT '地理位置的空间索引'
) COMMENT '地理空间数据表';
  • 场景索引代码
-- 创建地理位置的空间索引 
ALTER TABLE geospatial_data ADD SPATIAL spatial_idx_location (location);
  • 索引不起作用条件
-- 查询中使用了非空间索引列 
SELECT * FROM geospatial_data WHERE geo_id = 1; 
-- 索引不起作用,因为条件中没有使用location列 
-- 查询中使用了空间索引不支持的操作 
SELECT * FROM geospatial_data WHERE location = POINT(121.47, 31.24); 
-- 索引可能不起作用,因为使用了直接比较

9. 前缀索引

在这里插入图片描述

前缀索引只对字符串的一部分创建索引,节省空间。

构建原理:对字符串列的前缀部分创建索引,以减少索引占用的空间。

设计目标:在列前缀足够唯一的情况下,优化查询性能,节省存储空间。

业务场景:存储大量URL或长文本数据,需要快速检索。

  • 场景表结构
CREATE TABLE logs (
    log_id INT NOT NULL AUTO_INCREMENT COMMENT '日志ID',
    message TEXT NOT NULL COMMENT '日志信息',
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
    INDEX idx_message_prefix (message(255)) COMMENT '日志信息前缀索引'
) COMMENT '日志信息表';
  • 场景索引代码
-- 创建日志信息的前缀索引
ALTER TABLE logs ADD INDEX idx_message_prefix (message(255));
  • 索引不起作用条件
-- 查询条件包含不在前缀索引内的部分
SELECT * FROM logs WHERE message LIKE '部分信息%'; -- 索引不起作用,因为%在后缀

-- 查询使用了前缀索引列的范围查询
SELECT * FROM logs WHERE message > '某个值'; -- 索引不起作用,因为使用了范围查询

10. 聚簇索引(Clustered Index)

在这里插入图片描述

聚簇索引的叶子节点直接包含数据行,提高范围查询效率。

构建原理:行数据存储在B+Tree的叶子节点,非叶子节点包含键值和指向子节点的指针。

设计目标:数据物理存储顺序与索引顺序一致,提高范围查询效率。

业务场景:按主键查询或插入数据,如用户ID。

  • 场景表结构
CREATE TABLE customers (
    customer_id INT NOT NULL AUTO_INCREMENT COMMENT '客户ID',
    first_name VARCHAR(50) NOT NULL COMMENT '名字',
    last_name VARCHAR(50) NOT NULL COMMENT '姓氏',
    birth_date DATE NOT NULL COMMENT '出生日期',
    PRIMARY KEY (customer_id) COMMENT '客户ID聚簇索引'
) COMMENT '客户信息表';
  • 场景索引代码
-- 主键自动创建聚簇索引,无需额外SQL代码
  • 索引不起作用条件
-- 没有使用主键查询
SELECT * FROM customers WHERE first_name = 'John'; -- 索引可能部分起作用,但不是聚簇索引的优势

-- 使用了非索引列的范围查询
SELECT * FROM customers WHERE birth_date > '2000-01-01'; -- 索引不起作用,因为没有使用聚簇索引列

11. 非聚簇索引(Non-clustered Index)

在这里插入图片描述

非聚簇索引的叶子节点包含指向数据行的指针。

构建原理:索引和数据物理存储分离,索引包含键值和指向数据行的指针。

设计目标:提供快速的索引查找,然后通过指针回表查询数据。

业务场景:查询非主键列,如商品分类。

  • 场景表结构
CREATE TABLE product_categories (
    category_id INT NOT NULL AUTO_INCREMENT COMMENT '分类ID',
    category_name VARCHAR(100) NOT NULL COMMENT '分类名称',
    description TEXT COMMENT '分类描述',
    PRIMARY KEY (category_id),
    INDEX idx_category_name (category_name) COMMENT '分类名称索引'
) COMMENT '商品分类表';
  • 场景索引代码
-- 创建非聚簇索引
ALTER TABLE product_categories ADD INDEX idx_category_name (category_name);
  • 索引不起作用条件
-- 查询使用了索引列的范围查询
SELECT * FROM product_categories WHERE category_name > 'Books'; -- 索引不起作用

-- 查询中包含了索引列之外的排序
SELECT * FROM product_categories ORDER BY description; -- 索引不起作用

12. 自适应哈希索引

在这里插入图片描述

InnoDB存储引擎根据查询模式自动创建哈希索引以加速查询

构建原理:InnoDB自动在热点B+Tree索引上创建Hash索引,以加速等值查询。

设计目标:自动优化频繁等值查询的性能。

业务场景:频繁查询的列,如用户表的用户名。

  • 场景表结构
CREATE TABLE users (
    user_id INT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
    username VARCHAR(255) NOT NULL COMMENT '用户名',
    INDEX idx_username (username) COMMENT '用户名索引'
) COMMENT '用户信息表';
  • 场景索引代码
-- InnoDB自动创建自适应哈希索引,无需额外SQL代码
  • 索引不起作用条件
-- 查询使用了非等值查询
SELECT * FROM users WHERE username LIKE 'user%'; -- 索引不起作用

-- 查询使用了索引列的范围查询
SELECT * FROM users WHERE username > 'user1'; -- 索引不起作用

13. 覆盖索引(Index-Only Scan)

在这里插入图片描述

覆盖索引包含查询所需的所有字段,查询无需访问数据行。

构建原理:索引包含查询所需的所有列,查询可以直接从索引中获取数据。

设计目标:避免访问主表数据,直接从索引中读取所需数据。

业务场景:查询只需要索引列,如获取商品名称和价格。

  • 场景表结构
CREATE TABLE products (
    product_id INT NOT NULL AUTO_INCREMENT COMMENT '商品ID',
    product_name VARCHAR(255) NOT NULL COMMENT '商品名称',
    price DECIMAL(10, 2) NOT NULL COMMENT '商品价格',
    INDEX idx_cover_product_name_price (product_name, price) COMMENT '覆盖索引'
) COMMENT '商品信息表';
  • 场景索引代码
-- 创建覆盖索引
ALTER TABLE products ADD INDEX idx_cover_product_name_price (product_name, price);
  • 索引不起作用条件
-- 查询需要访问非索引列
SELECT * FROM products WHERE product_name = 'iPhone'; -- 索引不起作用,因为查询了非索引列product_id

-- 查询使用了索引不支持的操作符
SELECT * FROM products WHERE product_name LIKE '%Phone'; -- 索引不起作用

14. 部分索引(Partial Index)

在这里插入图片描述

部分索引只对满足特定条件的记录创建索引。

构建原理:基于表中满足特定条件的行创建索引。

设计目标:优化特定条件下的查询性能。

业务场景:只对活跃用户创建索引,查询活跃用户信息。

  • 场景表结构
CREATE TABLE users (
    user_id INT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
    is_active BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否活跃',
    INDEX idx_active_users (user_id) WHERE is_active COMMENT '活跃用户索引'
) COMMENT '用户信息表';
  • 场景索引代码
-- 创建部分索引
ALTER TABLE users ADD INDEX idx_active_users (user_id) WHERE is_active;
  • 索引不起作用条件
-- 查询包含了非活跃用户
SELECT * FROM users WHERE is_active = FALSE; -- 索引不起作用

-- 查询没有使用索引列
SELECT * FROM users WHERE user_id = 1; -- 索引不起作用,因为is_active条件未满足

15. 函数索引(Functional Index)

在这里插入图片描述

函数索引基于列值的函数结果创建,优化特定函数查询。

构建原理:基于列值的函数结果创建索引。

设计目标:优化基于列值函数结果的查询。

业务场景:基于用户邮箱的特定格式处理后的查询。

  • 场景表结构
CREATE TABLE users (
    user_id INT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
    email VARCHAR(255) NOT NULL COMMENT '用户邮箱',
    INDEX idx_func_email (LOWER(email)) COMMENT '基于函数的邮箱索引'
) COMMENT '用户信息表';
  • 场景索引代码
-- 创建函数索引
ALTER TABLE users ADD INDEX idx_func_email (LOWER(email));
  • 索引不起作用条件
-- 查询使用了不同的函数或未应用函数
SELECT * FROM users WHERE email = 'USER@example.com'; -- 索引不起作用,因为未转换为小写

-- 查询使用了索引列的范围查询
SELECT * FROM users WHERE LOWER(email) > 'user@example.com'; -- 索引不起作用

16. 索引分区

在这里插入图片描述

索引分区将大型索引分割为多个分区,提高索引管理查询效率。

构建原理:将大型索引分割成多个更小的分区,以提高索引的管理和查询效率。

设计目标:优化大型表的索引性能。

业务场景:大型订单数据表,按年份分区索引。

  • 场景表结构
CREATE TABLE orders (
    order_id INT NOT NULL AUTO_INCREMENT COMMENT '订单ID',
    order_date DATE NOT NULL COMMENT '订单日期',
    INDEX idx_order_date (order_date) COMMENT '订单日期索引'
) COMMENT '订单信息表';
  • 场景索引代码
-- 索引分区通常由存储引擎自动管理,但可以通过分区表来实现

-- 例如,创建按年份分区的表
CREATE TABLE orders_partitioned (
    order_id INT NOT NULL AUTO_INCREMENT COMMENT '订单ID',
    order_date DATE NOT NULL COMMENT '订单日期',
    PRIMARY KEY (order_id, order_date) COMMENT '订单ID和订单日期的组合索引'
    ) PARTITION BY RANGE (YEAR(order_date)) (
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION p2024 VALUES LESS THAN (2025)
-- 其他分区...
);
  • 索引不起作用条件
-- 查询跨越多个分区
SELECT * FROM orders_partitioned WHERE order_date >= '2023-01-01' AND order_date < '2025-01-01'; -- 索引可能部分起作用

-- 查询没有使用分区键
SELECT * FROM orders_partitioned WHERE order_id = 100; -- 索引不起作用,因为条件中没有使用order_date

17. 外键索引(Foreign Key Index)

在这里插入图片描述

外键索引确保数据的引用完整性,通常由外键约束自动创建。

构建原理:基于外键列创建索引,保证数据的引用完整性。

设计目标:确保外键列的唯一性或唯一性组合,加速外键关联查询。

业务场景:订单表和用户表之间的外键关系。

  • 场景表结构
CREATE TABLE customers (
    customer_id INT NOT NULL AUTO_INCREMENT COMMENT '客户ID',
    PRIMARY KEY (customer_id) COMMENT '客户ID主键索引'
) COMMENT '客户信息表';

CREATE TABLE orders (
    order_id INT NOT NULL AUTO_INCREMENT COMMENT '订单ID',
    customer_id INT NOT NULL COMMENT '客户ID',
    INDEX fk_customer_id (customer_id) COMMENT '外键索引',
    FOREIGN KEY (customer_id) REFERENCES customers(customer_id) COMMENT '外键约束'
) COMMENT '订单信息表';
  • 场景索引代码
-- 外键自动创建索引,无需额外SQL代码
  • 索引不起作用条件
-- 查询没有使用外键列
SELECT * FROM orders WHERE order_id = 1; -- 索引不起作用,因为条件中没有使用customer_id

-- 插入违反外键约束的数据
INSERT INTO orders (customer_id) VALUES (999); -- 索引阻止插入,因为没有对应的customer_id
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Solomon_肖哥弹架构

你的欣赏就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值