关于MySQL IN LIKE OR使用索引的问题
以前在网上看了一些资料,有些人说话不严谨,导致一直被误导,最近在实际开发中发现一些结论有问题,因此特地整理了一下,防止下次继续犯错。
以下前提是有对这个字段建立索引(简直废话,没建的肯定不会使用索引啊)
首先建立一张表:
CREATE DATABASE `test_lkc` CHARATER SET utf8 COLLATE utf8_general_ci; CREATE TABLE `students` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`stuno` varchar(9) NOT NULL DEFAULT '' COMMENT '学号',
`name` varchar(64) NOT NULL DEFAULT '' COMMENT '姓名',
`major` varchar(255) NOT NULL DEFAULT '' COMMENT '专业',
`class` int(10) unsigned NOT NULL DEFAULT '' COMMENT '班级',
`id_card` varchar(18) NOT NULL DEFAULT '' COMMENT '身份证号码',
`memo` varchar(255) NOT NULL DEFAULT '' COMMENT '备注',
PRIMARY KEY (`id`),
UNIQUE KEY `stuno` (`stuno`) USING BTREE,
UNIQUE KEY `id_card` (`id_card`) USING BTREE,
KEY `major_class` (`major`,`class`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
数据我是用php批量生成的
<?php
$pdo = new PDO("mysql:host=127.0.0.1;dbname=test_lkc","root","root");
//数据
$addList = [];
$majorList = ['CN','EN','JP','KO','RU','SV','CU','DE','FR','RO'];
$prefixList = ['A','B','C','D','E','F','G','H','I','J'];
for ($i=0;$i<1000;$i++){
$row = [];
$id = sprintf('%03d',$i);
$row['stuno'] = $prefixList[$i/100] . '2017' . sprintf('%04d',$i + 1);
$row['name'] = $prefixList[$id[0]] . $prefixList[$id[1]] . $prefixList[$id[2]];
$row['major'] = $majorList[$id[0]];
$row['class'] = $i%3 + 1;
$row['id_card'] = '320106194910290' . $id; $addList[] = $row;
} $res = addAll($pdo,$addList);
var_dump($res); function addAll($pdo,$addList){
//字段
$sql = "INSERT INTO `students` (`" . implode("`,`",array_keys($addList[0])) . "`) VALUES ";
//拼接SQL语句
foreach ($addList as $value){
$sql .= "('";
$sql .= implode("','", $value);
$sql .= "'),";
}
$sql = rtrim($sql,','); $res = $pdo->exec($sql);
return $res ? $res : $pdo->errorInfo();
}
1.IN到底会不会使用索引?
答:会!
explain select * from students where id_card IN ('','');

如果没有走索引,那么可能是你的使用姿势不对,比如
(1)字符串类型没有加单引号,
explain select * from students where id_card IN (320106194910290999,320106194910290998);

(2)或者mysql认为使用全表扫描要比使用索引快(我自己遇到的是数据太少或者查询出来的结果很多的时候会出现,比如图中预估的行数是952),则不使用索引
explain select * from students where major IN ('RO','CN');

2.OR到底会不会使用索引?
答:会!
explain select * from students where id = 1 or stuno = 'A20170002';

如果没有走索引,那么肯定又是你的使用姿势不对,比如说
(1)两个条件里面其中一个字段没有建立索引;
explain select * from students where id = 1 or name = 'AAB';

(2)字符串类型的没有加单引号;
explain select * from students where id = 1 or id_card = 320106194910290999;

(3)mysql认为使用全表扫描要比使用索引快,则不使用索引
explain select * from students where id = 1 or major = 'CN';

3.LIKE会不会使用索引
答:LIKE 'xxx%'会;
(1)LIKE'%xxx'或者LIKE'%xxx%'不会
explain select * from students where stuno like 'A2017%';

explain select * from students where stuno like '%20170001';

(2)mysql认为使用全表扫描要比使用索引快,则不使用索引
explain select * from students where major like 'C%';

说来惭愧,我自己被错误的结论误导了那么久,希望大家引以为戒,网络上的答案也不一定就是对的,还是要自己多试试。实践才是检验真理的唯一标准
在查询语句前面加explain ,根据type和key来分析查询到底有没有使用索引
type排行:
连接类型
system 表只有一行
const 表最多只有一行匹配,通用用于主键或者唯一索引比较时
eq_ref 每次与之前的表合并行都只在该表读取一行,这是除了system,const之外最好的一种,
特点是使用=,而且索引的所有部分都参与join且索引是主键或非空唯一键的索引
ref 如果每次只匹配少数行,那就是比较好的一种,使用=或<=>,可以是左覆盖索引或非主键或非唯一键
fulltext 全文搜索
ref_or_null 与ref类似,但包括NULL
index_merge 表示出现了索引合并优化(包括交集,并集以及交集之间的并集),但不包括跨表和全文索引。
这个比较复杂,目前的理解是合并单表的范围索引扫描(如果成本估算比普通的range要更优的话)
unique_subquery 在in子查询中,就是value in (select...)把形如“select unique_key_column”的子查询替换。
PS:所以不一定in子句中使用子查询就是低效的!
index_subquery 同上,但把形如”select non_unique_key_column“的子查询替换
range 常数值的范围
index a.当查询是索引覆盖的,即所有数据均可从索引树获取的时候(Extra中有Using Index);
b.以索引顺序从索引中查找数据行的全表扫描(无 Using Index);
c.如果Extra中Using Index与Using Where同时出现的话,则是利用索引查找键值的意思;
d.如单独出现,则是用读索引来代替读行,但不用于查找
all 全表扫描
关于MySQL IN LIKE OR使用索引的问题的更多相关文章
- MySQL基础(四)——索引
MySQL基础(四)--索引
- MySQL优化技巧之三(索引操作和查询优化)
对于任何DBMS,索引都是进行优化的最主要的因素.对于少量的数据,没有合适的索引影响不是很大,但是,当随着数据量的增加,性能会急剧下降.如果对多列进行索引(组合索引),列的顺序非常重要,MySQL仅能 ...
- MySQL 数据库性能优化之索引优化
接着上一篇 MySQL 数据库性能优化之表结构,这是 MySQL数据库性能优化专题 系列的第三篇文章:MySQL 数据库性能优化之索引优化 大家都知道索引对于数据访问的性能有非常关键的作用,都知道索引 ...
- Mysql优化之创建高性能索引(一)
1.索引基础 索引对于良好的性能非常关键.尤其是当表中的数据量越来越大时,索引对性能的影响愈发重要.但是不恰当的索引随着数据量的增加,也会使整个数据库的性能下降. 举个例子: ; 如果在id上建立索引 ...
- MySQL系列(三)---索引
MySQL系列(三)---索引 前言:如果有疏忽或理解不当的地方,请指正. 目录 MySQL系列(一):基础知识大总结 MySQL系列(二):MySQL事务 MySQL系列(三):索引 什么是索引 如 ...
- mysql进阶(二十七)数据库索引原理
mysql进阶(二十七)数据库索引原理 前言 本文主要是阐述MySQL索引机制,主要是说明存储引擎Innodb. 第一部分主要从数据结构及算法理论层面讨论MySQL数据库索引的数理基础. ...
- (转)Mysql哪些字段适合建立索引
工作中处理数据时,发现某个表的数据达近亿条,所以要为表建索引提高查询性能,以下两篇文章总结的很好,记录一下,以备后用. 数据库建立索引常用的规则如下: 1.表的主键.外键必须有索引: 2.数据量超过3 ...
- Mysql哪些字段适合建立索引
数据库建立索引常用的规则如下: 1.表的主键.外键必须有索引: 2.数据量超过300的表应该有索引: 3.经常与其他表进行连接的表,在连接字段上应该建立索引: 4.经常出现在Where子句中的字段,特 ...
- 关于MySql数据库主键及索引的区别
一.什么是索引?索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里 ...
- MySQL 第五篇:索引原理与慢查询优化
一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...
随机推荐
- Linux课程---12、linux中内存指令(top命令的作用是什么)
Linux课程---12.linux中内存指令(top命令的作用是什么) 一.总结 一句话总结: top实时观察进程.内存和CPU情况 1.电脑出现反应慢情况,最先想到的是什么? 内存 2.linux ...
- awk 一些题目
1.1. 输出记录最多的IP [腾讯面试题]:一个文本类型的文件,里面每行存放一个登陆者的IP(某些行是重复的),写一个shell脚本输出登陆次数最多的用户. Ip_input.txt的内容假设如下: ...
- java关键字之instanceof
首先来看段测试代码 public class TestInstanceof{ public static void main(String[] args){ int a = 1; if(a insta ...
- JS规则 确定你的存在(变量声明) 声明变量语法: var 变量名; 一次声明多个,中间用逗号隔开var num1,mun2 ;
确定你的存在(变量声明) 我们要使用盒子装东西,是不是先要找到盒子,那在编程中,这个过程叫声明变量,找盒子的动作,如何表示: 声明变量语法: var 变量名; var就相当于找盒子的动作,在JavaS ...
- grep 强大的文本搜索工具
1.grep -r "History folder does't exist:" * :中间是要搜索的文本,* 表示全部显示出来
- 位运算 - 左移右移运算符 >>, <<, >>>
1-左移运算符m<<n,表示把m左移n位.左移n位的时候,最左边的n位数将被丢弃,同时在最右边补上n个0.例如: 00001010<<2 = 00101000 10001010 ...
- ubuntu下apache服务器操作方法小结,具有参考借鉴价值
这篇文章主要介绍了ubuntu下apache服务器操作方法小结,非常不错,具有参考借鉴价值,需要的朋友可以参考下(http://www.0831jl.com)Linux系统为Ubuntu 一.Star ...
- thinkphp Mongo模型
Mongo模型是专门为Mongo数据库驱动而支持的Model扩展,如果需要操作Mongo数据库的话,自定义的模型类必须继承Think\Model\MongoModel. Mongo模型为操作Mongo ...
- 0901NOIP模拟测试赛后总结
突然想学迪哥列一下分数线搞清楚自己和别人的差距. rank1- 5- 6-分. 差距很大啊.尤其是和某kyh.大家都开玩笑说天皇是个变态.但是事实摆在这儿,同样坐在机房这么长的时间,人家又AK了. 我 ...
- 关于将ECharts引入到项目中的几种方式
方式一.在webpack中使用ECharts 1.npm安装ECharts npm install echarts --save 2.引入ECharts 通过 npm 上安装的 ECharts 和 z ...