数据库索引设置及命中

本文探讨了数据库索引的不同类型,包括主键、唯一、普通、全文和空间索引。重点在于联合索引的命中问题,通过多个SQL查询示例分析了不同条件组合下索引的使用情况,如字段类型匹配、查询顺序等对索引命中率的影响。

一、数据库索引的类型

  1. 主键索引

  2. 唯一索引

  3. 普通索引

  4. 全文索引

  5. 空间索引

二、索引命中

  1. 主要讨论下联合索引命中的问题

数据准备:假设我们有如下图所示的数据库表study_goods_size,并且我们设置goods_id和size_id为联合索引,即:idx_goods_size。

CREATE TABLE `study_goods_size` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `goods_id` varchar(50) NOT NULL DEFAULT '' COMMENT '商品Id',
  `goods_name` varchar(50) NOT NULL DEFAULT '' COMMENT '商品名称',
  `size_id` varchar(100) NOT NULL DEFAULT '' COMMENT '尺码Id',
  `size_name` varchar(100) NOT NULL DEFAULT '' COMMENT '尺码名称',
  PRIMARY KEY (`id`),
  KEY `idx_goods_size` (`goods_id`,`size_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1;

联合索引命中总结
场景SQL是否命中索引其他
场景1explain select * from study_goods_size where goods_id = 123 and size_id = 234;   NO 
场景2explain select * from study_goods_size where goods_id = '123' and size_id = 234;YES 
场景3explain select * from study_goods_size  where goods_id = 123 and size_id = '234';NO 
场景4explain select * from study_goods_size  where goods_id = '123' and size_id = '234';YES 
场景5explain select * from study_goods_size  where size_id = '234' and goods_id = '123' ;YES 
场景6explain select * from study_goods_size  where goods_id = '123';YES 
场景7explain select * from study_goods_size  where goods_id = 123;NO 
场景8explain select size_id from study_goods_size  where goods_id = 123;YES 
场景9explain select size_id from study_goods_size  where goods_id = '123';YES 
场景10explain select size_id from study_goods_size;YES 

 

  • 情况一:explain select * from study_goods_size where goods_id = 123 and size_id = 234;   

结果:不能命中索引,实测情况如下图所示:

  • 情况二:explain select * from study_goods_size  where goods_id = '123' and size_id = 234;

  • 情况三:explain select * from study_goods_size  where goods_id = 123 and size_id = '234';

  • 情况四:explain select * from study_goods_size  where goods_id = '123' and size_id = '234';

  • 情况五:explain select * from study_goods_size  where size_id = '234' and goods_id = '123' ;

  • 情况六:explain select * from study_goods_size  where goods_id = '123';

  • 情况七:explain select * from study_goods_size  where goods_id = 123;

  • 情况八:explain select size_id from study_goods_size  where goods_id = 123;

  • 情况九:explain select size_id from study_goods_size  where goods_id = '123';

  • 情况十:explain select size_id from study_goods_size;

【参考资料】

  1. 索引类型参考:https://www.cnblogs.com/zhenghengbin/p/11908268.html
  2. 如何检测MySql是否命中索引:https://blog.youkuaiyun.com/ba_qi/article/details/88799093
<think>嗯,用户这次明确想了解提高数据库索引命中率的方法,而且提供了四个相关引用。从引用内容看,涉及索引分析工具、数据类型匹配、索引选择性、索引维护等关键点。 用户可能是个正在优化数据库性能的开发人员或DBA,语气比较急切,需要实用方案。值得注意的是,ta特意强调引用仅供参考,说明更想要系统化的方法论而非零散技巧。 上次系统指令要求用中文回复并规范数学公式,不过当前问题不涉及数学表达,重点在技术要点整合。引用[3]特别有价值,举了数据类型不匹配导致索引失效的典型案例,这个在实际开发中容易被忽视。 需要把零散的引用内容结构化:首先应该是索引创建阶段的注意事项(如选择性评估),然后是查询编写规范(避免隐式转换),最后是维护策略(定期重建索引)。引用[2]提到的SQL Server Profiler工具和引用[1]的ANALYZE TABLE命令可以分别作为两个数据库平台的代表方案。 考虑到用户没指定数据库类型,回复要兼顾通用性和平台差异。比如MySQL的全文索引限制(引用[4])属于特殊场景,应该单独说明。数值型字段错误使用字符串查询的例子很典型,必须包含在"避免索引失效"部分。 最后生成的问题要引导用户深入:索引命中率监控、不同数据库的优化工具差异、复合索引设计原则都是自然延伸方向。尤其复合索引涉及字段顺序选择,对命中率影响很大,值得单独探讨。 </think>以下是提高数据库索引命中率的核心方法及实施步骤,综合了最佳实践和引用内容: --- ### **一、索引创建优化** 1. **选择高区分度列** - 优先选择**重复率低于15%**的列建索引(如手机号、身份证号),避免对性别等低区分度列单独索引。 - **复合索引设计**:按区分度降序排列字段(如 `INDEX(城市, 性别)` 优于 `INDEX(性别, 城市)`)[^3]。 2. **避免冗余索引** - 定期检查重复索引(如已存在 `INDEX(a,b)` 时,`INDEX(a)` 可能冗余),使用 `SHOW INDEX FROM 表名` 分析。 --- ### **二、查询语句优化** 1. **严格匹配数据类型** ```sql -- 错误示例(字符串 vs 数值) SELECT * FROM users WHERE age = '20'; -- 索引失效 -- 正确写法 SELECT * FROM users WHERE age = 20; [^3] ``` 2. **禁止索引列操作** ```sql -- 错误示例(函数操作) SELECT * FROM orders WHERE YEAR(order_date) = 2023; -- 索引失效 -- 正确写法 SELECT * FROM orders WHERE order_date BETWEEN '2023-01-01' AND '2023-12-31'; ``` 3. **减少 `SELECT *`** 仅查询必要字段,降低I/O开销。 --- ### **三、索引维护策略** | **操作** | **命令示例** | **频率** | |-------------------------|----------------------------|----------------| | 索引统计分析 | `ANALYZE TABLE users;` | 每周/数据变更后[^1] | | 索引碎片整理 | `OPTIMIZE TABLE users;` | 每月 | | 索引重建 | `ALTER TABLE users REBUILD INDEX idx_name;` | 索引失效时[^3] | --- ### **四、高级技巧** 1. **覆盖索引** 确保查询字段均在索引中: ```sql -- 建立覆盖索引 CREATE INDEX idx_cover ON users(age, name); -- 查询命中索引无需回表 SELECT age, name FROM users WHERE age = 30; [^4] ``` 2. **全文索引优化** - MySQL InnoDB 需5.6+版本支持中文全文索引 - 使用分词插件(如ngram)或转存英文关键词表[^4]。 --- ### **五、监控工具** 1. **MySQL** - 执行 `EXPLAIN` 分析查询计划 - 监控 `Handler_read%` 状态变量 2. **SQL Server** - 使用 **SQL Server Profiler** 捕获低效查询 - 通过 **Extended Events** 分析索引命中率[^2]。 --- > **关键总结**:索引命中率取决于**合理设计**(20%)+ **规范查询**(50%)+ **定期维护**(30%)。避免索引失效的六大陷阱:隐式类型转换、列运算、低选择性、`OR`滥用、最左前缀缺失、索引损坏。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值