文章转自:http://www.cnblogs.com/zhengyun_ustc/p/slowquery2.html

写在前面的话:

之前曾说过“不要求每个人一定理解 联表查询(join/left join/inner join等)时的mysql运算过程”,但对于字段选择性差意味着什么,组合索引字段顺序意味着什么,要求每个人必须了解;

重复上一次的话:把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) 吗?

EXPLAIN

SELECT ac.ads_id

FROM ads, ac

WHERE

  ads.id = ac.ads_id

  AND ac.city_id IN (0, 8005) 

  AND ads.status = 'online'

  AND ac.start_time<UNIX_TIMESTAMP()

  AND ac.end_time>UNIX_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. 在oracle中操作表及字段注释,查询一个表的所有字段名以及属性和约束

    1.查询表注释 SELECT * FROM USER_TAB_COMMENTS; 三列:TABLE_NAME,TABLE_TYPE,COMMENTS 2.查询字段注释 SELECT * FROM US ...

  2. [慢查优化]慎用MySQL子查询,尤其是看到DEPENDENT SUBQUERY标记时

    案例梳理时间:2013-9-25 写在前面的话: 在慢查优化1和2里都反复强调过 explain 的重要性,但有时候肉眼看不出 explain 结果如何指导优化,这时候还需要有一些其他基础知识的佐助, ...

  3. INDEX--创建索引和删除索引时的SCH_M锁

    最近有一个困惑,生产服务器上有一表索引建得乱七八糟,经过整理后需要新建几个索引,再删除几个索引,建立索引时使用联机(ONLINE=ON)创建,查看下服务器负载(磁盘和CPU压力均比较低的情况)后就选择 ...

  4. 一个Web报表项目的性能分析和优化实践(四):MySQL建立索引,唯一索引和组合索引

    先大致介绍下项目的数据库信息. 数据库A:主要存放的通用的表,如User.Project.Report等. 数据库B.C.D:一个项目对应一个数据库,而且这几个项目的表是完全一样的. 数据库表的特点 ...

  5. 使用DbVisualizer 10.0.20 查询ES中的索引时需要注意的事项

    查询前5条数据 光标停在某一个查询结果框中,左下角会显示该字段的类型 查询类型是text的字段使用单引号,使用双引号查询会报错

  6. sql server中使用组合索引需要注意的地方

    一.使用组合索引需要注意的地方 1.索引应该建在选择性高的字段上(键值唯一的记录数/总记录条数),选择性越高索引的效果越好.价值越大,唯一索引的选择性最高: 2.组合索引中字段的顺序,选择性越高的字段 ...

  7. mysql索引之组合索引

    多列索引又称组合索引,在mysql的查询操作中,我们经常会遇到多个搜索条件,如:$sql = "select * from article where content='ma4' and t ...

  8. java web轻量级开发面试教程读书笔记:建索引时我们需要权衡的因素

    场景一,数据表规模不大,就几千行,即使不建索引,查询语句的返回时间也不长,这时建索引的意义就不大.当然,若就几千行,索引所占的空间也不多,所以这种情况下,顶多属于"性价比"不高. ...

  9. SAP:建表时如果有QUAN、CURR类型的字段不能激活的问题

    建表时如有一个QUAN类型的字段,那么就要给字段设置Reference field,参考的字段的Data Type要是UNIT, 并设置对应的Reference table,也就是参考字段所在的tab ...

随机推荐

  1. Spring Bean的加载

    Spring加载bean的原则:不等bean创建完成就会将创建bean的ObjectFactory提早曝光加入到缓存中.   单例bean在Spring容器里只会创建一次,后续创建时会首先从缓存中获取 ...

  2. 一键准备Oracle安装

    在Linux下安装Oracle软件之前,有相当工作需要准备,包括建立用户.配置内核参数.配置资源限制参数.配置Oracle用户环境等,十分繁琐.即便十分熟悉,也需要花费一定的精力来准备.说白了,做这些 ...

  3. 错误: “WebForm_DoPostBackWithOptions”未定义

    无论是ASP.NET WebForm 还是 ASP.NET MVC项目,在本地程序测试没问题,但是部署在IIS上访问就会出现  错误: “WebForm_DoPostBackWithOptions”未 ...

  4. centos本地yum源安装

    1.为DVD或U盘创建一个用于挂载的目录 [root@localhost ~]# mkdir /media/CentOS/ 2.查看DVD或U盘所在的路径 [root@localhost ~]# fd ...

  5. 将Centos的yum源更换为国内的阿里云源

    阿里云是最近新出的一个镜像源.得益于阿里云的高速发展,这么大的需求,肯定会推出自己的镜像源.阿里云Linux安装镜像源地址:http://mirrors.aliyun.com/ CentOS系统更换软 ...

  6. 2.lvm动态逻辑卷

    Lvm动态逻辑卷 一.             基本概念 LVM 把实际的物理磁盘数据映射到一个简单而灵活的虚拟逻辑存储视图上,藉以控制磁盘资源: 也就是重新考虑了管理文件系统和卷的方法,在文件系统管 ...

  7. 使用shell脚本实现ping对应IP所对应的人名

    #!/bin/bash a=(张三 李四 王五 赵六) ..} do . $((${i}+)) >dev/>&;then ))"号"${a[${i}]}&quo ...

  8. Maven build lifecycle

    Clean Lifecycle 运行mvn clean执行clean生命周期,包含三个生命周期阶段: pre-clean clean post-clean clean:clean会删除一次构建后的输出 ...

  9. plain framework 1 网络流 缓存数据详解

    网络流是什么?为什么网络流中需要存在缓存数据?为什么PF中要采用缓存网络数据的机制?带着这几个疑问,让我们好好详细的了解一下在网络数据交互中我们容易忽视以及薄弱的一块.该部分为PF现有的网络流模型,但 ...

  10. BZOJ 3144: [Hnoi2013]切糕

    3144: [Hnoi2013]切糕 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1495  Solved: 819[Submit][Status] ...