关于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左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...
随机推荐
- Centos7 下修改日期
Centos7 下修改日期 2017年11月19日 19:37:47 harris135 阅读数:2851 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csd ...
- iOS开发之SceneKit框架--SCNParametricGeometry.h
1.SCNParametricGeometry简介 SCNParametricGeometry用于创建简单的3D模型,比如SCNPlane 平面.SCNPyramid 锥形(金字塔).SCNBox 立 ...
- MDK 虚拟串口 *** error 30: undefined name of virtual register
概念说明 查看已有的虚拟寄存器 输入指令: dir vtreg 可以看到没有要配置的虚拟寄存器SxIN和SxOUT,通过查询手册可以看到所有的虚拟寄存器类型: 说明不支持.
- python语句结构(if判断语句)
一.python语句结构分类 条件控制语句:if 语句 if....elif语句 if嵌套 循环语句:while语句 for循环 控制语句:break.continue.pass语句 二.pyt ...
- printk 函数消息是如何记录的
printk 函数将消息写入一个 LOG_BUF_LEN 字节长的环形缓存, 长度值从 4 KB 到 1 MB, 由配置内核时选择. 这个函数接着唤醒任何在等待消息的进程, 就是说, 任何在系统 ...
- ASP.NET中的DEC加密解密过程
本文章分享自 青青果树园的博客,地址是:http://www.cnblogs.com/qqingmu/archive/2008/01/10/1034168.html 我们做网页时经常会遇到URL传输( ...
- leetcode146周赛-1131-绝对值表达式的最大值
题目描述: class Solution: def maxAbsValExpr(self, arr1, arr2) -> int: def function(s1,s2): result1=[] ...
- LUOGU P1438 无聊的数列 (差分+线段树)
传送门 解题思路 区间加等差数列+单点询问,用差分+线段树解决,线段树里维护的就是差分数组,区间加等差数列相当于在差分序列中l位置处+首项的值,r+1位置处-末项的值,中间加公差的值,然后单点询问就相 ...
- CDN与智能DNS原理和应用
1.cdn概念,DNS概念 CDN:Centent Delivery Network(内容分发网络) 使用户可以就近取得所需内容,提高用户访问网站相应速度 CDN=更智能的镜像+缓存+流量导流: DN ...
- 安装hadoop伪分布式
修改hosts cat /etc/hosts 127.0.0.1 mo.don.com 创建用户 useradd hadoop passwd hadoop sudo授权 visudo hadoop A ...