数据库索引设计

数据库索引设计

一、核心指导思想:目标与权衡

索引设计的终极目标是:以最小的存储和维护成本,最大化地提升查询性能。

这意味着所有具体原则都服务于两个核心KPI:

  1. 查询更快

  2. 空间更小

任何索引设计都需在 "查询性能提升""写入开销及存储成本" 之间进行权衡。"没有最好的索引,只有最适合的索引。"


二、索引设计的核心原则(做什么与不做什么)
原则一:为查询而建,而非为表而建
  • 必须建索引的列:

    • WHERE 子句中的高频过滤条件列。

    • JOIN ... ON 子句中的关联列。

    • ORDER BY / GROUP BY 子句中的排序列。

  • 推论: 不出现在查询条件中的列,创建索引通常是无意义的。

原则二:追求高区分度(高基数)
  • 优先选择区分度高的列。 区分度指该列不同值的数量占表总行数的比例。比例越高,索引筛选效果越好。

    • 优秀选择: 用户ID、手机号、订单号(接近唯一)。

    • 较差选择: 性别、状态标志(如is_deleted)、类型(区分度低,可能只返回大量数据)。

  • 例外: 即使区分度低,但如果该列常与其他高区分度列组成联合索引,且遵循最左前缀原则,则仍有价值。

原则三:利用联合索引,避免冗余索引
  • 扩展而非新建: 如果已有索引 (a),业务又需要查 (a, b),应优先考虑将索引扩展为 (a, b),而非新建独立索引 (b)

  • 最左前缀匹配: 联合索引 (a, b, c) 等效于建立了 (a)(a, b)(a, b, c) 三个索引。设计时应根据查询模式,将最常用、筛选力最强的列放在最左边

原则四:保持索引的"轻量"
  • 使用短索引(前缀索引): 对长字符串列(如VARCHAR(255)),可以只对前N个字符建立索引。N的选取应能保证足够高的前缀区分度。这是以微小的查询精度损失换取显著的存储空间和性能提升的经典权衡。

    复制代码
    -- 仅对`url`列的前50个字符建立索引
    CREATE INDEX idx_url_prefix ON table_name (url(50));
  • 选择简洁的数据类型: 整型索引效率远高于字符串。主键应优先使用自增整型 (如BIGINT),避免使用冗长的UUID(除非分布式场景必需)。

原则五:警惕索引的负面影响
  • 避免过度索引: 每个额外索引都会增加INSERTUPDATEDELETE操作的成本(需要维护索引树),并占用磁盘/内存空间。定期审查并删除未使用或冗余的索引。

  • 更新频繁的列需谨慎: 对于值频繁变更的列,维护索引的代价可能超过其查询收益。

  • 外键列必须建索引: 用于维护引用完整性和加速关联查询。

原则六:理解并利用索引覆盖
  • 设计索引时,可考虑让索引直接包含 查询所需的所有列(SELECT的列)。这样查询可以完全在索引中完成,避免回表,性能提升极大。

    复制代码
    -- 假设有联合索引 (user_id, create_time)
    SELECT user_id, create_time FROM orders WHERE user_id = 123;
    -- 此查询可被索引完全覆盖,效率极高
原则七:知道何时不应建索引
  • 表数据量极小时(如配置表),全表扫描更快,索引反而成为负担。

  • 查询中极少被引用的列。

  • 存储大文本(TEXT/BLOB)或超长字段的列(应使用前缀索引或全文索引)。

相关推荐
HAWK eoni6 分钟前
Mysql 驱动程序
数据库·mysql
二哈赛车手18 分钟前
新人笔记---实现简易版的rag的bm25检索(利用ES),以及RAG上传时的ES与向量数据库双写
java·数据库·笔记·spring·elasticsearch·ai
何中应28 分钟前
CentOS 7安装、卸载MySQL数据库(二)
数据库·mysql·centos
KmSH8umpK38 分钟前
Redis分布式锁从原生手写到Redisson高阶落地,附线上死锁复盘优化方案进阶第六篇
数据库·redis·分布式
梁萌1 小时前
mysql使用事件做日志表数据转移
数据库·mysql
lThE ANDE1 小时前
MySQL中的TRUNCATE TABLE命令
数据库·mysql
kexnjdcncnxjs1 小时前
Redis如何记录每一次写操作_开启AOF持久化机制实现命令级追加记录
jvm·数据库·python
逸Y 仙X2 小时前
文章十九: ElasticSearch Full Text 全文本查询
java·大数据·数据库·elasticsearch·搜索引擎·全文检索
STER labo2 小时前
mysql配置环境变量——(‘mysql‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件解决办法)
数据库·mysql·adb
微软技术分享2 小时前
本地部署千问 2.5-1.5B-GGUF + LangChain 封装学习
数据库·学习·langchain