我们在写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都会影响整体性能,所以怎样平衡这个度需要自己把握。
转自:http://blog.itpub.net/28912557/viewspace-1255568/
相关推荐
在MySQL数据库中,`FIND_IN_SET()` 和 `IN` 是两种不同的查询方法,它们在处理数据集时有不同的特性和应用场景。本文将对这两种方法进行详细对比,以帮助理解它们之间的差异。 `FIND_IN_SET()` 函数主要用于在一个...
为了高效地从数据库中检索数据,MySQL优化器会利用各种规则和成本模型对不同的查询执行计划进行优化。下面,我们将详细探讨MySQL优化器执行计划优化的若干重要知识点。 首先,我们需要理解子查询优化的概念。子查询...
MySQL中的`EXPLAIN`命令是数据库管理员和开发者用于分析SQL查询执行计划的重要工具。通过`EXPLAIN`,我们可以深入了解MySQL如何处理查询,包括选择的数据访问方法、使用的索引以及执行顺序,这对于优化查询性能至关...
在MySQL数据库中,EXPLAIN命令是一个非常重要的工具,它能够帮助我们分析SQL查询的执行计划,从而优化查询性能。通过对EXPLAIN输出的各个列的解释,我们可以深入理解MySQL如何处理SELECT语句,以及如何利用索引来...
MySQL的`EXPLAIN`命令是数据库管理员和开发者用于分析SQL查询执行计划的重要工具。通过`EXPLAIN`,我们可以了解MySQL如何处理我们的查询,从而优化查询性能。以下是对`EXPLAIN`输出各列的详细解释: 1. **table**:...
- 如果在`WHERE`子句中使用参数(如`@num`),MySQL会在编译时创建访问计划,此时参数的值未知,可能导致索引未被利用。可以通过显式指定索引来强制使用特定索引。 8. **避免在`WHERE`子句中对字段进行表达式或...
首先,`mysql_win32.inc` 文件可能是包含预编译头的文件,它可能包含了针对Windows平台的MySQL库的路径和定义,以便在Delphi项目中正确链接到MySQL的动态链接库(DLL)。这些头文件通常会定义函数原型、常量和类型...
`EXPLAIN`命令是MySQL提供的一种工具,用于分析SQL查询的执行计划,帮助我们理解数据库如何执行查询,从而找出可能存在的性能瓶颈。本文将深入探讨如何通过`EXPLAIN`来分析低效SQL,并解释其返回结果的主要列。 ...
MySQL的EXPLAIN命令是数据库管理员和开发者用于分析SQL查询执行计划的重要工具。通过EXPLAIN,我们可以深入了解MySQL如何处理SELECT语句,以及如何连接不同的表,从而优化查询性能和索引设计。 1. **id**: 这是...
- **执行计划**:使用`EXPLAIN`命令查看SQL执行计划,从而找出瓶颈所在。 ##### 3.3 EXPLAIN命令使用 - `EXPLAIN SELECT * FROM tb_item;` - **结果解释**: - **id**:SELECT查询的序列号,不重要。 - **select_...
MySQL使用基于开销的成本优化器,其目标是预测不同执行计划的开销,并选择开销最小的方案。开销是指对大小为4KB的页面进行一次随机读取。然而,优化器并不总是能够做出最佳决策: 1. **统计数据可能是错误的**:不...
1. `IN`通常用于比较单个列值是否在某个列表中,例如: ```sql SELECT * FROM table1 WHERE column1 IN (SELECT column2 FROM table2 WHERE condition) ``` `IN`会返回所有`table1`中`column1`值与`table2`中`...
MySQL中的`IN`查询和`EXISTS`查询都是在处理子查询时常用的操作,它们各自有不同的特性和适用场景。理解两者的区别对于优化SQL查询性能至关重要。 ### `IN`查询 `IN`查询通常用于检查某列的值是否在特定的值列表中...
在条件处理步骤中,MySQL会分析WHERE子句中的条件,并进行等式传播、常量传播和无意义条件删除等优化。在表依赖步骤中,MySQL会列出每个表及其依赖关系。在引用优化关键使用步骤中,MySQL会展示如何使用索引来优化...
常用的一种工具是`EXPLAIN`命令,它可以显示SQL查询的执行计划。 - **语法**:`EXPLAIN SELECT * FROM tb_item;` - **结果说明** - **id**:表示SELECT查询的序列号。一般情况下,这个字段的值并不重要。 - **...
13.1 LOAD DATA INFILE语句 13.2 存储引擎 13.3 事务 13.3.1 理解事务的定义 13.3.2 通过InnoDB使用事务 13.4 外键 13.5 存储过程 13.5.1 基本示例 13.5.2 局部变量 13.5.3 游标和控制结构 13.6 进一步...
在MySQL中,使用`EXPLAIN`关键字可以帮助我们查看SQL查询的执行计划,这对于优化查询非常重要。例如: ```sql EXPLAIN SELECT * FROM tb_item; ``` ##### 结果说明 - **id**:表示SELECT查询的序列号。这个字段在...