MySQL中in(常量列表)的执行计划

我们在写sql的时候,经常用到in,in后面跟一堆常量列表,如id。有人说in的效率很高,而有人说很低;有人说in能使用索引,还有人说in不能使用索引。。。
到底是一个怎样的情况呢?我们分析以下几种情况
在这之前,我们先了解一下explain的几种type类型(本次分析即参照type类型),按照性能从高到低:

const:表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)。因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待

eq_ref:在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用

ref:这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生。对于之前的表的每一个行联合,全部记录都将从表中读出。这个类型严重依赖于根据索引匹配的记录多少—越少越好

range:这个连接类型使用索引返回一个范围中的行,比如使用>或<查找东西时发生的情况

index: 这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)

ALL:这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免

一,in后面只有1个值
1.1 对于主键或者唯一索引,那么type=const,这种性能最高,表示表中只有1个记录能满足查询

1.2 对于普通索引、或者联合主键,type=ref

1.3 对于普通字段,type=all,这种性能最差

二,in后面多余1个值,但少于某一个值,这个值具体是多少,之后会揭晓。
这时,不管是主键,还是唯一索引,还是普通索引,type=range

但是在这里需要注意的一个特例是:当你的索引的Cardinality属性比较低时,type=all,意思就是这个索引的区分度很低,建立的意义不大,
这时他的执行计划type=all,mysql认为走这个索引还不如全表扫描:

到底Cardinality处于什么水平时,性能最好?一般认为这个值越接近count(*),性能最好。而对于像性别这种字段,就没必要加索引了。

三,相对于第二种情况,当in后面的值多于某一个值,会导致扫描全表。这个经验值我目前不能确定,咨询过相关DBA,他们也不能给出其经验值
3.1 test1表总共27条数据,当in后面的值少于8个时,type=range,而当超过8个时,type=all,如下:

3.2 这个t_word_cost表,总共有38244条数据,word_id上有索引,我测试了一把,当in后面不超过5千多或者6千多时,type=range,这是什么意思?
因为令我不解的是,这个值还不确定,它是波动的,我执行了好多次,有时候是5千多,有时候是6千多,或者其他值

通过对test1、t_word_cost表进行测试,我确实没有找出规律来,我原来妄想,通过大量实践得出一个经验值,然后通过经验值来判断到底in后面的个数占count(*)百分比多少的时候,能走索引,看来我徒劳了。

既然不能得出经验值,那我们只有在实际应用环境下具体选择解决方案了。
譬如我这次操作t_word_cost表,in后面值的个数都超过count(*)了,如果一次性全部写进in后面,一次查询所耗时间是30-40s左右!
根据上面我分析的结果,貌似我应该选择5000作为临界值,然后分批、多次查询,这样性能应该最高。但实际情况是这样吗?
通过我在程序中不断地人肉测试发现,并不是5000耗时最少,选择2000或者2500时,总体耗时最少,至于为什么,可能与内存、频繁的数据库连接有关吧,
因为我们知道,内存、IO都会影响整体性能,所以怎样平衡这个度需要自己把握。

时间: 2024-10-24 14:24:38

MySQL中in(常量列表)的执行计划的相关文章

MySQL——通过EXPLAIN分析SQL的执行计划

在MySQL中,我们可以通过EXPLAIN命令获取MySQL如何执行SELECT语句的信息,包括在SELECT语句执行过程中表如何连接和连接的顺序. 下面分别对EXPLAIN命令结果的每一列进行说明: select_type:表示SELECT的类型,常见的取值有: 类型 说明 SIMPLE 简单表,不使用表连接或子查询 PRIMARY 主查询,即外层的查询 UNION UNION中的第二个或者后面的查询语句 SUBQUERY 子查询中的第一个 table:输出结果集的表(表别名) type:表示

初步理解MySQL(5.6)的执行计划

声明:以下均来自于MySQL英文手册5.6. 1.MySQL所有的join都是使用 nest-loop join 算法(嵌套循环算法). 2.对于一组joins,MySQL的join算法会从第一个表读取一行,然后一直往后逐个表找匹配行,如果某一行能够从第一个表开始,之后每个表都能找到匹配的行,则输出该"大行":然后原路返回到之前的表直到能找到一张中包含匹配行的表为止,然后继续向后面的每个表找匹配的行. 3.MySQL中索引的使用会被索引的cardinality所影响,cardinali

Mysql中explain命令查看语句执行概况

Mysql中可以使用explain命令查看查询语句的执行方式,使用方法举例:explain + 查询语句 例如:explain select * from user_info 几个重要的字段说明: table:此次查询操作是关联哪张数据表 type:连接查询操作类型,一般根据索引查询的话为const,如果没有索引,则遍历所有数据那么为All(此种方式效率极低) possible_keys:显示可能应用在这张表中的索引.如果为空,没有可能的索引. key: 实际使用的索引.如果为NULL,则没有使

Oracle 11g如何清除share pool中某条SQL的执行计划

以前在10g数据库上,如果遇到绑定窥探导致执行计划慢的情况,想要清除某条SQL的执行计划,让它硬解析,找了很久都没有找到直接操作share pool的方法(总不能alter system flush shared_pool),只能通过对表ddl使SQL硬解析.现在终于找到了,使用sys.dbms_shared_pool.purge,在11g下可以直接使用,但在10g上需要alter session set events '5614566 trace name context forever'.

mysql查询优化器为什么可能会选择错误的执行计划

可能导致mysql优化器选择错误的执行计划的原因如下: A:统计信息不准确,mysql依赖存储引擎提供的统计信息来评估成本,但有的存储引擎提供的信息是准确的,有的引擎提供的可能就偏差很大,如:innodb因为其MVCC的架构,并不能维护一个数据表的行数的精确统计. B:执行计划中的成本估算不等同于实际执行的成本,所以即使统计信息精准,优化器给出的执行计划也可能不是最优的,如:有时候某个执行计划虽然需要读取更多的页,但它的实际执行成本却更小,因为如果这些页面都是顺序或者这些页面都在内存中,那么它的

SQL Server 执行计划利用统计信息对数据行的预估原理以及SQL Server 2014中预估策略的改变

前提  本文仅讨论SQL Server查询时, 对于非复合统计信息,也即每个字段的统计信息只包含当前列的数据分布的情况下, 在用多个字段进行组合查询的时候,如何根据统计信息去预估行数的. 利用不同字段的统计信息做数据行数预估的算法原理,以及SQL Server 2012和SQL Server 2014该算法的差异情况, 这里暂时不涉及复合统计信息,暂不涉及统计信息的更新策略及优化相关话题,以及其他SQL Server版本计算方式. 统计信息是什么 简单说就是对某些字段的数据分布的一种描述,让SQ

转://看懂Oracle中的执行计划

一.什么是Oracle执行计划? 执行计划是一条查询语句在Oracle中的执行过程或访问路径的描述 二.怎样查看Oracle执行计划? 2.1 explain plan for命令查看执行计划 在sql*plus中,执行如下命令: 1)explain plan for select * from XXXX; 2)select * from table(dbms_xplan.display); 2.2 SET AUTOTRACE ON查看执行计划 语法:SET AUTOT[RACE] {OFF |

SQLServer中的执行计划缓存由于长时间缓存对性能造成的干扰

本文出处:http://www.cnblogs.com/wy123/p/7190785.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错误进行修正或补充,无他) 先抛出一个性能问题,前几天遇到一个生产环境性能极其低下的存储过程,开发人员根据具体的业务逻辑和返回的数据量,猜测到这个存储过程的执行应该不会有这么慢.当时意识到可能是执行计划缓存的问题,因为当前这个存储过程的写法还是比较遵守参数化SQL的规范的(如果是动态即席查询SQL就不

谈一谈SQL Server中的执行计划缓存(下)

简介 在上篇文章中我们谈到了查询优化器和执行计划缓存的关系,以及其二者之间的冲突.本篇文章中,我们会主要阐述执行计划缓存常见的问题以及一些解决办法. 将执行缓存考虑在内时的流程 上篇文章中提到了查询优化器解析语句的过程,当将计划缓存考虑在内时,首先需要查看计划缓存中是否已经有语句的缓存,如果没有,才会执行编译过程,如果存在则直接利用编译好的执行计划.因此,完整的过程如图1所示. 图1.将计划缓存考虑在内的过程 图1中我们可以看到,其中有一步需要在缓存中找到计划的过程.因此不难猜出,只要是这一类查

谈一谈SQL Server中的执行计划缓存(上)

原文:谈一谈SQL Server中的执行计划缓存(上) 简介     我们平时所写的SQL语句本质只是获取数据的逻辑,而不是获取数据的物理路径.当我们写的SQL语句传到SQL Server的时候,查询分析器会将语句依次进行解析(Parse).绑定(Bind).查询优化(Optimization,有时候也被称为简化).执行(Execution).除去执行步骤外,前三个步骤之后就生成了执行计划,也就是SQL Server按照该计划获取物理数据方式,最后执行步骤按照执行计划执行查询从而获得结果.但查询