关于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左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...
随机推荐
- 河南理工大学算法协会暑期集训积分赛(二)网络同步赛-Numbers of interval-尺取法
原题链接:https://hpuoj.com/contest/24/problem/E/ 思路:一般的尺取法,不断更新左端点的值. #include<iostream> #include& ...
- day 62 Django基础之jQuery操作cookie
Django基础之jQuery操作cookie jquery之cookie操作 定义:让网站服务器把少量数据储存到客户端的硬盘或内存,从客户端的硬盘读取数据的一种技术: 下载与引入:jquery. ...
- mybatis中一对一关系映射
一对一关系中普通的配置方式 一.多表连接查询语句: <select id="selectStudentWithAddress" parameterType="int ...
- <Python基础>字典的基本操作
''' 小知识 1.字典的键只能是不可变数据类型:int 元组 bool str(可哈希) 字典查找数据会使用二分查找,会先用哈希表将键转化为数字然后进行查找 ''' s = { "name ...
- webpack 简单笔记(二)CommonsChunkPlugin插件
接下来就要使用CommonsChunkPlugin插件 (一)单一入口,模块单一引用,分文件输出,单一入口,模块重复引用,分文件输 main.js代码 require('./static/js/mai ...
- iOS逆向系列-Mach-O文件
概述 Mach-O是Mach object的缩写,是Mac\iOS上用于存储程序.库的标准格式. 常见的Mach-O文件 属于Mach-O格式的文件类型有. 可以在xnu源码中,查看到Mach-O格式 ...
- 2019-5-15-影子系统让-C++-程序无法运行
title author date CreateTime categories 影子系统让 C++ 程序无法运行 lindexi 2019-05-15 15:24:35 +0800 2019-05-1 ...
- 2019-8-31-PowerShell-通过-WMI-获取系统安装软件
title author date CreateTime categories PowerShell 通过 WMI 获取系统安装软件 lindexi 2019-08-31 16:55:58 +0800 ...
- 阿里云香港ECS搭建Shadowscoks
注(转https://yijingping.github.io/2016/11/29/fanqiang.html) 1 为什么FQ 作为一个技术人员, 最常用的就是Google.StackOverfl ...
- System.UriFormatException: Invalid URI 解决方法
mobox 企业网页登陆界面,sa 登陆后 提示 System.UriFormatException: Invalid URI: The URI scheme is not valid. at Sys ...