作为唯一索引_Mysql什么情况下不走索引?

本文基于Mysql5.7版本和InnoDB存储引擎。

1、InnoDB索引组织表

在InnoDB引擎中,表都是按照主键顺序组织存放的,这种存放方式的表称为索引组织表。InnoDB存储引擎中的表,都有主键,如果没有显式声明主键,则采取以下措施:
  • 该表如果有非空唯一索引,则该列为主键;如果有多个,则取第一个;

  • 如果没有非空唯一索引,则InnoDB自动创建一个大小为6字节的指针作为主键;

为什么推荐使用自增ID做主键而不是UUID?

  • 这是由于B+树的性质决定的,UUID无序,占用空间大,每(磁盘)页能存放的索引少,这会导致磁盘IO次数增加,效率变慢;

什么是堆表?

  • 与索引组织表相对应,堆表是按照行数据的插入顺序存放,无组织,在某些情况下,堆表比索引组织表更快;

2、索引原理

2.1、什么是索引?

  • 索引是一个单独的、存储在磁盘上的数据库结构。

  • InnoDB支持B+树索引;B+树索引由于一个结点存储的是一个磁盘页的数据,因此只能先找到被查找数据所在的页,然后将页读进内存中,最后再在内存中查找;

  • 关于B+树数据结构的相关知识请看 什么是B-树、B树、B+树、B*树?

2.2、B+树索引分类

聚集(主键)索引

辅助(非聚集、二级)索引

  • 普通索引

  • 唯一索引

  • 联合索引

聚集索引和主键索引的相同点:

  • 叶子结点存放所有数据(这是由B+树的性质所决定的);

不同点:

  • 聚集索引的叶子结点存放一整行数据,而辅助索引的叶子结点只存放该列数据和主键;

每张表只能有一个聚集索引,如果是select *操作,则优化器更倾向于使用聚集索引,因为聚集索引能在B+树的叶子结点上找到一整行的数据;聚集索引对于主键的排序和范围查找非常快;如果采用辅助索引查找,比如:select * from user where name="张三",假设在辅助索引name上通过3次查找得到(name=张三,id=10),再在聚集索引上通过3次查找得到id为10的整行数据,因此一共进行了6次查找;因此直接查找聚集索引比查找辅助索引效率高:聚集索引的叶子结点包含了全部数据;

2.3、联合索引原理

f2074ebd6a4dca9f53f040f52380c47f.png

如上图所示,联合索引的结点以(a列的值,b列的值)形式存储。

下面看看如何使用联合索引进行查询:

  • select * from tb1 where a=? and b=?,走联合索引,因为a和b在一起是排序的;

  • select * from tb1 where a=?,走联合索引,因为单独的a是排序的;

  • select * from tb1 where b=?,不走联合索引,因为单独的b不是排序的,如上图,b的顺序为1,2,1,4,1,2;

联合索引的好处:

  • 首先,a列和b列都是排好序的;比如我要查询用户最近三次的购买记录,可以使用user_id作为索引,也可以使用(user_id,buy_date)的联合索引;如果使用user_id作为索引,则需要将查询出来的结果再按buy_date进行一次排序,才能查出最近三次的购买记录;而联合索引已经将buy_date排好序了,只需要取最后三条数据,就是用户最新三次的购买记录;

2.4、什么是覆盖索引?

定义:如果能直接从辅助索引上查找到所有想要的数据,而不需要回表(通过主键在聚集索引上做二次查询),就称该辅助索引覆盖了这条select语句,又称索引覆盖;


优化器一般会倾向于使用覆盖索引而不是聚集索引,因为聚集索引占用空间大,磁盘IO次数多;

联合索引可以当做覆盖索引使用。对于联合索引(a,b)而言,使用b作为查询条件则不走索引,但是如果此时没有针对b的索引,且要查询的列该联合索引都有,则优化器会将该联合索引视作覆盖索引(联合索引上单独的b是无序的,所以是从头到尾顺序查找,尽管如此也比在聚集索引上顺序查找效率高),explain的Extra中有Using index就表明使用了覆盖索引;

2.5、操作索引

查看某个表的索引:show index from 表名

下面解释一下各字段的意思:

  • Table:索引所在表名;

  • Non_unique:值为0表示唯一;

  • Key_name:索引名称;

  • Seq_in_index:索引中该列的位置;

  • Column:索引中列的名称;

  • Collation:列以什么方式存储在索引中,值为A或NULL,B+树索引总是A,即排序的;

  • Cardinality:表示该列中唯一值数目的估计值。如果该值非常小,则表示该列重复数据较多;为什么是估计值呢?因为该值不是实时更新的(代价太大),可以用analyze table命令手动更新一次Cardinality值;

  • Sub_part:是否只对列的一部分索引;比如某个列类型为varchar(1000),可以设置只索引该列的前100个字符,则Sub_part的值为100,如果索引的是列的全部,则Sub_part为NULL;

  • Packed:关键字如何被压缩。如果没有被压缩则为NULL;

  • Null:该列是否允许有NULL值;

  • Index_type:索引类型;

在select语句中使用force index(index_name)强制使用某个索引,而user index(index_name)则提示使用某个索引。

3、性能优化

3.1、执行计划

查看sql的执行计划:explain select ...

下面简要介绍一下各字段的意思,详细解释请查阅Mysql5.7官方文档:https://dev.mysql.com/doc/refman/5.7/en/explain-output.html

id:select的查询序列号

select_type:查询类型

  • simple:简单查询,不包括连接查询和子查询

  • primary:主要的查询,最外层的查询

  • subquery:子查询

table:表示查询的表

partitions:命中的分区,如果是非分区表则为NULL

type:表的连接类型

  • const:只返回一行数据,查询速度很快,该列具有唯一索引或主键索引;如果是普通索引,即时真的只返回一行数据,也不会是const;

  • range:范围查询;

  • index:根据辅助索引全表扫描;

  • ALL:无索引(聚集索引)全表扫描;

possible_keys:通过检测where子句获得可用的索引;

key:实际使用的索引;

rows:显示Mysql在表中进行查询时必须检查的行数;

extra:表示Mysql在处理查询时的详细信息;

3.2、索引设计原则

索引优点:

  • 唯一索引可以保证唯一性;

  • 加快速度:查询速度、表与表连接速度、分组和排序的速度;

缺点:

  • 索引需要占用磁盘空间;

  • 索引的维护(增删改)需要时间,尤其是数据量大的时候;

索引设计原则:

  • 索引并非越多越好,索引太多会影响insert、update、delete的性能;

  • 经常更新的列不使用索引,经常查询(逻辑外键、where子句、group by子句、order by子句)的列使用索引;

  • 数据量小的表不使用索引;

  • 重复值很多的列不使用索引;

  • 删除长期未使用的索引,不用的索引会造成不必要的性能消耗;

  • 避免使用冗余索引:如(name,city)和(name)就是冗余索引,因此一般应该扩展已有的索引,而不是创建新的索引;

3.3、索引失效的情况

避免where子句中对字段施加函数,会造成无法命中索引。
  • 这是因为b+树只能对原值进行索引。

索引列尽量不要存在null值,将该列设置not null约束,可以用0代替null。

假设订单表有1000万数据,订单号为null有100条,分析如下三条sql语句:

explain select order_num from goods_order where order_num ='f035a84a-4672-4517-bd8a-2c9f2d92423e'
explain select order_num from goods_order where order_num is null
explain select order_num from goods_order where order_num is not null

通过执行结果发现,只有is not null不走索引。

联合索引遵循最左前缀原则,否则不走索引。

使用in不走索引,用exists代替,如果是连续的数值则可以用between代替。

应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,则不走索引。like子句不能前置百分比,否则不走索引,如果非要前置百分比不可,则考虑使用全文索引。where 子句中不要使用 != 或 <> ,否则不走索引。limit offset查询缓慢时,可以借助主键索引来提高性能:
  • select a.* from bigtable a inner join (select id from bigtable LIMIT 6520000,10) b on a.id=b.id

最后看一下下面这种情况:

比如select * from order where order_id>10000 and order_id<20000,注意order_id不是主键,此时有一个辅助索引order_id,由于该索引上不包含所有的字段(注意是select *),因此还要回表。通过order_id找到的对应主键是无序的,所以回表的过程是磁盘离散读,而磁盘顺序读的速度是远大于离散读的(固态硬盘的随机读速度非常快),特别是数据量大的情况下差异更明显,这时会优化器会放弃辅助索引而走全表扫描。

总体来说,优化器选择走不走索引,也不是千篇一律的,有时候也要看实际情况。对于我们而言,要熟练使用explain查看sql执行计划,在实际项目中分析sql性能的瓶颈,进行优化。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383037.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

r语言系统计算上是奇异的_R语言实现并行计算

Python作为多线程的编程语言在并行方面相对于R语言有很大的优势&#xff0c;然而作为占据统计分析一席之地的R语言自然不能没有并行计算的助力。那么我们来看下在R语言中有哪些并行的包&#xff1a;隐式并行&#xff1a;OpenBLAS&#xff0c;Intel MKL&#xff0c;NVIDIA cuBLA…

cansina 目录_dirmap - 一个高级web目录、文件扫描工具-华盟网

Dirmap一个高级web目录扫描工具&#xff0c;功能将会强于DirBuster、Dirsearch、cansina、御剑需求分析经过大量调研&#xff0c;总结一个优秀的web目录扫描工具至少具备以下功能&#xff1a;并发引擎能使用字典能纯爆破能爬取页面动态生成字典能fuzz扫描自定义请求自定义响应结…

唯有自己变得强大_物竞天择,适者生存,唯有强大自己,方能百毒不侵

物竞天择&#xff0c;适者生存&#xff0c;这是亘古不变的道理。面对生活中的困难&#xff0c;人生路上的挫折&#xff0c;我们只有足够坚强&#xff0c;足够勇敢&#xff0c;足够强大&#xff0c;才能战胜这一切。人活着要明白&#xff0c;你所有的负面&#xff0c;都源于你的…

树莓派c语言运行_树莓派完成简单的编程(四)

在上一篇文章中&#xff0c;我们学习了Vi文本编辑器&#xff0c;那么用它可以实现什么功能呢&#xff1f;树莓派python以及c语言编程这里我选择了最简单和很流行的两种编程语言&#xff1a;C语言和Python。实现最简单的功能&#xff0c;输出hello world。Python编程简介Python是…

python中的与或非_「Python基础」 While 循环语句

Python 编程中 while 语句用于循环执行程序&#xff0c;即在某条件下&#xff0c;循环执行某段程序&#xff0c;以处理需要重复处理的相同任务。其基本形式为&#xff1a;while 判断条件&#xff1a;执行语句……执行语句可以是单个语句或语句块。判断条件可以是任何表达式&…

go定时器 每天重复_Go语言学习基础-定时器、计时器

Timer计时器如果希望在将来的某个时间点执行Go代码&#xff0c;或者在某个时间间隔重复执行Go代码&#xff0c;使用Go内置的timer和ticker功能。先看定时器timer&#xff0c;然后再看计时器ticker。定时器代表未来的单个事件。告诉定时器需要等待多长时间&#xff0c;它返回一个…

html类名定义规则_HTML入门笔记1

HTML 是谁发明的?Tim Berners-LeeHTML起手式&#xff1a;HTML起手式 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0&q…

怎样检测mysql5.5安装成功_64位wiN7系统中装配MySQL5.5.17(测试安装成功哦!)

64位wiN7系统中安装mysql5.5.17(测试安装成功哦&#xff01;&#xff01;~~)下载地址&#xff1a;[url] http://www.mysql.com/downloads/mysql/[/url]下载的话需要登录,你只需按照要求注册一个账号,然后下载即可.我下载的是mysql-5.5.17-winx64.msi版本.安装步骤:Step 1. Mysq…

xcode 创建模拟器_Xcode编译WebKit

下载WebKit源码1)进入https://webkit.org/2)点击页面的 Get Started 进入新页面&#xff0c;如下图所示3)点击 Getting the code 进入新页面&#xff0c;如下图所示4)在源码下载页面&#xff0c;有多种下载方式&#xff0c;包括直接下载代码zip包&#xff0c;通过SVN下载&#…

mysql iscsi_iscsi共享存储的简单配置和应用

1、环境介绍SCSI(Small Computer System Interface)是块数据传输协议&#xff0c;在存储行业广泛应用&#xff0c;是存储设备最基本的标准协议。从根本上说&#xff0c;iSCSI协议是一种利用IP网络来传输潜伏时间短的SCSI数据块的方法&#xff0c;ISCSI使用以太网协议传送SCSI命…

request mysql 接口_TP5接口开发

开启debug调试模式(正式上线建议关闭)config.php// 应用调试模式app_debug > true,设置输出类型index.phpnamespace app\index\controller;class Index{public function index(){$data [name > steven, age > 24];return json([code > 0, msg > 操作成功, data…

命令行进入指定目录_VIM学习笔记 操作目录(Manipulate Directory)

在目录间移动使用以下命令&#xff0c;可以显示当前所在的目录&#xff1a;:pwd使用以下命令&#xff0c;在Linux下可以进入HOME目录&#xff0c;而在Windows下则显示当前所在目录&#xff1a;:cd使用以下命令&#xff0c;可以进入指定的目录&#xff1a;:cd D:tepm使用以下命令…

koa2 mysql 中间件_Koa2第二篇:中间件

第一篇介绍了生成器目录设计。xyzcoding&#xff1a;Koa2第一篇&#xff1a;详解生成器​zhuanlan.zhihu.com接下来学习Koa2的中间件。Koa2本身只能算一个极简的HTTP服务器&#xff0c;自身不内置中间件&#xff0c;但是提供中间件内核。中间件是Koa2的核心&#xff0c;因此需要…

rs485数据线接反_终于有人把RS485通讯的正确接线方式讲明白了,网友:这下好办了...

RS485是一个定义平衡数字多点系统中的驱动器和接收器的电气特性的标准,该标准由电信行业协会和电子工业联盟定义。使用该标准的数字通信网络能在远距离条件下以及电子噪声大的环境下有效传输信号。RS485使得廉价本地网络以及多支路通信链路的配置成为可能。那么RS485通讯的正确…

骑马与砍杀python代码_GitHub - yunwei1237/scottish-fold: 一个关于骑马与砍杀的剧本制作工具...

scottish-fold一个关于骑马与砍杀的剧本简单快速的制作工具前言​在很久以前的时候&#xff0c;也就是刚开始玩骑砍的时候就想着能够制作一个自己的剧本&#xff0c;用于书写自己想要的故事。当我怀着远大的梦想去这么做的时候才发现&#xff0c;原来制作剧本没有自己想象的那么…

java object强制类型转换_scala object 转Class Scala强制类型转换

asInstanceOf[T]将对象类型强制转换为T类型。还是由于泛型存在类型擦除的原因,1.asInstanceOf[String]在运行时会抛出ClassCastException异常&#xff0c;而List(1).asInstanceOf[List[String]]将不会。packageresti.webimportorg.springframework.beans.factory.annotation.Au…

java毛玻璃_模糊效果(毛玻璃效果)

模糊效果(毛玻璃效果)效果演示&#xff1a;1. 使用iOS自带的 UIImageImageEffects 文件文件中有这么几个方法&#xff1a;- (UIImage *)applyLightEffect;- (UIImage *)applyExtraLightEffect;- (UIImage *)applyDarkEffect;- (UIImage *)applyTintEffectWithColor:(UIColor *)…

java程序崩溃怎么重启_android 异常崩溃后 重启app(进程守护方式实现)

【实例简介】【实例截图】【核心代码】package com.sunfusheng.daemon.sample;import android.content.ComponentName;import android.content.Intent;import android.os.Looper;import android.util.Log;import com.blankj.utilcode.util.AppUtils;import com.sunfusheng.daem…

python 库 全局变量_python局部变量和全局变量global

当你在函数定义内声明变量的时候&#xff0c;它们与函数外具有相同名称的其他变量没有任何关系&#xff0c;即变量名称对于函数来说是 局部 的。这称为变量的 作用域 。所有变量的作用域是它们被定义的块&#xff0c;从它们的名称被定义的那点开始。使用局部变量例7.3 使用局部…

java精确测量文本高度_基于文本精确计算UITableViewCell的高度

我正在开发一个ios应用程序&#xff0c;并使用autolayout我正在尝试创建一个具有不同行高的表视图 .原型单元的布局如下&#xff1a;我有一个主单元格(黑色)里面有一个UIView(红色)&#xff0c;里面有一个UILabel(蓝色)我添加的Autolayout约束如图所示&#xff1a;The UIView h…