0

0

[慢查优化]建索引时注意字段选择性 & 范围查询注意组合_MySQL

php中文网

php中文网

发布时间:2016-06-01 13:29:45

|

1391人浏览过

|

来源于php中文网

原创

bitsCN.com 写在前面的话:

  1. 之前曾说过“不要求每个人一定理解 联表查询(join/left join/inner join等)时的mysql运算过程”,但对于字段选择性差意味着什么,组合索引字段顺序意味着什么,要求每个人必须了解;
  2. 重复上一次的话:把mysql客户端(如SQLyog,如HeidiSQL)放在桌面上,时不时拿出来 explain 一把,这是一种美德!
  • 确保亲手查过SQL的执行计划,一定要注意看执行计划里的 possible_keys、key和rows这三个值,让影响行数尽量少,保证使用到正确的索引,减少不必要的Using temporary/Using filesort;
  • 不要在选择性非常差的字段上建索引,原因参见优化策略A;
  • 查询条件里出现范围查询(如A>7,A in (2,3))时,要警惕,不要建了组合索引却完全用不上,原因参见优化策略B;

  • 我们先回顾一下字段选择性的基础知识。

    ——字段选择性的基础知识——

    引子:什么字段都可以建索引吗?

    如下表所示,sort 字段的选择性非常差,你可以执行 show index from ads 命令可以看到 sort 的 Cardinality(散列程度)只有 9,这种字段上本不应该建索引:

    Table

    Non_unique

    Key_name

    Seq_in_index

    Column_name

    Collation

    Cardinality

    Sub_part

    Packed

    Null

    Index_type

    Comment

    ads

    1

    sort

    1

    sort

    A

    9

    /N

    /N

     

    BTREE

     

     优化策略A:字段选择性

    • 选择性较低索引 可能带来的性能问题
      • 索引选择性=索引列唯一值/表记录数;
      • 选择性越高索引检索价值越高,消耗系统资源越少;选择性越低索引检索价值越低,消耗系统资源越多;
    • 查询条件含有多个字段时,不要在选择性很低字段上创建索引
      • 可通过创建组合索引来增强低字段选择性和避免选择性很低字段创建索引带来副作用;
      • 尽量减少possible_keys,正确索引会提高sql查询速度,过多索引会增加优化器选择索引的代价,不要滥用索引;

    再回顾组合索引与范围查询的业务场景。

    ——组合索引字段顺序与范围查询之间的关系——

    引子:范围查询 city_id in (0,8,10) 能用组合索引 (ads_id,city_id) 吗?

    举例,

    ac 表有一个组合索引(ads_id,city_id)。

    那么如下 ac.city_id IN (0, 8005) 查询条件能用到 ac表的组合索引(ads_id,city_id) 吗?

    Pokecut
    Pokecut

    AI图片编辑处理工具,拥有超过50多种AI功能

    下载
    EXPLAINSELECT ac.ads_idFROM ads,  acWHERE      ads.id = ac.ads_id      AND ac.city_id IN (0, 8005)       AND ads.status = 'online'      AND ac.start_timeUNIX_TIMESTAMP()

    优化策略B:

    由于 mysql 索引是基于 B-Tree 的,所以组合索引有“字段顺序”概念。

    所以,查询条件中有 ac.city_id IN (0, 8005),而组合索引是 (ads_id,city_id),则该查询无法使用到这个组合索引。

    DBA总结道:

    组合索引查询的各种场景

    兹有 Index (A,B,C) ——组合索引多字段是有序的,并且是个完整的BTree 索引。

    • 下面条件可以用上该组合索引查询:
      • A>5
      • A=5 AND B>6
      • A=5 AND B=6 AND C=7
      • A=5 AND B IN (2,3) AND C>5
    • 下面条件将不能用上组合索引查询:
      • B>5 ——查询条件不包含组合索引首列字段
      • B=6 AND C=7 ——查询条件不包含组合索引首列字段
    • 下面条件将能用上部分组合索引查询:
      • A>5 AND B=2 ——当范围查询使用第一列,查询条件仅仅能使用第一列
      • A=5 AND B>6 AND C=2 ——范围查询使用第二列,查询条件仅仅能使用前二列

     组合索引排序的各种场景兹有组合索引 Index(A,B)。

    • 下面条件可以用上组合索引排序:
      • ORDER BY A——首列排序
      • A=5 ORDER BY B——第一列过滤后第二列排序
      • ORDER BY A DESC, B DESC——注意,此时两列以相同顺序排序
      • A>5 ORDER BY A——数据检索和排序都在第一列
    • 下面条件不能用上组合索引排序:
      • ORDER BY B ——排序在索引的第二列
      • A>5 ORDER BY B ——范围查询在第一列,排序在第二列
      • A IN(1,2) ORDER BY B ——理由同上
      • ORDER BY A ASC, B DESC ——注意,此时两列以不同顺序排序

     顺着组合索引怎么建继续往下延伸,请各位注意“索引合并”概念:

    • MySQL 5,0以下版本,SQL查询时,一张表只能用一个索引(use at most only one index for each referenced table),
    • 从 MySQL 5.0开始,引入了 index merge 概念,包括 Index Merge Union Access Algorithm(多个索引并集访问),包括Index Merge Intersection Access Algorithm(多个索引交集访问),可以在一个SQL查询里用到一张表里的多个索引。
    • MySQL 在5.6.7之前,使用 index merge 有一个重要的前提条件:没有 range 可以使用。[出自参考资源2]
    索引合并的简单说明:
    • MySQL 索引合并能使用多个索引
      • SELECT * FROM TB WHERE A=5 AND B=6
        • 能分别使用索引(A) 和 (B) 或 索引合并;
        • 创建组合索引(A,B) 更好;
      • SELECT * FROM TB WHERE A=5 OR B=6
        • 能分别使用索引(A) 和 (B) 或 索引合并;
        • 组合索引(A,B)不能用于此查询,分别创建索引(A) 和 (B)会更好;
    最后的总结:

    仍然是强调再强调:

    记住,explain 后再提测是一种美德!

    参考资源:

    1)中文译稿,2013,MySQL 索引最佳实践之问题反馈;2)orczhou,2013,MySQL优化器:index merge介绍;3)orczhou,2013,index merge的补充说明;4)zhengyun,2013,[慢查优化]联表查询注意谁是驱动表 & 你搞不清楚谁join谁更好时请放手让mysql自行判定;5)nocode,2013,MySQL Internals-Index Merge优化; 


    赠图1枚:转:喵了个咪的,老板催我去重构遗留的 Python 代码……http://ww2.sinaimg.cn/bmiddle/7cc829d3jw1e8qihxzpebg20af07yx6p.gifbitsCN.com

    热门AI工具

    更多
    DeepSeek
    DeepSeek

    幻方量化公司旗下的开源大模型平台

    豆包大模型
    豆包大模型

    字节跳动自主研发的一系列大型语言模型

    通义千问
    通义千问

    阿里巴巴推出的全能AI助手

    腾讯元宝
    腾讯元宝

    腾讯混元平台推出的AI助手

    文心一言
    文心一言

    文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

    讯飞写作
    讯飞写作

    基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

    即梦AI
    即梦AI

    一站式AI创作平台,免费AI图片和视频生成。

    ChatGPT
    ChatGPT

    最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

    相关专题

    更多
    pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
    pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

    本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

    1044

    2026.02.13

    微博网页版主页入口与登录指南_官方网页端快速访问方法
    微博网页版主页入口与登录指南_官方网页端快速访问方法

    本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

    334

    2026.02.13

    Flutter跨平台开发与状态管理实战
    Flutter跨平台开发与状态管理实战

    本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

    213

    2026.02.13

    TypeScript工程化开发与Vite构建优化实践
    TypeScript工程化开发与Vite构建优化实践

    本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

    35

    2026.02.13

    Redis高可用架构与分布式缓存实战
    Redis高可用架构与分布式缓存实战

    本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

    111

    2026.02.13

    c语言 数据类型
    c语言 数据类型

    本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

    77

    2026.02.12

    雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
    雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

    本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

    17

    2026.02.12

    豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
    豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

    本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

    813

    2026.02.12

    PostgreSQL性能优化与索引调优实战
    PostgreSQL性能优化与索引调优实战

    本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

    97

    2026.02.12

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    PHP课程
    PHP课程

    共137课时 | 12.3万人学习

    Go语言实战之 GraphQL
    Go语言实战之 GraphQL

    共10课时 | 0.9万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号