在MySQL中当有多个索引时 你知道MySQL是如何选择索引的吗 ???
在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天、每周,都会留下一些脚印,就是这些创作的内容,有一种执着,就是不知为什么,如果你迷茫,不妨来瞅瞅码农的轨迹。
- 优美的音乐节奏带你浏览这个效果的编码过程
- 坚持每一天,是每个有理想青年的追求
- 追寻年轻人的脚步,也许你的答案就在这里
- 如果你迷茫 不妨来瞅瞅这里
有一种业务场景就是 不断地删除历史数据和新增数据的,你会发现这个过程非常慢,你知道这是怎么回事吗 ?
1 索引普通查询
MySQL 中一张表可以支持多个索引,在 SQL 语句也并不主动指定使用的索引,具体使用哪个索引是由 MySQL 自己来选择的。
如下图所示,在这里我们有一张490多万数据的表
其中 user_id 添加的普通索引,如下图所示
然后当我执行查询语句
select * from question_extracting where user_id BETWEEN 670 AND 990
如下图所示
毫无疑问在执行上述这个查询时,user_id 上有索引,肯定是走的这个索引查询。
2 索引选错 查询耗时
如下图所示 ,在事务A中开启这个查询,然后同时事务B中删除数据,再插入数据,事务B中再开启同样的查询。
这两个事务的操作结果是,事务A中会开启user_id索引查询,而事务B中的查询就不会再使用user_id索引查询。
这是因为 MySql 选错了索引 。
在MySql中,优化器是负责来选择索引的,来决定使用哪个索引,从而找到一个最优的执行方案。
在执行过程中,扫描的行数越少,意味着访问磁盘数据的次数越少,消耗的 CPU 资源越少,反之就会多,体现的就是操作缓慢。
在上述两个事务的查询中,优化器需要考虑
- 使用索引 user_id,每次从索引 user_id上拿到一个值,然后回到主键索引上查出整行数
- 选择扫描 如100 万行(基数),是直接在主键索引上扫描的,没有额外的代价
优化器会估算这两个选择的代价,在这个查询中,优化器认为直接扫描主键索引更快,所以就出现了这个情况 ,原因就是没有准确的估算查询时间,或者说是没有准确估算扫描主键行数。
3 无法正确估算行数原因
一个索引上不同的值的个数,可称之为“基数“,可以使用 show index 方法,看到一个索引的基数,如下图所示我们看到这里 user_id的基数
在这里有两个值 M与N ,在 MySQL 中,有两种存储索引统计的方式:
- 参数 innodb_stats_persistent 设置为 on 的时候,表示统计信息会持久化存储。这时,默认的 N 是 20,M 是 10
- 设置为 off 的时候,表示统计信息只存储在内存中。这时,默认的 N 是 8,M 是 16
然后MySQL 在获取如上图所示的索引的基数,是InnoDB 引擎默认会选择 N 个数据页,统计这些页面上的不同值,得到一个 平均值,然后乘以这个索引的页面数,就得到了这个索引的基数(有一定的误差)。
也就是MySQL没有正确估算这个基数而导致的索引选错。
4 解决方法
在业务开发中,可以通过force index 显示的指定查询索引
# 未指定
EXPLAIN select * from question_extracting where user_id BETWEEN 670 AND 990# 显示指定
EXPLAIN select * from question_extracting force index(user_id) where user_id BETWEEN 670 AND 990
可通过 Explain 关键字来对比扫描索引基数,如下图所示,当两者的 rows 有较大差别时,可以考虑选择显示指定索引查询。(rows 这个字段表示的是预计扫描行数)
完毕
不局限于思维,不局限语言限制,才是编程的最高境界。
以小编的性格,肯定是要录制一套视频的,随后会上传
有兴趣 你可以关注一下 西瓜视频 — 早起的年轻人
在MySQL中当有多个索引时 你知道MySQL是如何选择索引的吗 ???相关推荐
- Mysql中求两个时间差的小时数以及mysql中substring_index 用法
Mysql中求两个时间差的小时数以及mysql中substring_index 用法 1.mysql中求两个时间的差,返回小时数:可以使用mysql的hour() 函数,具体如下: SQL code ...
- mysql中只运行一部分数据_MySQL(一)——MySQL基础和部分面试题
MySQL基础: 数据库的创建与删除 CREATE DATABASE ;//创建数据库 DROP DATABASE ;//删除数据库 数据库表的创建与删除 CREATE TABLE (column_n ...
- mysql中a b为什么是假_[灵魂拷问]MySQL面试高频问题(工程师方向)
前言 本文主要受众为开发人员,所以不涉及到MySQL的服务部署等操作,且内容较多,大家准备好耐心和瓜子矿泉水. 前一阵系统的学习了一下MySQL,也有一些实际操作经验,偶然看到一篇和MySQL相关的面 ...
- 在mysql中如何添加外键约束_如何在MySQL中设置外键约束
(1) 外键的使用: 外键的作用,主要有两个: 一个是让数据库自己通过外键来保证数据的完整性和一致性 一个就是能够增加ER图的可读性 有些人认为外键的建立会给开发时操作数据库带来很大的麻烦.因为数据库 ...
- mysql栏的范围外值,MySQL中各种字段的取值范围-数据库专栏,MySQL
mysql中各种字段的取值范围过节回来,网站更新的第一篇文章. 看来我有必要在最近找到一位志同道合的同学一起来维护站点才行了----------------------tinyint -128 – 1 ...
- Spark-SQL从MySQL中加载数据以及将数据写入到mysql中(Spark Shell方式,Spark SQL程序)
1. JDBC Spark SQL可以通过JDBC从关系型数据库中读取数据的方式创建DataFrame,通过对DataFrame一系列的计算后,还可以将数据再写回关系型数据库中. 1.1. 从MySQ ...
- mysql中两列拼接_python之Pandas读写操作mysql数据库
官方介绍:pandas的官方手册:https://pandas.pydata.org/pandas-docs/stable/pandas官方读写数据文档:https://pandas.pydata.o ...
- spark mysql 写_Spark-SQL从MySQL中加载数据以及将数据写入到mysql中(Spark Shell方式,Spark SQL程序)...
1. JDBC Spark SQL可以通过JDBC从关系型数据库中读取数据的方式创建DataFrame,通过对DataFrame一系列的计算后,还可以将数据再写回关系型数据库中. 1.1. 从MySQ ...
- mysql中12e10等于多少_一篇文章看懂mysql中varchar能存多少汉字、数字,以及varchar(100)和varchar(10)的区别...
看完这篇文章,你能搞清楚以下问题: 1.varchar(100)和varchar(10)的区别在哪里? 2.varchar能存多少汉字.数字? 3.varchar的最大长度是多少呢? 4.字符.字节. ...
最新文章
- 第一季度Teradata营收下降7.3% 利润下跌63%
- 蓝书4.1-4.4 树状数组、RMQ问题、线段树、倍增求LCA
- JAVA中return与finally的先后关系
- Eclipse变量名自动补全问题 自定义上屏按键为TAB
- 磁盘及文件系统的管理
- Docker容器虚拟化技术---Docker安装和操作1
- telegram定时消息_ActiveMQ(18):Message之延迟和定时消息投递
- 做网上商城项目的一点记录
- Linux之tr命令
- Create-React-App创建antd-mobile开发环境
- 银联接口的一些加密方式
- sql递归查询上级_递归的实际业务场景之MySQL 递归查询
- Python中DataFrame按照行遍历
- 【路径规划】基于matlab遗传结合模拟退火算法仓库拣货小车最优路径规划【含Matlab源码 649期】
- c语言求最长单调子序列,设计一个O(n2)时间算法,找出由n个数组成的序列的最长单调递增子序列...
- 图灵机停机问题的不可判定性
- Html网页制作图片选择
- 植物大战 类和对象 ——C++
- word文档中显示目录结构、插入目录
- WAMP Server Localhost Shows 500 Internal Server Error