系列文章

二、一生挚友redo log、binlog《死磕MySQL系列 二》

三、MySQL强人“锁”难《死磕MySQL系列 三》

四、S 锁与 X 锁的爱恨情仇《死磕MySQL系列 四》

五、如何选择普通索引和唯一索引《死磕MySQL系列 五》

如果你对索引的知识点还不太清楚,可以直接通过传送门查看咔咔总结的索引知识点。

揭开MySQL索引神秘面纱

索引是为加速查询速度,创建的索引也符合所有规则,但MySQL就是不使用理想的索引,导致查询速度变慢并产生大量慢查询记录。

今天就从这个问题来聊聊MySQL选择索引时都做一些什么事情。

一、如何选择索引

影响优化器的几大因素

一条查询SQL执行需要经过连接器、分析器、优化器、执行器,而选择索引的重任就交给了优化器

优化器在多个索引中选择目的是为了找出执行代价最低的方案。

影响优化器选择无非就这几个因素,扫描行数、是否使用了临时表、是否使用文件排序。

临时表、文件排序这个两个点会在后期文章给大家慢慢引出,今天只聊扫描行数。

扫描行数越少则访问磁盘数据的次数就越少,消耗的CPU资源越少。

那么这个扫描行数是从哪里取的呢?

扫描行数从何而来?

创建索引一直提倡大家给区分度高的列建立索引,在一个索引上不同值的个数称之为基数(cardinality)。

使用show index from table_name可以查看每个索引的基数是多少。


索引基数

索引基数怎么计算

MySQL使用采样统计的方法,会选出N个数据页,每个数据页大小16kb,接着统计选出来的数据页上的不同值就会得到一个平均值,用平均值在乘以索引的页面数得到的结果就是这个索引的基数。

表数据是持续增加或删减的,统计的这个数据也不是时时变化的,当变更的数据超过1/M时会自动触发重新计算。

这个M是根据参数innodb_stats_persistent的值选则的,设置为on值为10,设置为off值为16。

索引基数通过这种方式计算不是精准的但也差不了多少

为什么优化器选择了扫描行数多的索引?

第一种情况

表增删十分频繁,导致扫描行数不准确

第二种情况

假设你主键索引扫描行数是10W行,而普通索引需要扫描5W行,这种情况就会遇到优化器选择了扫描行数多的。

在索引那一期文章中知道主键索引是不需要回表的,找到值直接就返回对应的数据了。

而普通索引是需要先拿到主键值,再根据主键值获取对应的数据,这个过程优化器选择索引时需要计算的一个成本。

如何解决这种情况

扫描行数不准确时可以执行analyze table table_name命令,重新统计索引信息,达到预期优化器选择的索引。

二、索引选择异常如何处理

方案一

在MySQL中提供了force index来强制优化器使用这个索引。

使用方法:select * from table_name force index (idx_a) where a = 100;

但别误解force index的使用方法,之前在代码中看到这样一个案例,给查询列使用了函数操作导致使用不上索引,然后这哥们就直接使用force index,肯定不行的哈!

当优化器没有正确选择索引时是可以使用这种方案来解决。

缺点

使用force index的缺点相信大家也知道就是太死板,一旦索引名字改动就会失效。

方案二

删掉误选的索引,简单粗暴,很多索引建立其实也是给优化器的一个误导,直接删掉即可。

方案三

修改SQL语句,主动引导MySQL使用期望的索引,一般情况这种做法使用的很少除非你对系统十分熟悉,否则尽量少操作。

三、总结

优化器选择索引首先会根据扫描行数再由执行成本决定。

当索引统计信息不准确时,使用analyze table 解决。

优化器选择了错误的索引,只用force index来快速矫正,再通过优化SQL语句来引导优化器选择正确的索引,最暴力的手法是直接删除误选的索引。

坚持学习、坚持写作、坚持分享是咔咔从业以来所秉持的信念。愿文章在偌大的互联网上能给你带来一点帮助,我是咔咔,下期见。

五分钟,让你明白MySQL是怎么选择索引《死磕MySQL系列 六》的更多相关文章

  1. 聊聊MySQL的加锁规则《死磕MySQL系列 十五》

    大家好,我是咔咔 不期速成,日拱一卒 本期来聊聊MySQL的加锁规则,知道这些规则后可以判断SQL语句的加锁范围,同时也可以写出更好的SQL语句,防止幻读问题的产生,在能力范围内最大程度的提升MySQ ...

  2. MySQL强人“锁”难《死磕MySQL系列 三》

    系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 前言 最近数据库 ...

  3. 如何选择普通索引和唯一索引《死磕MySQL系列 五》

    系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 三.MySQL强 ...

  4. 字符串可以这样加索引,你知吗?《死磕MySQL系列 七》

    系列文章 三.MySQL强人"锁"难<死磕MySQL系列 三> 四.S 锁与 X 锁的爱恨情仇<死磕MySQL系列 四> 五.如何选择普通索引和唯一索引&l ...

  5. S 锁与 X 锁的爱恨情仇《死磕MySQL系列 四》

    系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 三.MySQL强 ...

  6. 为什么不让用join?《死磕MySQL系列 十六》

    大家好,我是咔咔 不期速成,日拱一卒 在平时开发工作中join的使用频率是非常高的,很多SQL优化博文也让把子查询改为join从而提升性能,但部分公司的DBA又不让用,那么使用join到底有什么问题呢 ...

  7. 为什么不建议给MySQL设置Null值?《死磕MySQL系列 十八》

    大家好,我是咔咔 不期速成,日拱一卒 之前ElasticSearch系列文章中提到了如何处理空值,若为Null则会直接报错,因为在ElasticSearch中当字段值为null时.空数组.null值数 ...

  8. 重重封锁,让你一条数据都拿不到《死磕MySQL系列 十三》

    在开发中有遇到很简单的SQL却执行的非常慢,甚至只查询一行数据. 咔咔遇到的只有两种情况,一种是MySQL服务器CPU占用率很高,所有的SQL都执行的很慢直到超时,程序也直接502,另一种情况是行锁造 ...

  9. 一生挚友redo log、binlog《死磕MySQL系列 二》

    系列文章 原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 一生挚友redo log.binlog<死磕MySQL系列 二> 前言 咔咔闲谈 上期根据 ...

随机推荐

  1. html jquey的选择器checkbox,select

    1 判断checkbox是否选中 用到 jquery的 is方法 jquery: <div id="divId" class="divTable"> ...

  2. 解决wampserver无法启动问题

    如果无法启动,找不到原因.直接依次点击打开到:控制面板--管理工具--事件查看器--windows日志--应用程序,查看对应进程错误信息对症下药即可. 我这个错误就是8099端口错误,运行cmd命令, ...

  3. win7下python2.7安装 pip,setuptools的正确方法

    windows7  下 0.先安装python2.7.13 32位:https://www.python.org/ftp/python/2.7.13/python-2.7.13.msi 64位:htt ...

  4. 第一次接触linux系统的你,必须要知道的概念

    linux系统一切皆为文件 linux系统一个多用户系统 没有消息就是好消息 linux系统目录结构 Linux文件系统采用带链接的树形目录结构,即只有一个根目录(通常用"/"表示 ...

  5. appium和selenium不同与相同之处

    原文来自: https://www.cnblogs.com/zhengshuheng/p/6370398.html selenium是web端的自动化,appium是app端的自动化,它继承了webd ...

  6. IOS 安装网页

    一般使用企业签名的iOS安装包 都需要一个下载地址,像蒲公英什么的 都有下载限制,所以求人不如求己. 内容也是复制别人的 :https://lzw.me/a/itms-services-ios-ins ...

  7. 🧚‍♂️全套Java教程_Java基础入门教程,零基础小白自学Java必备教程👨‍💻004 # 第四单元 流程控制语句上 #

    一.本单元知识点概述 二.本单元目标 (Ⅰ)重点知识目标 1.if语句的格式及执行流程2.switch语句的格式及执行流程 (Ⅱ)能力目标 1.掌握if语句的格式及执行流程2.掌握switch语句的格 ...

  8. 老板说,你给我1分钟内下载1000张图片!So,easy!

    上班的某一天,领导过来说!你帮下载一些图片资源,我以为就几张来着,原来是几十百来个网站要去保存图片!是要我把搞!!! 我们最常规的做法就是通过鼠标右键,选择另存为.但有些图片鼠标右键的时候并没有另存为 ...

  9. FastAPI(56)- 使用 Websocket 打造一个迷你聊天室

    背景 在实际项目中,可能会通过前端框架使用 WebSocket 和后端进行通信 这里就来详细讲解下 FastAPI 是如何操作 WebSocket 的 模拟 WebSocket 客户端 #!usr/b ...

  10. 2.1 附录--JVM指令手册

    栈和局部变量操作 将常量压入栈的指令 aconst_null 将null对象引用压入栈 iconst_m1 将int类型常量-1压入栈 iconst_0 将int类型常量0压入栈 iconst_1 将 ...