作为唯一索引_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,一经查实,立即删除!

相关文章

python捕获全局异常统一管理_python中如何用sys.excepthook来对全局异常进行捕获、显示及输出到error日志中...

使用sys.excepthook函数进行全局异常的获取。1. 使用MessageDialog实现异常显示&#xff1b;2. 使用logger把捕获的异常信息输出到日志中&#xff1b;步骤&#xff1a;定义异常处理函数&#xff0c; 并使用该函来替换掉系统的内置处理函数&#xff1b;对于threading.py的异常捕…

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是…

mysql 读写引擎_揭秘MySQL存储引擎spider

转自&#xff1a;兴趣部落​buluo.qq.com导读&#xff1a; Spider是为MySQL/MariaDB开发的一个特殊引擎&#xff0c;具有内嵌分片功能。现在它已经被集成到MariaDB10.0及以上版本中&#xff0c;作为MariaDB的一个新的主要性。Spider的主要功能是将数据分散到多个后端节点&#…

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

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

lamp mysql大小限制_LAMP 调优之:MySQL 服务器调优

关于 MySQL 调优有 3 种方法可以加快 MySQL 服务器的运行速度&#xff0c;效率从低到高依次为&#xff1a;替换有问题的硬件。对 MySQL 进程的设置进行调优。对查询进行优化。替换有问题的硬件通常是我们的第一考虑&#xff0c;主要原因是数据库会占用大量资源。不过这种解决方…

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…

mysql主从虚拟机_虚拟机centos7Mysql实现主从配置

环境搭建在虚拟机上和创建两个一模一样的centos7系统&#xff0c;并安装相同版本的mysql(可以先创建一个再克隆)在master上操作登录mysqlmysql -u root -p使用mysqluse mysql;创建用户CREATE USER lystbc1% IDENTIFIED BY Lys135426tbc;给用户授权GRANT REPLICATION SLAVE ON *…

怎样检测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…

django和mysql写注册_Django电商项目---完成注册页面和用户登录

完成基本的创建项目、用户注册、登录、注销功能创建Django项目,创建df_user的App创建静态文件夹static(跟manage.py保持在同一级别下)复制静态文件(css images js)到static路径下修改settings.py文件修改templates路径修改数据库新添加静态文件加载路径Pycharm连接mysql数据库…

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

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

mysql cluster双机_GitHub - sophys/mysqlha: 博客“Mysql-cluster数据库集群双机HA研究”测试代码...

mysqlha本代码是基于博客Mysql-cluster数据库集群双机HA研究所写的。测试采用的是32位环境&#xff0c;linux环境为debian&#xff0c;如果是其他系列只需修改部分指令即可。mysql-cluster版本位&#xff1a;mysql-cluster-gpl-7.2.7-linux2.6-i686.tar.gz&#xff0c;可自行去…

mysql gtid基础_MySQL 基础知识梳理学习(四)----GTID

在日常运维中&#xff0c;GTID带来的最方便的作用就是搭建和维护主从复制。GTID的主从模式代替了MySQL早期版本中利用二进制日志文件的名称和日志位置的做法&#xff0c;使用GTID使操作和维护都变得更加简洁和可高。1.GTID的优点(1)基于GTID搭建主从复制根据简单。(2)可以确保每…

k8s pod MySQL环境变量_Kubernetes 配置Pod和容器(一)定义容器环境变量

此页展示了如何给运行在Kubernetes Pod中的容器定义环境变量。开始之前必须有一个Kubernets集群&#xff0c;和一个能和集群沟通的kubectl命令行工具。如果你还没有集群&#xff0c;你可以用Minikube建立一个集群。给容器定义环境变量当你建立了一个Pod,你可以给你运行在Pod中的…