【MySQL】索引 面试题

文章目录

      • 适合创建索引的情况
      • 创建索引的注意事项
      • MySQL中不适合创建索引的情况
      • 索引失效的常见情况

在这里插入图片描述

  1. 索引定义与作用

    • 索引是帮助MySQL高效获取数据的有序数据结构,通过维护特定查找算法的数据结构(如B+树),以某种方式引用数据,实现高级查找算法,从而提高数据检索效率,降低数据库IO成本。
    • 例如在查找年龄为45的数据时,无索引需逐条比对,有索引(如二叉树)可减少对比次数,提升效率。
  2. 二叉树与红黑树的不足
    在这里插入图片描述

    • 二叉树:普通二叉树时间复杂度不稳定,可能退化为链表(O(n)),即使相对平衡时为O(log n),也不满足MySQL需求,所以MySQL底层未使用。
    • 红黑树:节点可保证平衡,时间复杂度稳定为O(log n),但数据量大(如1000万数据)时,因其二叉结构节点分叉有限,树会很高,查找需找很多层级,效率不高。
  3. B树的特点
    在这里插入图片描述

    • B树是多岔路平衡查找树,每个节点可有多分支(如度数为五时,最多五个子节点),节点上最多存储一定数量的key(如四个),key有指针指向子节点数据,且存储对应数据。整体为“矮胖”结构,查找层级短,效率高。
  4. B+树的结构与优势

在这里插入图片描述
- 结构优化:在B树基础上优化,更适合外存储索引结构(如InnoDB存储引擎默认采用)。非叶子节点只存储指针,不存储数据,存储压力低;数据只存储在叶子节点,非叶子节点主要起导航作用,便于找到叶子节点数据。
- 磁盘读写代价低:查找数据时,B树需加载路径上节点数据,B+树非叶子节点不存数据,只需通过指针导航找到叶子节点获取数据,无需额外加载非叶子节点数据,效率更高,磁盘读写代价更低。
- 查找效率稳定:所有数据在叶子节点,查找时从根节点依次对比到叶子节点获取数据,查找路径相似,效率稳定。
- 便于扫库和区间查询:叶子节点之间使用双向指针连接,进行范围查询(如查询6 - 34区间数据)时,从根节点找到起始值所在叶子节点后,可利用双向指针一次性获取区间内所有数据,无需多次从根节点查找,效率更高。

  1. 面试题回答要点
    • 索引定义及作用方面:强调索引是有序数据结构,用于高效获取数据,可提高检索效率、降低IO成本(因B+树查找层级短),还能通过索引排序降低数据排序成本,间接降低CPU消耗(创建索引时已排序)。
    • 索引底层数据结构方面:说明MySQL的InnoDB引擎默认采用B+树存储索引,其特点包括阶数多、路径短(性能高)、磁盘读写代价低(非叶子节点只存指针,数据在叶子节点)以及便于扫库和区间查询(叶子节点间双向链表)。

在这里插入图片描述


在MySQL中,合适地创建索引可以显著提高查询性能,但索引也并非越多越好,不当的索引可能会影响数据插入、更新和删除的效率。以下是一些适合创建索引的常见情况:

适合创建索引的情况

  1. 频繁作为查询条件的列:如果某列经常出现在WHERE子句中,作为查询条件,那么为该列创建索引可以加快查询速度。
  2. 经常用于连接(JOIN)操作的列:在多表连接查询中,连接条件列通常应该创建索引,以加速连接操作。例如,在一个订单表和用户表的连接查询中,订单表的用户ID列和用户表的主键列(通常也是用户ID)都应该创建索引,这样可以快速定位匹配的行,提高连接性能。
  3. 在分组(GROUP BY)和排序(ORDER BY)操作中使用的列:当查询需要进行分组或排序操作时,为参与分组和排序的列创建索引可以避免数据库进行额外的排序操作,从而提高查询性能。例如,在查询每个部门的员工数量并按照部门名称排序时,为部门名称列创建索引可以加速分组和排序过程。
  4. 查询返回结果集较小的列:如果一个查询返回的结果集相对较小,但查询条件涉及的列数据量较大,创建索引可以帮助快速定位到满足条件的少量行,从而提高查询效率。例如,在一个包含大量商品信息的表中,根据商品类别查询特定类别下的少数热门商品,为商品类别列创建索引可以快速筛选出相关商品。
  5. 唯一约束列:对于具有唯一性约束的列,数据库通常会自动创建唯一索引,这不仅有助于确保数据的唯一性,还能提高基于该列的查询速度,因为数据库可以直接使用索引快速定位到特定的值。例如,用户表中的用户名或邮箱列,通常需要保证唯一性,并且在用户登录或查询特定用户时,这些列经常被使用,因此创建唯一索引是很有必要的。

创建索引的注意事项

  1. 避免过度索引:每个索引都会占用一定的存储空间,并在数据插入、更新和删除时需要额外的维护成本。如果为太多列创建索引,可能会影响数据库的整体性能,特别是在写操作频繁的表上。因此,只应该为那些真正需要提高查询性能的列创建索引。
  2. 选择合适的数据类型:索引列的数据类型会影响索引的性能。尽量使用简单、占用空间小的数据类型,例如整数类型通常比字符串类型在索引查找上更高效。如果可能的话,对于字符串类型列,可以考虑使用合适的前缀索引,而不是对整个字符串创建索引,以减少索引占用的空间和提高查询性能。
  3. 复合索引的使用:在创建索引时,有时候可以考虑创建复合索引(即包含多个列的索引)。复合索引适用于经常同时根据多个列进行查询的情况。但要注意索引列的顺序,应该将选择性高(即不同值较多)的列放在前面,这样可以更快地缩小查询范围。例如,如果经常根据城市和地区查询用户信息,并且城市的选择性高于地区,那么创建索引时应该先写城市列,再写地区列。
  4. 定期维护索引:随着数据的不断更新和插入,索引可能会变得碎片化,影响查询性能。因此,需要定期对索引进行维护,例如使用OPTIMIZE TABLE语句来重建和优化索引,以确保索引的效率。

MySQL中不适合创建索引的情况

  1. 数据量较小的表:如果表中的数据量非常小,例如只有几十条或几百条记录,全表扫描的速度可能比使用索引更快。因为使用索引需要额外的开销来维护索引结构,在数据量小时,这个开销可能超过索引带来的查询性能提升。例如,一个存储系统配置参数的小表,数据很少变动且查询频率不高,此时创建索引可能得不偿失。
  2. 频繁更新、插入或删除的列:对频繁进行写操作的列创建索引会增加数据库的维护成本。每次数据更新、插入或删除时,数据库都需要更新相关索引,这会影响写操作的性能。例如,在一个记录用户操作日志的表中,操作时间戳列经常更新,若为该列创建索引,会显著降低写操作速度。
  3. 区分度低的列:如果某列的取值非常有限,例如只有“男”“女”两种值,或者大部分值都相同,创建索引的效果可能不佳。因为索引在这种情况下无法有效缩小查询范围,数据库可能仍需扫描大量数据行。例如,一个员工表中的性别列,通常不适合创建索引(除非在特定场景下有特殊需求)。
  4. 数据行数频繁变动且分布不均匀的列:如果列的数据分布极不均匀,且数据行数经常变动,索引可能会频繁进行重新平衡和优化,这会消耗数据库资源。例如,某电商网站订单表中的订单状态列,可能大部分订单处于“已完成”状态,且新订单不断增加,状态频繁更新,此时为该列创建索引可能不利于性能优化。
  5. 长字符串列或大文本列:对于非常长的字符串列(如存储文章内容的列)或大文本列(如存储用户评论的列),创建索引会占用大量的存储空间,并且在查询时比较操作也会消耗较多资源,索引的维护成本较高。通常,只在需要根据这些列进行精确查询且查询频率较高时,才考虑创建索引,且可能更适合使用前缀索引等方式来减少索引大小。
  6. 查询中很少使用的列:如果某列在实际查询中很少被作为查询条件或连接条件使用,那么为其创建索引没有实际意义,反而会增加数据库的存储和维护负担。例如,一个产品表中有一个“产品介绍”列,该列主要用于展示产品详情,很少在查询中用到,就不需要为其创建索引。

索引失效的常见情况

  1. 使用函数或表达式对索引列进行操作:如果在查询条件中对索引列使用了函数(如SUBSTRINGDATE_FORMAT等)或表达式(如age + 1 = 30),索引可能失效。因为索引是基于列的原始值构建的,经过函数或表达式计算后,数据库无法直接使用索引进行快速定位。例如:
SELECT * FROM users WHERE SUBSTRING(name, 1, 3) = 'abc';

在这个查询中,对name列使用了SUBSTRING函数,即使name列有索引,数据库也可能无法有效利用该索引,导致查询效率降低。
2. 隐式类型转换:当查询条件中索引列的数据类型与实际传入的值的数据类型不匹配时,数据库可能会进行隐式类型转换,这可能导致索引失效。例如,如果age列是整数类型,而查询条件写成WHERE age = '30'(传入的是字符串类型),数据库会先将字符串转换为整数再进行比较,这种隐式转换可能使索引无法正常使用。
3. 对索引列进行运算:在查询条件中对索引列进行算术运算(如salary * 2 > 5000),会使索引失效。因为数据库需要先计算表达式的值,然后再进行比较,无法直接利用索引进行快速查找。
4. 使用OR连接多个条件,且其中有索引列和非索引列的条件:如果在WHERE子句中使用OR连接多个条件,并且其中既有索引列的条件又有非索引列的条件,那么索引可能失效。例如:

SELECT * FROM users WHERE age = 30 OR address = 'Beijing';

如果age列有索引,address列没有索引,这个查询可能不会使用age列的索引,因为OR操作使得数据库难以优化查询。
5. LIKE查询以通配符开头:当使用LIKE进行模糊查询时,如果通配符%在查询字符串的开头,索引可能失效。例如:

SELECT * FROM products WHERE product_name LIKE '%phone';

这种查询会导致数据库进行全表扫描,因为索引无法快速定位以通配符开头的数据。
6. 索引列参与了表达式计算或函数调用:与使用函数或表达式对索引列进行操作类似,只要索引列参与了表达式计算或函数调用,索引就可能无法正常工作。例如:

SELECT * FROM orders WHERE YEAR(order_date) = 2023;

这里对order_date列使用了YEAR函数,会使该列的索引失效。
7. IS NULLIS NOT NULL条件对索引列的使用:在某些数据库中,对索引列使用IS NULLIS NOT NULL条件可能导致索引失效,因为索引可能不包含空值的相关信息。不过,有些数据库对这种情况进行了优化,具体是否失效取决于数据库的实现。
8. 索引列使用不等于(!=<>)操作符:如果在查询条件中对索引列使用不等于操作符,数据库可能认为使用索引的成本较高,而选择全表扫描,导致索引失效。例如:

SELECT * FROM employees WHERE salary!= 5000;
  1. 查询条件中的数据分布不均匀导致索引选择不佳:如果索引列的数据分布非常不均匀,例如某一列大部分值都相同,只有少数不同的值,数据库在查询时可能认为使用索引的效果不如全表扫描,从而不使用索引。这种情况相对较少见,但在某些特定的数据场景下可能发生。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Excel制作通达信自定义“序列数据“

序列数据的视频教程演示 Excel制作通达信自定义序列数据 1.序列数据的制作方法&#xff1a;删掉没有用的数据&#xff08;行与列&#xff09;和股代码格式处理&#xff0c;是和外部数据的制作方法是相同&#xff0c;自己上面看历史博文。只需要判断一下&#xff0c;股代码跟随的…

【ELK】ES单节点升级为集群模式--太细了!

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言准备工作1. 查看现状【单节点】2. 原节点改集群模式3. 改es配置文件&#xff0c;增加集群相关配置项4. *改docker映射的端口* 启动新节点5. docker-compose起一…

关于区块链的安全和隐私

背景 区块链技术在近年来发展迅速&#xff0c;被认为是安全计算的突破&#xff0c;但其安全和隐私问题在不同应用中的部署仍处于争论焦点。 目的 对区块链的安全和隐私进行全面综述&#xff0c;帮助读者深入了解区块链的相关概念、属性、技术和系统。 结构 首先介绍区块链…

webauthn介绍及应用

1、webauthn介绍 官网&#xff1a;https://webauthn.io/ 1.1、什么是webauthn&#xff1f; webauthn即Web Authentication&#xff0c;是一个符合W3C标准的Web认证规范。它通过公私钥加密技术&#xff0c;实现无密码认证&#xff0c;用户仅需通过pin码、指纹、面部识别、usb …

ElasticSearch如何做性能优化?

大家好&#xff0c;我是锋哥。今天分享关于【ElasticSearch如何做性能优化?】面试题。希望对大家有帮助&#xff1b; ElasticSearch如何做性能优化? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Elasticsearch 是一个开源的分布式搜索引擎&#xff0c;广泛用于…

Python 高级游戏开发:构建一个基于 Pygame 的多人在线战斗游戏

在本篇文章中,我们将介绍如何使用 Python 和 Pygame 库开发一个具有多人在线功能的高级游戏。我们将涵盖如何搭建游戏服务器,如何实现客户端-服务器模型,以及如何处理网络通信和游戏逻辑。这不仅能帮助你提升游戏开发技能,还能加深对 Python 网络编程的理解。 一、准备工作…

瑞芯微全新芯片平台RK3506优势详解,高集成低功耗,为工业而生 触觉智能测评

RK3506是瑞芯微Rockchip在2024年第四季度全新推出的Arm嵌入式芯片平台&#xff0c;三核Cortex-A7单核Cortex-M0多核异构设计&#xff0c;CPU频率达1.5Ghz, M0 MCU为200Mhz。 而RK3506芯片平台下的工业级芯片型号RK3506J&#xff0c;具备-40-85℃的工业宽温性能、发热量小&#…

CentOS7 初始化模板

一、下载Centos7的qcow2镜像 CentOS Cloud Images qemu-img.exe convert -f qcow2 -O vmdk CentOS-7-x86_64-GenericCloud-2211.qcow2 centos7.vmdk 二、更改root密码 注意由于有cloud init的原因&#xff0c;按网上进入救援模式的办法无法修改密码&#xff0c;会卡住不动。…

Docker 安装全攻略:从入门到上手

Docker 安装全攻略&#xff1a;从入门到上手 在当今的软件开发与部署领域&#xff0c;Docker 已经成为了一项不可或缺的关键技术。它能够将应用程序及其依赖项打包成轻量级、可移植的容器&#xff0c;极大地简化了开发、测试和部署的流程。本文将详细讲解在不同操作系统下 Doc…

代码随想录算法训练营第六十天 | 图 | A星算法

Day 60 总结 自己实现中遇到哪些困难今日收获&#xff0c;记录一下自己的学习时间 13:00 - 14:00 BFS 题目&#xff1a;127. 骑士的攻击 给定两个坐标&#xff0c;搜索最短路径 使用 BFS&#xff0c;广度搜索&#xff0c;按层搜索找到最短路径 public class Main {public…

【 Sonarqube】可视化Java项目单元测试覆盖率统计框架搭建

一、项目背景&#xff1a; 一个小公司的朋友反应他们那边Java项目单元测试有&#xff0c;但还没有可视化统计覆盖率数据&#xff0c;没法统计就不能直观的看到单测的覆盖率&#xff0c;Java的覆盖率统计框架还是比较成熟&#xff0c;部署起来也不是很难&#xff0c;下面我们逐…

PTA数据结构编程题7-1最大子列和问题

我参考的B站up的思路 题目 题目链接 给定K个整数组成的序列{ N 1 ​ , N 2 ​ , …, N K ​ }&#xff0c;“连续子列”被定义为{ N i ​ , N i1 ​ , …, N j ​ }&#xff0c;其中 1≤i≤j≤K。“最大子列和”则被定义为所有连续子列元素的和中最大者。例如给定序列{ -2, 1…

jangow-01-1.0.1靶机

靶机 ip&#xff1a;192.168.152.155 把靶机的网络模式调成和攻击机kali一样的网络模式&#xff0c;我的kali是NAT模式, 在系统启动时(长按shift键)直到显示以下界面 ,我们选第二个&#xff0c;按回车。 继续选择第二个&#xff0c;这次按 e 进入编辑页面 接下来&#xff0c;…

在Windows上读写Linux磁盘镜像的一种方法

背景 嵌入式开发中&#xff0c;经常会把系统的Linux磁盘镜像保存到Windows上&#xff0c;以便上传到网盘备份或发送给工厂&#xff0c;但是如果想读取/修改镜像中的某个文件&#xff0c;一般有2种方案&#xff1a; 直接访问 就是用虚拟磁盘软件将镜像文件挂载成磁盘&#xf…

apisix的hmac-auth认证

目录 1、apisix的hmac认证Authorization头信息 2、signature的lua生成源码 3、java生成签证的简单示例 4、postman调用如下 apisix的hmac-auth认证&#xff0c;介绍可以看官方文档 hmac-auth | Apache APISIX -- Cloud-Native API Gateway 照着官方文档&#xff0c;发现生…

某些iphone手机录音获取流stream延迟问题 以及 录音一次第二次不录音问题

一些型号的iphone手机录音获取流stream延迟问题 以及 录音一次第二次不录音问题 延迟问题 navigator.mediaDevices.getUserMedia({ audio: true }) .then((stream) > {console.log(stream) }&#xff09;从开始到获取stream会有将近2s的延迟 导致按下按钮开始录音 会有前…

大数据导论汇总

第一章 作业 2、请阐述把数据变得可用需要经过哪几个步骤. 答&#xff1a;一共要经历三个步骤&#xff1a;数据清洗、数据管理、数据分析。 第一步&#xff1a;数据清洗。使用数据的第一步通常是数据清洗&#xff0c;也就是把数据变成一种可用的状态。这个过程需要借助工具去…

React 组件的通信方式

在 React 应用开发中&#xff0c;组件之间的通信是构建复杂用户界面和交互逻辑的关键。正确地实现组件通信能够让我们的应用更加灵活和易于维护。以下是几种常见的 React组件通信方式。 一、父子组件通信 1. 通过 props 传递数据&#xff08;父组件向子组件传递数据&#xff0…

高级Python游戏开发:基于Pygame的2D平台跳跃游戏

在这篇文章中,我们将开发一个基于 Python 和 Pygame 的2D平台跳跃游戏。这个游戏将包含多个关卡、玩家角色的跳跃控制以及简单的敌人和障碍物。通过这个项目,你将学习如何使用 Pygame 创建更复杂的游戏逻辑,如何处理碰撞检测以及如何设计关卡系统。 一、项目设计概述 在这…

Hugging Face Dataset的 dataset_info.json 文件详解

Hugging Face Dataset的 dataset_info.json 文件详解 什么是 dataset_info.json 文件&#xff1f; 在使用 Hugging Face&#xff08;HF&#xff09;数据集时&#xff0c;dataset_info.json 文件是一个描述数据集及其元数据的重要配置文件。这个文件包含了有关数据集的基本信息…