【数据库】组合索引生效规则及索引失效

文章目录

  • 索引演示示例
  • 组合索引
  • 索引失效

索引演示示例

# 创建表结构
CREATE TABLE Employees (EmployeeID INT PRIMARY KEY,FirstName VARCHAR(50),LastName VARCHAR(50),DepartmentID INT,Salary DECIMAL(10, 2),HireDate DATE
);
# 插入示例数据
INSERT INTO Employees (EmployeeID, FirstName, LastName, DepartmentID, Salary, HireDate) VALUES
(1, 'John', 'Doe', 10, 50000.00, '2023-01-01'),
(2, 'Jane', 'Smith', 10, 60000.00, '2023-02-01'),
(3, 'Alice', 'Johnson', 20, 55000.00, '2023-03-01'),
(4, 'Bob', 'Brown', 20, 70000.00, '2023-04-01'),
(5, 'Charlie', 'Davis', 30, 80000.00, '2023-05-01'),
(6, 'Emily', 'Davis', 10, 52000.00, '2023-06-01'),
(7, 'Michael', 'Brown', 10, 58000.00, '2023-07-01'),
(8, 'Sarah', 'Miller', 20, 62000.00, '2023-08-01'),
(9, 'David', 'Wilson', 20, 65000.00, '2023-09-01'),
(10, 'Jessica', 'Taylor', 30, 72000.00, '2023-10-01'),
(11, 'Matthew', 'Anderson', 30, 75000.00, '2023-11-01'),
(12, 'Olivia', 'Jackson', 10, 54000.00, '2023-12-01'),
(13, 'Daniel', 'Thomas', 10, 56000.00, '2024-01-01'),
(14, 'Sophia', 'Moore', 20, 60000.00, '2024-02-01'),
(15, 'Ethan', 'Martin', 20, 68000.00, '2024-03-01'),
(16, 'Mia', 'Thompson', 30, 78000.00, '2024-04-01'),
(17, 'James', 'White', 30, 82000.00, '2024-05-01'),
(18, 'Ava', 'Harris', 10, 53000.00, '2024-06-01'),
(19, 'Noah', 'Robinson', 10, 57000.00, '2024-07-01'),
(20, 'Isabella', 'Clark', 20, 63000.00, '2024-08-01');

组合索引

-- 创建组合索引
CREATE INDEX idx_lastname_dept ON Employees (LastName, DepartmentID);
CREATE INDEX idx_salary_dept ON Employees (Salary, DepartmentID);
CREATE INDEX idx_lastname_firstname ON Employees (LastName, FirstName);

推荐文章:MySQL高级(一) EXPLAIN用法和结果分析:https://blog.csdn.net/why15732625998/article/details/80388236

在这里插入图片描述

  • id 表的读取顺序
  • select_type 查询类型,区别普通查询、联合查询、子查询等的复杂查询
  • type 查询级别 system > const > eq_ref > ref > range > index > all
  • possible_keys 哪些索引可以使用
  • key 哪些索引被实际使用
  • rows 每张表有多少行被优化器查询

组合索引的生效规则主要基于以下几点:

一、左前缀原则

  • 左前缀匹配:查询必须从索引的最左边的列开始,并且是连续的。这意味着如果要使组合索引生效,查询条件至少需要包含索引中最左边的列。

    EXPLAIN SELECT * FROM Employees WHERE LastName = 'Jane';
    EXPLAIN SELECT * FROM Employees WHERE LastName = 'Jane' AND DepartmentID = 10;
    
  • 不遵循左前缀的情况:如果查询没有使用索引最左边的列或者跳过了中间的列,则不会使用整个索引

    EXPLAIN SELECT * FROM Employees WHERE DepartmentID = 10;
    

二、范围条件的影响

  • 范围条件限制后续列的使用:一旦在组合索引中遇到了范围条件(如>, <, BETWEEN等),那么该范围条件后的所有列将不再参与索引的选择过程。这是因为数据库引擎在处理范围条件时,无法再有效地利用后续的列来进行精确匹配。
EXPLAIN SELECT * FROM Employees WHERE Salary > 60000 AND DepartmentID = 30;

在这里插入图片描述

Using index condition 说明 MySQL 正在利用索引条件下推(Index Condition Pushdown, ICP)技术来优化查询。在这种情况下,即使 DepartmentID = 30 不是通过索引来直接定位数据的,MySQL 也会将这个条件“下推”到存储引擎层,在存储引擎层进行额外的过滤。

三、覆盖索引

  • 覆盖索引:如果查询的所有列都在索引中定义了,那么数据库可以直接从索引中读取数据,而不需要回表访问原数据行。这称为覆盖索引,它可以极大地提高查询性能。
EXPLAIN SELECT Salary, DepartmentID FROM Employees WHERE Salary = 70000 AND DepartmentID = 20;
EXPLAIN SELECT LastName, FirstName FROM Employees WHERE LastName = 'Johnson' AND FirstName = 'Alice';

这个查询可以从索引idx_name(column1, column2)中直接获取column1column2的数据,而不需要访问表中的其他列。因为减少了I/O操作,显著提高查询性能。

四、优化器决策

  • 优化器选择:最终是否使用某个索引还取决于数据库查询优化器的判断。优化器会根据统计信息、执行计划成本等因素来决定最佳的执行计划。有时候即使符合以上规则,优化器也可能选择不使用索引,因为可能有更优的执行路径。

索引失效

某些语法或查询条件可能会导致索引不生效。以下是一些常见的情况,其中索引可能不会被使用:

1、使用函数

如果在列上应用了函数,索引通常不会生效。例如:

EXPLAIN SELECT * FROM Employees WHERE UPPER(LastName) = 'Johnson';
# 可改写查询为:
EXPLAIN SELECT * FROM Employees WHERE LastName = 'Johnson';

2、不等操作符

使用不等操作符(如!=, <>)通常会导致索引不生效。例如:

EXPLAIN SELECT * FROM Employees WHERE salary != 50000;

在这种情况下,数据库引擎可能会选择全表扫描。

3、LIKE 通配符

LIKE语句以通配符开头时,索引通常不会生效。例如:

-- `LIKE`语句以通配符开头数据库引擎无法利用索引来快速定位匹配的行
EXPLAIN SELECT * FROM Employees WHERE LastName LIKE '%Doe%';
-- 可改写查询为:
EXPLAIN SELECT * FROM Employees WHERE LastName LIKE 'Doe%';

4、OR 条件

当使用OR条件时,如果其中一个条件不能使用索引,那么整个查询可能都不会使用索引。例如:

EXPLAIN SELECT * FROM Employees WHERE (salary > 50000 OR HireDate = '2024-08-01');

5、范围条件后的列

在组合索引中,一旦遇到范围条件(如>, <, BETWEEN),后续的列将不会被用于索引的选择过程。例如:

EXPLAIN SELECT * FROM Employees WHERE Salary > 60000 AND DepartmentID = 30;

在这个查询中,Salary上的范围条件使得DepartmentID这一列不会被用于索引选择。

6、数据类型不匹配

如果查询中的数据类型与列的数据类型不匹配,索引可能不会生效。

-- 如果`DepartmentID`是整数类型,而查询中使用了字符串,这会导致索引失效
SELECT * FROM Employees WHERE DepartmentID = '20';
-- 可改写查询为:
SELECT * FROM Employees WHERE DepartmentID = 20;

7、隐式类型转换

隐式类型转换也可能导致索引失效。

-- 如果`HireDate`是日期类型,而查询中使用了字符串,这会导致隐式类型转换从而可能使索引失效
SELECT * FROM Employees WHERE HireDate = '2023-01-01';
-- 正确的做法:
SELECT * FROM Employees WHERE HireDate = DATE '2023-01-01';

8、大量结果集

如果查询返回的结果集非常大(例如超过表的一定比例),数据库优化器可能会选择全表扫描而不是使用索引。这是因为全表扫描在这种情况下可能更高效。

9、使用 NOT INNOT EXISTS

使用NOT INNOT EXISTS子查询时,索引可能不会生效。

SELECT * FROM Employees WHERE DepartmentID NOT IN (SELECT DepartmentID FROM Departments WHERE location = 'New York');

10、使用 ORDER BYGROUP BY

如果ORDER BYGROUP BY中的列不在索引中,或者顺序与索引顺序不一致,索引可能不会生效。

-- 如果只有`LastName`上有索引,而没有包含`FirstName`,那么 `ORDER BY`可能不会使用索引
SELECT * FROM Employees ORDER BY LastName, FirstName;
-- 可以创建一个复合索引来解决这个问题:
CREATE INDEX idx_LastName_FirstName ON Employees (LastName, FirstName);

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

力扣 LeetCode 145. 二叉树的后序遍历(Day6:二叉树)

解题思路&#xff1a; 方法一&#xff1a;递归&#xff08;左右中&#xff09; class Solution {List<Integer> res new ArrayList<>();public List<Integer> postorderTraversal(TreeNode root) {recur(root);return res;}public void recur(TreeNode ro…

用指针遍历数组

#include<stdio.h> int main() {//定义一个二维数组int arr[3][4] {{1,2,3,4},{2,3,4,5},{3,4,5,6},};//获取二维数组的指针int (*p)[4] arr;//二维数组里存的是一维数组int[4]for (int i 0; i < 3; i){//遍历一维数组for (int j 0; j <4; j){printf("%d &…

[HCTF 2018]Warmup 详细题解

知识点: 目录穿越_文件包含 static静态方法 参数传递引用 mb_strpos函数 mb_substr函数 正文: 页面有一张 滑稽 的表情包,查看一下页面源代码,发现提示 那就访问/source.php 得到源码 <?phphighlight_file(__FILE__);class emmm{public static function checkFil…

从0-1训练自己的数据集实现火焰检测

随着工业、建筑、交通等领域的快速发展,火灾作为一种常见的灾难性事件,对生命财产安全造成了严重威胁。为了提高火灾的预警能力,减少火灾损失,火焰检测技术应运而生,成为火灾监控和预防的有效手段之一。 传统的火灾检测方法,如烟雾探测器、温度传感器等,存在响应时间慢…

小程序20-样式:自适应尺寸单位 rpx

手机设备的宽度逐渐多元化&#xff0c;也就需要开发者开发过程中&#xff0c;去适配不同屏幕宽度的手机&#xff0c;为了解决屏幕适配问题&#xff0c;微信小程序推出了 rpx 单位 rpx&#xff1a;小程序新增的自适应单位&#xff0c;可以根据不同设备的屏幕宽度进行自适应缩放 …

在Ubuntu系统中,默认情况下会安装`apt`作为包管理工具(Advanced Package Tool)

文章目录 方法一&#xff1a;使用命令行检查apt是否存在方法二&#xff1a;尝试运行一个apt命令方法三&#xff1a;查看包列表如果apt没有安装主要功能高级用法注意事项 在Ubuntu系统中&#xff0c;默认情况下会安装 apt作为包管理工具。你可以通过以下几种方法来检查系统中是…

Github 2024-11-16Rust开源项目日报 Top10

根据Github Trendings的统计,今日(2024-11-16统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10Go项目1Python项目1Lapce:用 Rust 编写的极快且强大的代码编辑器 创建周期:2181 天开发语言:Rust协议类型:Apache License 2.0St…

C++:基于红黑树封装map和set

目录 红黑树的修改 红黑树节点 红黑树结构 红黑树的迭代器 红黑树Insert函数 红黑树的默认成员函数 修改后完整的红黑树 set、map的模拟实现 set map 测试封装的set和map 红黑树的修改 想要用红黑树封装map和set&#xff0c;需要对之前实现的key-value红黑树进行修…

LeetCode 3240.最少翻转次数使二进制矩阵回文 II:分类讨论

【LetMeFly】3240.最少翻转次数使二进制矩阵回文 II&#xff1a;分类讨论 力扣题目链接&#xff1a;https://leetcode.cn/problems/minimum-number-of-flips-to-make-binary-grid-palindromic-ii/ 给你一个 m x n 的二进制矩阵 grid 。 如果矩阵中一行或者一列从前往后与从后…

在kile 5中一个新工程的创建

这两天博主学习到了在kile5中创建一个工程&#xff0c;当然博主不会忘了小伙伴们的&#xff0c;这就和你们分享。 本次创建以STM32F103C8为例 创建过程&#xff1a; 1首先创建文件 名字随意&#xff0c;但也不要太随意&#xff0c;因为是外国软件&#xff0c;所以多少对中文…

深度学习工具和框架详细指南:PyTorch、TensorFlow、Keras

引言 在深度学习的世界中&#xff0c;PyTorch、TensorFlow和Keras是最受欢迎的工具和框架&#xff0c;它们为研究者和开发者提供了强大且易于使用的接口。在本文中&#xff0c;我们将深入探索这三个框架&#xff0c;涵盖如何用它们实现经典深度学习模型&#xff0c;并通过代码…

2024-11-16 特殊矩阵的压缩存储

一、数组的存储结构 1.一维数组&#xff1a;各元素大小相同&#xff0c;且物理上连续存放。a[i]起始地址i*siezof(数组元素大小) 2.二维数组&#xff1a;b[j][j]起始地址&#xff08;i*Nj&#xff09;*sizeof(数组元素大小) 二、特殊矩阵 1.普通矩阵的存储&#xff1a;使用…

ISCTF2024

ezlogin 源码审计 先审源码,纯js题 const express require(express); const app express(); const bodyParser require(body-parser); var cookieParser require(cookie-parser); var serialize require(node-serialize); app.use(bodyParser.urlencoded({ e…

leetcode226:反转二叉树

给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 示例 1&#xff1a; 输入&#xff1a;root [4,2,7,1,3,6,9] 输出&#xff1a;[4,7,2,9,6,3,1]示例 2&#xff1a; 输入&#xff1a;root [2,1,3] 输出&#xff1a;[2,3,1]示例 3&#x…

Excel365和WPS中提取字符串的五种方法

一、问题的提出 如何在WPS或者Excel365中提取A列指定的字符串&#xff0c;从"面"开始一直到".pdf"? 问题的提出 二、问题的分析 我们可以采用多种方法解决这个问题&#xff0c;由于A列到B列的提取是非常有规律的&#xff0c;因此我们可以采用如下几种方…

下载jakarta-taglibs-standard-current.zip

官网&#xff1a;https://archive.apache.org/dist/jakarta/taglibs/standard/binaries/ 下载版本&#xff1a;

Qt信号和槽

信号和槽的概念 在Linux中我们也学过信号 Signal&#xff0c;这是进程间通信的一种方式&#xff0c;这里大致分为三个要素&#xff1a; 信号源&#xff1a;谁发送的信号&#xff08;用户进程&#xff0c;系统内核&#xff0c;终端或者作业控制&#xff0c;&#xff09; 信号的类…

MATLAB绘图

一、实验内容和步骤 MATLAB的图形功能非常强大&#xff0c;可以对二维、三维数据用图形表现&#xff0c;并可以对图形的线形、曲面、视觉、色彩和光线等进行处理。 1、绘制二维曲线 绘制如下图所示的图形&#xff0c;把图形窗口分割为2列2行&#xff0c;在窗口1中绘制一条正弦…

H3C NX30Pro刷机教程-2024-11-16

H3C NX30Pro刷机教程-2024-11-16 ref: http://www.ttcoder.cn/index.php/2024/11/03/h3c-nx30pro亲测无需分区备份 路由器-新机初始化设置路由器登录密码telnet进入路由器后台 刷机上传uboot到路由器后台在Windows环境下解压后的软件包中打开 tftpd64.exe在NX30Pro环境下通过以…

boost之property

简介 property在boost.graph中有使用&#xff0c;用于表示点属性或者边属性 结构 #mermaid-svg-56YI0wFLPH0wixrJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-56YI0wFLPH0wixrJ .error-icon{fill:#552222;}#me…