关于索引的最常见的十道面试题

面试题一:索引底层如何实现的?

MySQL索引的底层实现是取决于存储引擎的,但是是大部分存储引擎底层都是通过B+树实现的,以默认的存储InnoDB为例,底层就是通过B+树实现的,如下图所示:

B+树是一种自平衡、多路搜索树,它的主要特征包含以下几点:

  • 非叶子节点只存储键值和指向子节点的指针
  • 所有数据都在叶子节点,并且用双向链表连接,便于查询
  • 查询速度比较稳定,都是树的高度O(logn)

面试题二:InnoDB索引、MyISAM和MEMORY索引底层实现都一样呢?

InnoDB索引、MyISAM和MEMORY索引底层实现是不一样的,其中:

  • InnoDB索引底层是通过B+树实现的,并且叶子节点为整行数据
  • MyISAM索引底层是通过B+树实现的,但是叶子节点存储的十内存地址,要根据内存地址进行寻找才能找到行数据
  • MEMORY索引底层是实现并不是树,因为其主要为内存引擎,并且适合存储键值数据,所以使用的是哈希结构实现的索引

面试题三:默认引擎索引为什么使用B+树,其他数据类型不行呢?为什么?

既然作为索引那么查询效率必然是要放在第一位,而树比其他的数据结构查询效率更高。这时你可能说哈希索引查询效率更高为什么不用哈希呢,因为哈希索引不能进行范围性查找,所以不适合作为索引的底层

而普通的二叉搜索树的层级节点太少,这样意味着查找一个元素需要多次I/O操作。所以要使用多路搜索树(B树和B+树),这样层级节点会增加,查询节点的时候,I/O操作次数会减少,这样查找效率会提高

B+树比B树的优势:

  • I/O次数更少(查询效率高):B+树的非叶子节点不存放实际记录数据,仅存放索引,因此数据量相同的情况下,相比又存放索引又存放数据的B树,B+树的非叶子节点可以存放更多的索引,因此I/O次数会更少,查询效率更高
  • 范围查询效率更高:B+树叶子节点是使用链表连接起来的,有利于范围查询;而B树要实现范围查询,只能是用树的遍历来完成范围查询,这样会涉及多次I/O操作,效率不如B+树
  • 插入和删除效率更高:B+树中有大量的冗余节点(所有非叶子节点都是冗余索引),这些冗余索引让B+树让插入、删除的效率更高

面试题四:索引的类型有哪些?

普通索引:这个是最基本的索引,它没有任何限制。普通索引主要是以B+树和哈希索引尾椎,任务就是加快对数据的访问速度。例如:我们有一个员工表employees,我们想要根据员工的last_name来查找员工,我们可以创建一个普通索引:

CREATE INDEX idx_lastname ON employees (last_name);

唯一索引:与普通索引类似,不同的就是:索引列的值必须唯一,但是允许空值。例如:我们有一个用户表users,我们想要确保每个用户的email都是唯一的,我们可以创建一个唯一索引:

CREATE UNIQUE INDEX idx_email ON users (email);

主键索引:主键索引是MySQL中的一个特殊的索引类型,用于标识每一个表中的唯一行的索引。主键索引要求主键列中的每一个值都是唯一的并且不为空。例如:我们在创建employees表的时候,可以这样指定employee_id为主键:

CREATE TABLE employees (
    employee_id INT PRIMARY KEY,
    first_name VARCHAR(50),
    last_name VARCHAR(50),
    email VARCHAR(50)
);

全文索引:全文索引是MySQL中的一个特殊的索引类型,用于对文本字段进行全文的搜素,全文索引可以帮助加快对文本数据的搜索速度,并且支持全文搜索的高级功能,例如模糊搜索和关键字匹配。假设我们有一个博客文章表posts,我们想要根据文章的content进行全文搜索,我们可以创建一个全文索引:

CREATE FULLTEXT INDEX idx_content ON posts (content);

单列索引和多列索引:单列索引是指索引只包含单个列,一个表中可以有多个单列索引 ,但是每个单列索引只能包含一个列。多列索引(也称为复合索引、联合索引)包含两个或者多个索引。例如:在employees表中,我们可以为last_name创建一个单列索引,也可以为last_namefirst_name创建一个多列索引:

CREATE INDEX idx_lastname ON employees (last_name);

CREATE INDEX idx_names ON employees (last_name, first_name);

聚簇索引和非聚簇索引:在 MySQL 的 InnoDB 引擎中,每个索引都会对应一颗 B+ 树,而聚簇索引和非聚簇索引最大的区别在于叶子节点存储的数据不同,聚簇索引叶子节点存储的是行数据,因此通过聚簇索引可以直接找到真正的行数据;而非聚簇索引叶子节点存储的是主键信息,所以使用非聚簇索引还需要回表查询。例如: student 表中有一个聚簇索引(也就是主键索引)id,和一个非聚簇索引 class_id

CREATE TABLE student(
    id INT PRIMARY KEY,
    name VARCHAR(16),
    INDEX(class_id)
);

面试题五:什么是最左匹配原则? 为什么要遵循最左匹配原则?

最左匹配原则,也称为最左前缀原则,是指在使用联合索引(复合索引)进行查询时,查询条件需要遵循索引中列的顺序,从左到右进行匹配123。只有当查询条件满足最左前缀原则时,才能充分利用联合索引的优势,提高查询性能。当遇见范围查询(<、>、between、like)机会停止匹配,其中范围列可以用到索引,但是范围列后就无法使用索引,即索引最多用于一个范围列

例如,假设有一个联合索引 (a, b, c),以下查询可以利用这个联合索引进行匹配:

  • select * from t where a = 1 and b = 1 and c = 1;
  • select * from t where a = 1 and b = 1;
  • select * from t where a = 1;

但是,如果查询条件不是从最左边的列开始,那么联合索引可能无法被充分利用。例如,select * from t where b = 1 and c = 1; 这样的查询就无法利用到定义的联合索引 (a, b, c)

遵循最左匹配原则的原因主要有以下几点:

减少开销:建立一个联合索引 (col1, col2, col3),实际相当于建立了 (col1)(col1, col2)(col1, col2, col3) 三个索引。每多一个索引,都会增加写操作的开销和磁盘空间的开销。对于大量数据的表,使用联合索引会大大的减少开销。

覆盖索引:对联合索引 (col1, col2, col3),如果有如下的 SQL:select col1, col2, col3 from test where col1 = 1 and col2 = 2。那么 MySQL 可以直接通过遍历索引取得数据,而无需回表,这减少了很多的随机 IO 操作。

效率高:索引列越多,通过索引筛选出的数据越少。有 1000W 条数据的表,有如下 SQL:select from table where col1 = 1 and col2 = 2 and col3 = 3,假设每个条件可以筛选出 10% 的数据,如果只有单值索引,那么通过该索引能筛选出 1000W * 10% = 100w 条数据,然后再回表从 100w 条数据中找到符合 col2 = 2 and col3 = 3 的数据,然后再排序,再分页;如果是联合索引,通过索引筛选出 1000w * 10% * 10% * 10% = 1w,效率提升可想而知。

面试题六:日常工作中,如何排查某个SQL是否正确使用了索引?

在日常工作中,我们可以使用explain关键字来查看SQL中查询的执行计划,从而判断是否正确使用索引。例如,如果我们有一个名为 users 的表,并且我们想要查询 id 等于 1 的用户,我们可以执行以下查询:

EXPLAIN SELECT * FROM users WHERE id = 1;

执行上述SQL语句,数据库会返回一个查询计划的结果集,其中包含查询的执行计划、使用的索引以及其他相关信息。查询计划通常包含以下重要信息:

  • type:查询块的连接类型,常见的类型包括ALL、index、range等。如果type列的值为ALL,则意味着查询未使用索引,可能对整个数据表进行全表扫描。如果type列值时index或range,则意味着查询使用了索引
  • possible_keys:可能使用的索引列表
  • key:实际使用的索引
  • rows:预估扫描行数
  • Extra:额外的信息,如对查询执行的描述

面试题七:索引失效的场景有哪些?

在MySQL中,有一些常见的场景可能会导致索引失效:

  1. 联合索引非最左匹配:当使用联合索引时,如果查询条件不遵循最左匹配原则(即查询条件不包含联合索引的最左边的列),那么索引可能无法被充分利用,也就是说,索引失效了。

  2. 不当模糊查询LIKE 查询的模式字符串如果以 % 开头或者前后都有 %,那么索引可能无法被使用。只有当模式字符串以确定的字符开头,如 LIKE '张%',才能使用索引。

  3. 使用列运算:如果查询条件中的索引列参与了运算,如 SELECT * FROM table WHERE age * 2 = 40;,那么索引可能无法被使用。

  4. 使用函数:如果查询条件中的索引列使用了函数,如 SELECT * FROM table WHERE UPPER(name) = 'Zhang';,那么索引可能无法被使用。

  5. 类型转换:如果查询条件中的索引列需要进行类型转换,如某列为字符串类型,而查询的时候设置了 int 类型的值,SELECT * FROM table WHERE name = 123;,那么索引可能无法被使用。

  6. 使用 IS NOT NULL:当在查询中使用了 IS NOT NULL,SELECT * FROM table WHERE name IS NOT NULL;,索引可能无法被使用,而 IS NULL 则会正常触发索引的使用。

  7. 使用 OR 操作符:当查询条件包含 OR 连接的条件,SELECT * FROM table WHERE a = 1 OR c = 1;,索引可能无法被使用,除非 OR 左右的查询字段都是索引。

面试题八:MySQL中索引和的约束有什么关系?

在MySQL中,索引和约束都是用于优化数据库性能和保证数据完整性的重要工具,但是它们的作用和使用方式有所不同:

索引是一种优化技术,它可以加快数据库的查询速度。在MySQL中,可以在列上创建索引,以便在查询的时候更快查询数据

约束是一种规则,它强制表中的数据满足特定的条件。约束的目的是为了保证表中的记录完整和有效。常见的约束类型包括非空约束(NOT NULL)、唯一性约束(UNIQUE)、主键约束(PRIMARY KEY)和外键约束(FOREIGN KEY)等

在某些情况下,索引和约束可以相互转换。例如,主键约束和唯一性约束在创建的时候会自动创建对应的索引。这是因为索引可以加快对这些约束的检查速度。然而,虽然索引可以提高查询效率,但是它并不能强制数据满足任何特定条件,这就是索引和约束的主要区别

面试题九:什么是索引覆盖?它给我们提供了什么启示?

索引覆盖是指查询语句可以完全按通过索引来满足,而勿需进一步访问表中的数据。当一个查询仅需要从索引中获取所需的数据列,而不需要访问表中实际数据行时,就称为索引覆盖。通过索引覆盖,可以减少对磁盘和内存的读取,提高查询性能例如,select id from table where age between 18 and 22,其中 id 为主键,而age 为二级索引,这时的 SOL只需要查询主键 id 的值,而 id 的值已经在 age 索引树上了,因此可以直接提供查询结果,不需要回表,这就叫做覆盖索引。
索引覆盖给我们的启示是,在实际工作中,能不使用 select *就不要使用 select *,因为 select *一定会进行回表查询,降低查询的效率,并且因为其包含的信息较多,所以也会增加网络带宽的负担,传输效率被拖慢等问题。

面试题十:什么是索引下推?为什么要有索引下推?

索引下推指的是在索引遍历的过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数

假设我们有一个 employees 表,表中有 idnamesalary 三个字段,其中 idsalary 字段都有索引。现在,我们要执行以下查询:

SELECT * FROM employees WHERE id > 1000 AND salary < 5000;

在不使用索引下推的情况下,MySQL 会先使用 id 的索引找到所有 id > 1000 的记录,然后将这些记录的所有字段(包括 idnamesalary)都取出来,返回给 MySQL 服务器。然后,MySQL 服务器再判断这些记录中哪些记录的 salary < 5000

而在使用索引下推的情况下,MySQL 服务器会将 salary < 5000 这个条件也一并下推给存储引擎。存储引擎在利用 id 的索引找到 id > 1000 的记录的同时,也会判断这些记录的 salary 是否小于 5000。只有当 salary < 5000 的记录,才会被取出所有字段并返回给 MySQL 服务器。

通过这个例子,你可以看到,索引下推可以减少存储引擎返回给 MySQL 服务器的记录数,从而减少了不必要的 IO 操作,提高了查询效率。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

NumPy2要来了,但先别急!

B站&#xff1a;啥都会一点的研究生公众号&#xff1a;啥都会一点的研究生 如果你正在使用 Python 编写代码&#xff0c;那么很有可能正在直接或间接地使用 NumPy 如Pandas、Scikit-Image、SciPy、Scikit-Learn、AstroPy…这些都依赖于 NumPy NumPy 2 是一个新的重要版本&am…

网络逻辑示意图工具

现代网络容纳了来自不同供应商的大量设备&#xff0c;支持一系列新技术&#xff0c;并跨越了分布在多个位置的边界&#xff0c;随着网络变得越来越复杂&#xff0c;网络管理员发现越来越难以跟踪网络领域的所有当代进步和发展&#xff0c;这使得网络管理比以往任何时候都更具挑…

Java8的Stream最佳实践

从这一篇文章开始&#xff0c;我们会由浅入深&#xff0c;全面的学习stream API的最佳实践&#xff08;结合我的使用经验&#xff09;&#xff0c;本想一篇写完&#xff0c;但写着写着发现需要写的内容太多了&#xff0c;所以分成一个系列慢慢来说。给大家分享我的经验的同时&a…

hadoop必记知识点(1)

1.Hadoop是什么&#xff0c;解决什么问题&#xff1f; Hadoop是一个由Apache基金会所开发的分布式系统基础架构。它可以让使用者在普通的硬件上搭建起一个强大的计算集群。Hadoop的特点包括&#xff1a;高可靠性、高扩展性、高容错性、支持大数据和高并发等。Hadoop核心组件包…

python写完程序怎么运行

python有两种运行方式&#xff0c;一种是在python交互式命令行下运行; 另一种是使用文本编辑器直接在命令行上运行。 注&#xff1a;以上两种运行方式均由CPython解释器编译运行。 当然&#xff0c;也可以将python代码写入eclipse中&#xff0c;用JPython解释器运行&#xff0c…

推荐系统|2.4 矩阵分解的目的和效果

文章目录 矩阵分解矩阵分解的必要性和方法隐向量 矩阵分解 矩阵分解的必要性和方法 比如原本是一个 m n m\times n mn规模大小的矩阵,经过分解后可得到两个矩阵一个是 m k m\times k mk&#xff0c;另外一个是 k n k\times n kn,于是总占用空间为 ( m n ) k (mn)\times k…

腾讯云.com域名报价

腾讯云com域名首年价格&#xff0c;企业新用户注册com域名首年1元&#xff0c;个人新用户注册com域名33元首年&#xff0c;非新用户注册com域名首年元85元一年&#xff0c;优惠价75元一年&#xff0c;com域名续费85元一年。腾讯云百科txybk.com分享腾讯云com域名注册优惠价格&a…

【C语言编程之旅 7】刷题篇-函数

第1题 解析 A&#xff1a;错误&#xff0c;一个函数只能返回一个结果 B&#xff1a;正确&#xff0c;将形参存在数组中&#xff0c;修改数组中内容&#xff0c;可以通过数组将修改结果带出去 C&#xff1a;正确&#xff0c;形参如果用指针&#xff0c;最终指向的是外部的实参…

Unity3D学习之UI系统——GUI

文章目录 1. 前言2. 工作原理和主要作用3. 基础控件3.1 重要参数及文本和按钮3.1.1 GUI 共同点3.1.2 文本控件3.1.3 按钮控件 3.2 多选框和单选框3.2.1 多选框3.2.2 单选框3.2.3 输入框3.2.4 拖动条 3.3 图片绘制和框3.3.1 图片3.3.2 框绘制 4 工具栏和选择网格4.1 工具栏4.2 选…

Docker(十一)Swarm mode

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; Swarm mode Docker 1.12 Swarm mode 已经内嵌入 Docker 引擎&#xff0c;成为了 docker 子命令 docker swarm。请注意与旧的 Docker Swarm …

Liunx系统和Window系统有什么区别

在信息技术世界里&#xff0c;操作系统扮演着至关重要的角色&#xff0c;它负责管理和控制计算机硬件与软件资源。Linux和Windows是市面上两个最流行的操作系统。接下来&#xff0c;我们将深入研究这两种操作系统的主要差异。 核心体系结构及源代码访问&#xff1a; 首先&#…

node介绍

1.node是什么 Node是一个基于Chrome V8引擎的JS运行环境。 Node不是一个独立的语言、node不是JS框架。 Node是一个除了浏览器之外的、可以让JS运行的环境 Node.js是一个让JS运行在服务端的开发平台&#xff0c;是使用事件驱动&#xff0c;异步非阻塞I/O&#xff0c;单线程&…

团灭 LeetCode 股票买卖问题

这几道题目是有共性的&#xff0c;我们只需要抽出来力扣第 188 题「188. 买卖股票的最佳时机 IV - 力扣&#xff08;LeetCode&#xff09;」进行研究&#xff0c;因为这道题是最泛化的形式&#xff0c;其他的问题都是这个形式的简化&#xff0c;看下题目&#xff1a; 第一题是只…

RHCE上课笔记(前半部分)

第一部分 网络服务 第一章 例行性工作 1.单一执行的例行性工作 单一执行的例行性工作&#xff08;就像某一个时间点 的闹钟&#xff09;&#xff1a;仅处理执行一次 1.1 at命令&#xff1a;定时任务信息 [rhellocalhost ~]$ rpm -qa |grep -w at at-spi2-core-2.40.3-1.el9.x…

一条sql是如何运行的

在我们平时使用sql的时候&#xff0c;基本是基于黑盒的使用方式&#xff0c;在客户端输入一条sql语句&#xff0c;然后回显想要的数据&#xff0c;对于mysql server端内部如何运行的以及与存储引擎如何交互的不得而知。 通过下面一幅图&#xff0c;大致描述客户端和服务端交互…

重定位(一)段的概念引入

1.2440结构图 对于2440来说&#xff0c;cpu可以直接发指令给SRAM、网卡、SDRAM、NOR FLASH&#xff0c;但无法直接控制NAND FLASH,必须由NAND FLASH控制器来操作NAND FLASH&#xff0c;但为什么我们的裸机程序烧入NAND FLASH还可以运行呢&#xff1f; 这就引入了重定位机制&…

matlab appdesigner系列-常用12-日期选择器

日期选择器&#xff0c;目的就是显示时间&#xff0c;时间格式目前常用的 正序2024/1/19 也有倒序 19/1/2024 或者写成年-月-日格式的&#xff0c; 此示例&#xff0c;为当用户要更改日期时&#xff0c;弹出对话框提示&#xff1a;把日期从XXX改到XXX&#xff1f;确认日期…

热血江湖服务端服务器架设教程

热血江湖服务端服务器架设教程 大家好&#xff0c;我是艾西今天简单的说下热血江湖架设需要哪些东西然后怎么操作&#xff0c;不管你是自己玩还是对外开放&#xff0c;这对于有兴趣的小伙伴总的都是一件好事。技多不压身就是这么个道理&#xff0c;当你需要用上时还希望能记起…

【二叉树练习2】

文章目录 判断是否是完全二叉树找出p和q的最近的公共祖先非递归实现前序遍历非递归实现中序遍历非递归实现后序遍历 判断是否是完全二叉树 boolean isCompleteTree(TreeNode root){if (root null){return true;}//创建队列Queue<TreeNode> queue new LinkedList<>…

Midjourney在线绘画及提示词精选库

网址:https://chat.xutongbao.top/ 一碗面粉&#xff1a; Self-Rising Flour in a 50s colourful bowl. professional photograph --ar 720:1170 --v 6 烟花古建筑&#xff1a; At night, with the snow-covered scenery of the Beijing Forbidden City as the backdrop, brill…