MySql范围查找时,索引不生效问题原因

2023-11-04

1 问题描述

本文对建立好的复合索引进行排序,并取记录中非索引字段,发现索引不生效,例如,有如下表,DDL语句为:

CREATE TABLE `employees` (
  `emp_no` int(11) NOT NULL,
  `birth_date` date NOT NULL,
  `first_name` varchar(14) NOT NULL,
  `last_name` varchar(16) NOT NULL,
  `gender` enum('M','F') NOT NULL,
  `hire_date` date NOT NULL,
  `age` int(11) NOT NULL,
  PRIMARY KEY (`emp_no`),
  KEY `unique_birth_name` (`first_name`,`last_name`) USING BTREE
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

复合索引为unique_birth_name (first_name,last_name) 。使用以下语句:

EXPLAIN SELECT
    gender
FROM
    employees
ORDER BY
    first_name,
    last_name

这里写图片描述

根据上图:type:all 及 Extra:Using filesort 可得,索引没有生效。 
继续进行试验,对查询语句进一步改写,加上一个范围查找:

EXPLAIN SELECT
    gender
FROM
    employees
WHERE first_name > 'Leah'
ORDER BY
    first_name,
    last_name

执行计划显示如下图: 
这里写图片描述
这里发现结果和第一次sql分析无异。继续试验。 
改写sql语句:

EXPLAIN SELECT
    gender
FROM
    employees
WHERE first_name > 'Tzvetan'
ORDER BY
    first_name,
    last_name

这里写图片描述
此时,令人惊讶的是,索引生效了。

2 问题分析

此时,我们做一个大胆的猜测: 
第一次进行sql分析时,因为第一次order by 后,得到的还是全表数据,如果根据复合索引中携带的主键查找每一个gender进行拼接,自然很费资源和时间,mysql不会做如此蠢的事。不如直接进行全表扫描,把扫描到的每条数据和order by得到的临时数据进行拼接,从而得到需要的数据。 
为了验证上述想法的正确性,我们对三次sql进行分析。 
第一次sql根据复合索引得到的数据量为:300024,为全表数据

SELECT
    COUNT(first_name)
FROM
    employees
ORDER BY
    first_name,
    last_name

这里写图片描述

第二次改写的sql根据复合索引得到的数据量为:159149 , 为全表数据量的1/2。

SELECT
    COUNT(first_name)
FROM
    employees
WHERE first_name > 'Leah'
ORDER BY
    first_name,
    last_name

这里写图片描述 
第三次改写的sql根据复合索引得到的数据量为:36731, 为全表数据量的1/10。

SELECT
    COUNT(first_name)
FROM
    employees
WHERE first_name > 'Tzvetan'
ORDER BY
    first_name,
    last_name

这里写图片描述

通过对比发现,第二次改写的sql根据复合索引得到的数据量是全表数据量的1/2。此时还没有达到mysql使用索引进行二次查找的量级。第三次改写的sql根据复合索引得到的数据量是全表数据量的1/10,达到了mysql使用索引进行二次查找的量级,于是从执行计划上可以看到,第三次改写sql是走了索引的。

3 总结

mysql 是否根据首次索引条件查询出的主键进行二次查找,也是要看查询出来的数据量级,如果数据量接近全表数据量的话,就会进行全表扫描,否则根据第一次查询出来的主键进行二次查询。

 

 

https://blog.csdn.net/qq_25188255/article/details/81316498

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySql范围查找时,索引不生效问题原因 的相关文章

  • Android-数据在微调器中分配,但选择时不显示微调器中的值

    Problem我正在使用 Retrofit 从 mysql 获取一些产品类别 数据即将到来并在微调器中分配 但是当我选择一个项目时 它不会显示 在下拉菜单中 项目已分配 并且 setOnItemSelected 侦听器也正在工作 但所选项目
  • MySqlBulkLoader 说明

    你能告诉我什么吗MySqlBulkLoader的用途 在哪里以及如何使用它 一些例子也将不胜感激 请 MySQLBulkLoader是MySQL Connector Net类中的一个类 包装了MySQL语句LOAD DATA INFILE
  • MySQL:如何检索随机行或多个随机行?

    我有一个 MySQL 数据库表 用于存储照片的 URL 我需要从特定类型的数据库中提取 5 条随机记录 我可以像这样提取 5 条记录 SELECT Photos FROM Photos WHERE Photos Type ID 4 LIMI
  • 匹配 MySQL 中单词/后缀的相似/变体

    我如何匹配 MySQL 中单词的变体 例如搜索 accountancy 应匹配 accountant accountants accounting 等 我使用共享主机 因此无法向 MySQL 添加任何功能 例如 levenshtein 我想
  • 如何在 Flex 中对 PHP 字符串使用换行符

    这是我的 MXML
  • 连接两个表并保存到第三个sql

    我想加入两张桌子 TableA wordA primarykey countA abc 25 abcd 29 abcde 45 TableB wordB primarykey countB ab
  • Laravel 查询生成器 - 高级条件子句(可选参数)

    我需要带有接受可选参数的查询生成器的子句 例如 请考虑以下情况 我们有三个搜索字段 产品标题 公司名称和位置 邮政编码 城市或州 2 3 8 种可能性 该位置与 OR 连接 WHERE location postal code LIKE O
  • 使用java将数据插入mySQL表

    I have a predefined table in a mySQL database 我正在努力将从用户输入的数据保存到数据库中 但我似乎无法将任何数据保存在数据库中 使用以下代码 我尝试更新数据库的第一行 ID 1 到 OTHER
  • CSV 损坏,如何修复?

    我正在尝试解析 CSV 我想将它放入数据库或只是用 JavaScript 解析它 但由于语法损坏 任何一种方法都会失败 我的整个 CSV 文件在这里 https gist github com 1023560 https gist gith
  • UNION ALL mysql 子句中的行默认顺序?..我的意思是,首先提取哪一行?

    例如 如果我有一个真正简单的查询 选择1 联合所有 选择2 然后通过 Perl 或 PHP 获取行 我会将 1 作为第一行 将 2 作为第二行吗 这种行为在任何地方都有描述吗 Thanx 没有默认顺序 无论是在表中还是在查询中 除非您使用
  • 如何使用 Laravel 查询生成器在 WHERE 条件周围添加括号

    我使用 Laravel 查询构建器根据用户的过滤器选择动态过滤数据 query DB table readings foreach selections as selection query gt orWhere id selection
  • MySQL 主键是否已经处于某种默认顺序

    我刚刚在一个我刚刚开始使用的系统中偶然发现了几行我并不真正理解的代码 该系统有一个大表 可以保存大量具有唯一 ID 的实体 并在不再需要时将其删除 但绝不会重用它们 所以桌子看起来像这样 id info1 info2 info3 1 foo
  • MySQL存储过程错误意外字符“:”

    我有以下语句来创建存储过程 但我不断收到 位置 835 处出现意外字符 错误 语句中唯一的冒号位于 start loop 循环中 为什么我会收到此错误以及如何修复 DELIMITER CREATE DEFINER root localhos
  • 在没有条件的情况下,如何使查询不返回任何内容?

    相当简单 我有一对多 多对一关系 我想查询它 但是 当未提供任何 WHERE 子句信息时 我不希望返回任何结果 简单来说 如何使查询变得非贪婪 您可以添加一个始终为 false 的 where 子句 并附加您想要用 OR 提供的条件 sel
  • 如何通过csv文件仅更新sql表的一列

    我有一个 csv 文件包含一些数据 在我的 Sql 数据库中 我有一个具有多个列名的表 现在我只想通过 csv 文件更新一列 谢谢 你可以这样尝试 Import the csv file to a temp table Update you
  • 插入值数组

    我有一个具有可变数量值的数组 除了内部带有查询的循环之外 是否有更有效或更好的方法将它们插入到我的数据库中 At 这个网站 http www desilva biz mysql insert html 有一个很好的 MySQL 多插入查询示
  • 让网站登录也能在 WordPress 上使用

    我使用 PHP 和 MySQL 开发了一个网站 该网站已经有登录和注册表单 myweb com 我已经在这个网址添加了 wordpressmyweb com blog 我想禁用 WordPress 上的登录和注册页面并强制用户使用我的 基本
  • 如何使用索引优化 InnoDB 上的 COUNT(*) 性能

    我有一个较大但狭窄的 InnoDB 表 有大约 9m 条记录 正在做count or count id 桌子上的速度非常慢 6秒以上 DROP TABLE IF EXISTS perf2 CREATE TABLE perf2 id int
  • mysql中更新查询中的多个set和where子句

    我认为这是不可能的 因为我找不到任何东西 但我想我会在这里检查一下 以防我没有寻找正确的东西 我的数据库中有一个设置表 其中有两列 第一列是设置名称 第二列是值 我需要同时更新所有这些 我想看看是否有一种方法可以在一个查询的同时更新这些值
  • MySQL 中复制一条记录

    我有一个表 我想复制表中的特定行 我知道这不是最好的方法 但我们正在寻找快速解决方案 这比我最初想象的要难 我需要做的就是将整个记录复制到 MySql 中自动增量表中的新记录 而不需要指定每个字段 这是因为该表将来可能会发生变化 并且可能会

随机推荐

  • Educoder_web实训作业——写在最后

    今天终于把最后一章的web发了出来 这也是我第一次完整的将一个实训作业写成一个专栏推送 其实 这不是我第一次做关卡答案的文章了 上个学期Java实训的时候 由于当时自身也有很多题不是特别清楚 就上网搜了一下 没想到发现网上面已经有人开始再发
  • MFC中OnTimer定时器用法

    一 单个定时器用法 定时器工作主要流程 设置定时器SetTimer 时间到后调用OnTimer函数 关闭定时器KillTimer 可以在程序初始化用SetTimer函数弄成多个线程类似 并行进行多个函数功能 1 1 SetTimer H n
  • Python实现排队论——多坑位仿真(未使用仿真库,纯手写仿真)

    Python实现排队论 多坑位厕所 在一次偶然机会 接触到运筹学的排队论问题 于是简单尝试了一下硬撸代码 纯手打仿真 没有使用仿真库 建议大家可以学习Simpy库 用以仿真 一 案例 主要是基于 蒙特卡罗思想 求解 单坑位 排队等待时间问题
  • 动手做一个简单的智能小车

    动手做一个简单的智能小车 来到CNDN一年了 看到了许多大佬的杰出作品 也该写点什么来回馈给大家了前不久接触了单片机 想提前进行实践一下所以有想法做一个实体出来 想来想去难的怕自己搞不定 但是还好找到了志同道合的王同学 一起搞一个智能小车
  • 数据结构与算法课程笔记(十)

    实验十 图的存储结构与遍历 一 实验目的 二 实验环境 三 实验内容 一 实验目的 掌握图的邻接矩阵表示方法 理解基于邻接矩阵的深度优先 广度优先遍历方法的实现 掌握图的邻接表表示方法 理解基于邻接表的深度优先 广度优先遍历方法的实现 二
  • Java Socket 之 NIO

    对于 TCP 或 UDP 的服务器 如何实现并发处理客户端 最直观的想法就是为每个到来的请求 创建一个单独的线程来处理 但是这种方式未免太浪费资源了 那可以使用线程池来管理线程 这样可以节约资源 以 TCP 服务器举例 首先需要定义一个需要
  • C++ 穷举法

    今天我们来了解一下C 语言中 解决问题的一个较为常用的方法 穷举法 我们先来了解一下它的基本原理 再来做一些题目巩固一下 穷举又叫枚举 就是先确立一个范围 再把这个范围里的数 一个一个的带入题目中尝试 如果符合题目中的所有条件 那么这道题就
  • 读取Linux中I2C数据——c程序

    关于在Linux下读取I2C数据 该程序主要是在树莓派中读取AMG8833传感器中的64个温度数据 借鉴了一些网上的方法 然后参考芯片的数据手册 数据的存储格式 本芯片是2个字节存放一个数据 include
  • 搭建云原生环境

    1 安装准备工作 确保所有被安装服务器时区和时间一致 时间不一致会影响 Elasticsearch 和 Skywalking 等信息无法采集的情况出现 在各个服务器上安装时间同步命令工具 yum install ntp y 使用 ntpda
  • AJAX--XMLHttpRequest的方法

    AJAX XMLHttpRequest XMLHttpRequest是浏览器内置的一个构造函数 作用是 基于new出来的XMLsHttpRequest实例对象 可以发起Ajax的请求 axios中的axios get axios post
  • CSS Grid布局:合并单元格布局

    CSS Grid布局 网格单元格布局 一文中通过一些简单的实例介绍了如何给容器定义网格 并且怎么使用网格线或者网格区域来实现单元格这样的简单的布局 在文章结尾之处也提到过 这样的单元格如同表格一样 仅仅一个个独立的单元格是无法满足一些复杂的
  • 软件测试基础

    软件测试基础 一 软件测试基础理论 1 软件测试的必要性 所有的产品或者服务上线都需要测试 2 测试的发展过程 3 什么是软件测试 找bug 发现缺陷 4 测试的定义 使用人工或自动的手段来运行或者测试某个系统的过程 目的在于检测它是否满足
  • JSON parse error: Cannot deserialize instance of `java.util.ArrayList

    前言 今天测试接口 JSON里面有个集合 一直报错如下所示 name 到底怎么回事呢 status 0 tenantId 123 createId 123 modifyId 123 labelItemRelations itemId 111
  • 为什么Vue中data一定要是一个函数?

    1 什么是函数 函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块 js函数语法 函数就是包裹在花括号中的代码块 前面使用了关键词 function 当调用该函数时 会执行函数内的代码 可以在某事件发生时直接调用函数 比如当用户点击
  • Android--- Layout

    Android Layout Linear Layout Relative Layout Table Layout Grid Layout Frame Layout Constraint Layout Linear Layout
  • 【Java实践】java实现注册表单处理

    import java io IOException import javax servlet ServletException import javax servlet http HttpServlet import javax serv
  • android 仿钉钉日历,仿钉钉左右滑动日历

    先上我的效果图 再说思路 我这里不贴代码 思路 懂了 不管用前端还是移动端 都可以做出来的 做这个左后滑动的日历之前 首先无从下手的 有两个地方 第一 该怎么实现 左右滑动效果 第二 展示的日期是怎么计算的 因为我们是用ionic2 写的项
  • 【Docker+Mysql】docker搭建的mysql8.0中文乱码问题

    环境 CentOS 7 mysql docker 问题描述 查询数据库时 发现服务器端数据出现中文乱码问题 所有中文显示成问号 导致我的接口访问使用从数据库中读取出来的数据无法处理 解决过程 使用Docker搭建mysql容器 和不使用Do
  • 【python爬虫】1.爬虫基础知识

    文章目录 前言 初识爬虫 什么是爬虫 为什么需要爬虫 明晰路径 浏览器的工作原理 爬虫的工作原理 体验爬虫 requests get Response对象的常用属性 爬虫伦理 总结 前言 很高兴能在这里遇见你 我将会带你学习网络爬虫 我们可
  • MySql范围查找时,索引不生效问题原因

    1 问题描述 本文对建立好的复合索引进行排序 并取记录中非索引字段 发现索引不生效 例如 有如下表 DDL语句为 CREATE TABLE employees emp no int 11 NOT NULL birth date date N