关于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左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...
随机推荐
- flutter中的BuildContext
https://www.jianshu.com/p/509b77b26b78
- Python 日期和时间_python 当前日期时间_python日期格式化
Python 日期和时间_python 当前日期时间_python日期格式化 Python程序能用很多方式处理日期和时间,转换日期格式是一个常见的功能. Python 提供了一个 time 和 cal ...
- Python入门教程 超详细1小时学会Python
Python入门教程 超详细1小时学会Python 本文适合有经验的程序员尽快进入Python世界.特别地,如果你掌握Java和Javascript,不用1小时你就可以用Python快速流畅地写有用的 ...
- 利用VS2015自带的报表制作报表
我用的是VSEnterprise2015 注意:如果要用VS自带的报表,就需要在安装Microsoft SQL Server Data Tools 下面讲讲具体步骤: 1.添加winform界面 2. ...
- Java基础:基本类型
1.基本类型 Java中有8种基本类型,分为4类,分别为: 整型:包括 byte . short. int . long 泛型:float.double 字符型:char 布尔型:boolean 2 ...
- 第四篇:java读取Excel简单模板
场景:对于经常需要导入Excel模板或数据来解析后加以应用的,使用频率非常之高,做了一个比较稳定的版本,体现在这些地方工具:org.apache.poi使用前必须了解这些:1.要解析,那肯定先判断是不 ...
- Redis 的 4 大法宝,2018 必学中间件!
Redis是什么? 全称:REmote DIctionary Server Redis是一种key-value形式的NoSQL内存数据库,由ANSI C编写,遵守BSD协议.支持网络.可基于内存亦可持 ...
- 4_6.springboot2.xWeb开发之错误处理机制
1.SpringBoot默认的错误处理机制 默认效果:1).浏览器,返回一个默认的错误页面 浏览器发送请求的请求头: 2).如果是其他客户端,默认响应一个json数据 原理: 默认情况下,Sp ...
- where与having区别
解释一. 聚合函数是比较where.having 的关键. 开门见山.where.聚合函数.having 在from后面的执行顺序: where>聚合函数(sum,min,max,avg,cou ...
- 异常处理记录: Unable to compile class for JSP
出错信息截图: 经过搜索引擎的帮助, 发现这些引发异常的可能原因: 1. tomcat的版本必须大于等于JDK的版本 2. maven中的jar与tomcat中jar冲突 看看pom.xml, 果然j ...