秋招突击——7/9——MySQL索引的使用

news2024/11/15 11:08:36

文章目录

    • 引言
    • 正文
      • B站网课
        • 索引基础
        • 创建索引
        • 如何在一个表中查看索引
        • 为字符串建立索引
        • 全文索引
        • 复合索引
        • 复合索引中的排序问题
        • 索引失效的情况
        • 使用索引进行排序
        • 覆盖索引
        • 维护索引
      • 数据库基础——文档资料学习整理
        • 创建索引
        • 删除索引
        • 创建唯一索引
        • 索引提示
        • 复合索引
        • 聚集索引
        • 索引基数
        • 字符串前缀索引
        • 索引顺序
        • 对索引的隐式类型转换
      • 索引下推
      • 结合面试题回顾
        • 如何避免索引失效
        • 如何优化索引
    • 总结

引言

  • 今天怎么都得看完,不然项目都没时间整了,简历这周怎么都得搞完,不然肯定得挂!不行!
  • 这里重在于讲述索引的东西,先回顾一下索引基础知识、然后就是索引的原理以及如何设计索引才能更加高效。
  • 数据来源主要有两部分,分别是
    • B站的SQL进阶教程
    • 数据库教程网站

正文

B站网课

索引基础
  • 索引是能够提高数据库从表中检索数据行的速度的一种数据结构,但是需要额外的写入和存储来维护

    • 查询优化器,可以使用索引来快速定位数据,不需要全表逐行扫描
  • 索引很小,大部分都是保存在内存中的,所以,从内存中读取数据总是比磁盘中读取数据来得快
    *
    索引的代价

  • 增加数据库空间消耗,作为数据库的一部分,会一直和表格一块保存

  • 每次增删改都需要的维护更新索引

综上

  • 为性能关键的查询保留索引,需要基于查询创建索引,主要是为了加快部分查询十分缓慢的查找。
创建索引
  • 通过Explain关键字查看是否使用了索引,主要是通过Type关键字和row关键字查看
    • type是使用的索引类型
    • row是查询的行数
      在这里插入图片描述
      创建索引,加速查询的过程
create index idx_state on table_name(col_name);
  • possible_keys
    • 在查询过程中,可能用到的索引,这里是使用了idx_state,如果是联合查询,会是多个索引值
  • key
    • 在实际查询中,所使用索引或者键,上面那个是可能使用的,下面那个是实际使用的
      在这里插入图片描述
select customer_id  from customers where points > 100;   // 选择所有分数大于100的顾客的id
create index idx_points on customers(pointers);     // 对customer表格的pointer列创建索引

在这里插入图片描述

如何在一个表中查看索引
show indexes in customers;

在这里插入图片描述

  • 聚簇索引
  • 二级索引
    • 每一次创建一个二级索引,都会自动将主键索引加入到对应二级索引中
    • 二级索引:二级索引字段 + 主键索引
为字符串建立索引
  • 主要是为
    • char、varchar、text和blob创建索引
    • 这类索引会占据大量空间,无法达到很好的性能。所以,这里要尽量包含字符串的前几个字母,也就是前缀。

创建一个长度为20的前缀索引

  • 创建针对customers表格的last_name列的前二十个字符构成的字符串
create index idx_lastname on customers (last_name(20));
  • 这个长度选择,要能偶尽可能在短的情况下,遍历到所有的数据
全文索引
  • 查询文章或者题目中和“react redux”相关的所有的posts,下述方法存在一些问题
    • 随着数据库越来越大,搜索的范围越大,时间越慢
    • 全表扫描,没有索引
      在这里插入图片描述
      创建全文索引==》实现模糊查询,像搜索引擎一样
# 创建全文索引
create fulltext index on table_name(col_A,col_B);
# 使用全文索引
select *
from table_name 
where match(col_A,col_B) against ('这里输入相关的关键字');

在这里插入图片描述

  • 相关性得分
    • MySQL会基于若干因素,为包含了搜索短语的每一行计算相关性得分,是0到1之间的浮点数。

全文索引的两种方式

  • 自然语言模式,默认模式,就是上文使用模式
  • 布尔模式,包括或者是排除某些单词
    • 下述使用的布尔模式,查询包含了react和form,但是不包含redux 关键字的。
      在这里插入图片描述
复合索引
  • 找到位于加州并且收入大于8000的,这里加州和收入是两张表里面的数据
# 这里是做了一个连表查询
select customers_id from customers where state ='CA' and points > 1000;
  • 具体执行过程
    • 因为只用到一个索引,所以就是先找到所有州为CA的用户,然后在查询这些用的points
    • 因为只用到了一个索引,如果能够CA里面是有points >1000的索引,就快很多了。这就是联合索引的作用
      在这里插入图片描述
  • 对于州和point两个列建立联合索引,然后能够通过州和point快速访问到目标
create index idx_state_points on customers(state,points);

在这里插入图片描述

补充

  • 复合索引如果匹配到的范围查找,就不走索引了,后续会走索引下推
  • 复合索引的最左匹配原则,不是说顺序,是说具体的值,where a and b and c 对于索引(a,b,c)是满足最左匹配原则的,但是如果是where c and b就不满足了,因为少了一个。
复合索引中的排序问题

遵循以下两个原则

  • 使用最频繁的列放在前面
    • 将使用最频繁的放在前面,能够有效缩减搜索范围
  • 将基数最高的放在前面
    • 可以将总得样本,划分成数量跟少的样本,前面的搜索的范围会更小
  • 关注查询本身,根据查询本身进行优化,尽量缩减问题搜索的空间

在州和用户姓氏两个关键字上创建一个联合索引

create index idx_lastname_satte on customer(last_name,state);
  • 下述是last_name在前,state在后,扫描的列是40
    在这里插入图片描述
  • 下述是使用州在前,然后姓氏在后,仅仅查询了两行,效率更好
    在这里插入图片描述
索引失效的情况
  • 下述是使用or进行索引联合,通过explain可以看到,是查询了1010个数据,相当于全表扫描

  • 下述是使用union将两个子索引查询进行拼接,总共扫描了660个数据,远远小于第一个索引拼接方式

在这里插入图片描述

调用列进行了相关的运算
在这里插入图片描述

  • 下述进行了数字迁移,然后扫描量变成了3,因为虽然使用了比较函数,但是并没有调用对应对的列进行运算

在这里插入图片描述

使用索引进行排序
  • 添加索引的时候,MySQL会获取该列中的所有的值,并对结果进行排序,并将他们存储在索引中

在这里插入图片描述

使用没有对应索引的列进行排序==》产生外部排序,外部排序十分耗时,通过下图可以看到外部排序的时间耗费是第一个时间复杂度的10倍using filesort关键字进行排序

  • 下述做的排序是一个全标扫描,进行的排序
    在这里插入图片描述
  • 正常情况下,如果你要对数据进行排序,而且使用的是联合索引的中的两个列,那么必须要按照的相同顺序或者相同的升降顺序进行查询和排序的,否则会增加消耗时间。
    在这里插入图片描述
    特殊情况:一定要按照的联合索引的列进行排序查询,否则就会出现对应的全表扫描
  • 因为建立联合索引的时候,实现按照第一个列state进行分类的,然后在同一个state中,是按照points进行排序的。现在要直接points进行全部排序,就用不到索引了。
    在这里插入图片描述
    在这里插入图片描述
覆盖索引
  • 下述是覆盖索引,需要查询的数据在索引中就存在,不需要在会表进行查询即可获得,效率很高。这种现象就是索引覆盖!
  • select子句中查看的所有的数据列,都在索引中,就不需要在通过回表进行查询,这就是索引覆盖
    在这里插入图片描述
维护索引
  • 重复索引:相同列的不同顺序(A,B,C)和(B,A,C)
  • 多余索引:索引重复的情况,A和(A,B)

数据库基础——文档资料学习整理

创建索引

索引的定义

  • 索引是一种能够加快数据检索的数据结构,但是需要额外的写入和存储来维护
  • 查询优化器能够通过索引,快速定位数据,不必扫描表中的每一行
  • 索引本身和数据一起存储在同一表中

聚簇索引和非聚簇索引

  • 聚簇索引
    • 使用主键或者唯一键创建表的时候,会自动创建一个名为primary的索引
  • 非聚簇索引
    • 二级索引或者非聚簇索引是除了聚簇索引以外的索引。

创建索引的语法

CREATE [UNIQUE] INDEX index_name
[USING {BTREE | HASH}]
ON table_name (column_list)
[algorithm_option | lock_option];
  • 使用explain来查看对应的SQL执行情况
    在这里插入图片描述
  • 查看当前已经创建的索引

在这里插入图片描述

删除索引
  • 索引需要有空间代价和时间代价,所以需要删除
drop index index_name on table_name;

在这里插入图片描述

创建唯一索引
  • 虽然已经有了主键索引唯一索引,但是有的时候,还是需要创建自增的数字列,比如说订单表中的订单编号,用户表中的电子邮件等
create unique index index_name on table_name (col_name);

在这里插入图片描述

索引提示
  • MySQL的查询优化器为SQL语句制定最佳执行计划,根据索引基数进行决策,有的时候,你创建了索引但是没有使用也是因为索引基数不对。
  • 使用use index强制sql语句建议查询优化器使用指定的索引。
SELECT column_list
FROM table_name
USE INDEX (index_list)
WHERE condition;
复合索引

定义

  • 复合索引又称为组合索引或者是多列索引,最多能够创建16个列

创建语法

CREATE INDEX index_name
ON table_name(column_1, column_2, column_3);

复合索引规则

  • 将where子句中常用的列放在索引列列表的开头
  • 将不常用的列放在索引列列表的后面

MySQL总是按照最左匹配的原则展开对应的查询语句

CREATE INDEX index_name
ON table_name(a, b, c);
  • 在上述索引的情况下,如果查询使用的是下述顺序都会使用对应的索引,a先满足了,然后在去看b
WHERE a = v1 and b = v2 and c = v3;
WHERE a = v1 and b = v2;
WHERE a = v1;
  • 如果是下述情况,就不会使用对应的索引
WHERE b = v2 and c = v3;
WHERE c = v3
聚集索引

定义

  • 聚集索引是一种特殊的索引,该索引中的键值顺序决定了表中相应行的物理顺序。
  • 表格中的数据,只能按照一种顺序进行存储,所以表中只能有一个聚集索引。

InnoDB中的MySQL聚集索引

  • 如果指定了主键,主键就是聚集索引
  • 如果没有逐渐,第一个非空的列,并且是Unique的列,就是聚集索引
  • 如果没有合适的,MySQL会在内部生成一个隐藏的聚集索引。
  • InnoDB中二级索引中的每条记录都包含该行的主键列和非聚集索引指定的列
索引基数

定义

  • 一个索引的基数,就是这个索引列中唯一值的数量
    • 是根据统计信息生成的估计值,并不准确
  • 是查询优化器决定是否索引的依据,基数越高,索引越有效!
  • 基数越低,索引越无效,还不如全表扫描

查看索引基数

show indexes from table_name;

在这里插入图片描述

字符串前缀索引

定义

  • 为字符串列创建前缀索引,
  • 相比于对整个字符串创建索引,前缀索引能够减少磁盘的使用量,提高索引的写入速度

具体语法

create index idx_name on table_name (col(prefix_length));
  • 如果你使用对应的where的部分匹配,如果这对对应的字段创建了前缀索引就会使用对应索引加快速度,而不是全局扫描
select  * from table_name where first_name like 'ge%';
索引顺序

定义

  • 在创建索引的时候,指定索引的顺序,默认情况下,是按照升序存储的。
CREATE [UNIQUE] INDEX index_name
[USING {BTREE | HASH}]
ON table_name (column_name [ASC | DESC], ...)
[algorithm_option | lock_option];
对索引的隐式类型转换
  • 如果索引字段是字符串类型,但是在条件查询中,输入的参数是整型的话,会走全表扫描
    • 如果索引字段是 整型类型,查询条件中输入的参数是字符串,不会导致索引失效的

MySQL在遇到字符串和数字比较的时候,会自动把字符串转为数字,然后在进行比较

  • 自动类型转换是函数操作,CAST操作
# 下述两个SQL语句是等价的
select * from t_user where phone = 1300000001;
select * from t_user where CAST(phone AS signed int) = 1300000001;  # 这里是对phone进行了函数操作
# 下述的SQL语句会使用索引进行扫描,因为是将输入的参数的进行类型转换,而不是将索引进行类型转换
select * from t_user where id = "1";
select * from t_user where id = CAST("1" AS 1);

索引下推

这部分的所有资料都是来自这个链接——五分钟搞懂MySQL索引下推
定义

  • 能够减少回表查询的次数,提高查询的效率
  • 将部分上层也就是服务层负责的事情,交给下层引擎层去处理
  • 通过Extra中using index condition来进行判定

原理

  • 没有索引下推的情况

    • 存储引擎读取索引记录
    • 根据索引中的主键值,定位并读取完整的行记录。
    • 存储引擎吧记录交给Server层,检测记录是否满足Where子句条件
  • 有索引下推的情况

    • 存储引擎读取索引记录
    • 新增操作:判断where条件部分能够用索引中的列来检查,条件不满足,就处理下一行索引记录
    • 条件满足,使用索引中的之间,去定位并读取完整的行记录,也就是回表
    • 存储引擎吧记录交给Server层,检测记录是否满足Where子句条件

具体执行实例

  • 这里已经建立了联合索引,会按照最左匹配的原则,先查的name然后就是age
select * from tuser where name like '张%' and age = 10;
  • 没有ICP的时候

    • 数据引擎仅仅会使用第一个索引,返回所有姓张的列,然后由server层进行过滤,每一个姓张的样本都会进行回表查询,效率低
  • 有ICP

    • 数据引擎会在底层同时使用两个索引,查找到姓张的行后,会对年龄进行判定, 减少了回表的次数,效率比较高!

这里还是看一下原来的链接更容易理解

索引下推使用的条件

  • 只能用于range、ref、eq_ref、ref_of_null访问方法
  • 对于InnoDB来说,只能用于二级索引
  • 使用子查询的条件不能下推
  • 引用了存储函数条件的不能下推

具体应用场景

  • 联合索引在遇到范围查询时,会停止匹配,后续的字段就不会在使用
select * from t_user where age >20 and reward = 10;
  • 有了索引下推之后,即使reward无法走索引,但是在二级索引里面,会在存储引擎中进行过滤,减少回表次数

结合面试题回顾

如何避免索引失效

个人学完之后的回答

  • 不要使用or语句,如果是or的话,建议拆成多个不同的语句进行拼接
  • 不要对创建索引的列加上对应的运算,比如说加减乘除等,col + 2 > edge,不如改成 col > edge -2;
  • 如果是联合索引,在where子句中,一定要先先使用满足最左列,然后依次往后
  • 尽量使用基数比较大的索引。

参考回答

  • 使用左或者左右模糊匹配的时候,会造成索引失效,比如说like %xxx 或者 like %xxx%
  • 在查询条件中对索引列做了计算、函数、类型转换的操作,会造成索引失效的。
  • 联合索引要遵循最左匹配原则,按照最左有限的方式进行索引匹配,否则会导致索引失效。
  • 使用where子句时,or的前列是索引列,后列不是索引列,索引会失效
如何优化索引
  • 在创建联合索引的时候,观察select对应列,尽量创建覆盖索引,避免回表,减少大量的IO操作性能。
  • 防止索引失效,尽量不要写会让索引失效的SQL语句
  • 主键索引最好是单调递增的值
    • 主键是随机的值,插入会引起页分裂现象,导致大量的内存碎片
  • 对于大的字符串索引,考虑使用前缀索引只对前缀部分简历索引,节省索引的存储空间。

总结

  • 如果我在面试拼多多之前,就把这个东西整理了,或者说看了,也就不会那么尴尬,现在已经去实习了,很难顶!
  • 不过等到秋招的正式批,这个问题应该是难不倒我了,看一下,回顾一下就行了!
  • 加油吧!整理这个的时候,满心都是后悔,下次不能让这种事情发生!

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

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

相关文章

网络安全——防御课实验二

在实验一的基础上,完成7-11题 拓扑图 7、办公区设备可以通过电信链路和移动链路上网(多对多的NAT,并且需要保留一个公网IP不能用来转换) 首先,按照之前的操作,创建新的安全区(电信和移动)分别表示两个外网…

基础小波降噪方法(Python)

主要内容包括: Stationary wavelet Transform (translation invariant) Haar wavelet Hard thresholding of detail coefficients Universal threshold High-pass filtering by zero-ing approximation coefficients from a 5-level decomposition of a 16Khz …

win10系统更新后无法休眠待机或者唤醒,解决方法如下

是否使用鼠标唤醒 是否使用鼠标唤醒 是否使用键盘唤醒

【Java开发实训】day03——方法的注意事项

目录 一、方法的基本概念 二、void和return关键字 三、单一返回点原则 四、static方法使用说明 🌈嗨!我是Filotimo__🌈。很高兴与大家相识,希望我的博客能对你有所帮助。 💡本文由Filotimo__✍️原创,首发于…

《Windows API每日一练》9.25 系统菜单

/*------------------------------------------------------------------------ 060 WIN32 API 每日一练 第60个例子POORMENU.C:使用系统菜单 GetSystemMenu函数 AppendMenu函数 (c) www.bcdaren.com 编程达人 -------------------------------------------…

Java02--基础概念

一、注释 注释是在程序指定位置添加的说明性信息 简单理解,就是对代码的一种解释 1.单行注释 格式: //注释信息 2.多行注释 格式: /*注释信息*/ 3.文档注释 格式: /**注释信息*/ 注释使用的细节: 注释内容不会参与编译和运…

九盾安防丨如何判断叉车是否超速?

在现代物流和生产流程中,叉车是提高效率和降低成本的关键工具。然而,叉车的高速行驶也带来了安全隐患,这就要求我们对其进行严格的安全管理。九盾安防,作为业界领先的安防专家,今天就为大家揭晓如何判断叉车是否超速&a…

OpenCV距离变换函数distanceTransform的使用

操作系统:ubuntu22.04OpenCV版本:OpenCV4.9IDE:Visual Studio Code编程语言:C11 功能描述 distanceTransform是OpenCV库中的一个非常有用的函数,主要用于计算图像中每个像素到最近的背景(通常是非零像素到零像素&…

VMware_centos8安装

目录 VMware Workstation Pro的安装 安装centos VMware Workstation Pro的安装 正版VMware 17百度网盘下载链接 (含秘钥) 链接:https://pan.baidu.com/s/16zB-7IAACM_1hwR1nsk12g?pwd1111 提取码:1111 第一次运行会要求输入秘钥 秘钥在上边的百度网盘…

【Leetcode】最小数字游戏

你有一个下标从 0 开始、长度为 偶数 的整数数组 nums ,同时还有一个空数组 arr 。Alice 和 Bob 决定玩一个游戏,游戏中每一轮 Alice 和 Bob 都会各自执行一次操作。游戏规则如下: 每一轮,Alice 先从 nums 中移除一个 最小 元素&…

docker安装nginx并配置https

参考 docker安装nginx并配置https-腾讯云开发者社区-腾讯云 (tencent.com) 证书的生成 参见:SpringBoot项目配置HTTPS接口的安全访问(openssl配置)_配置接口访问-CSDN博客 步骤 1: 拉取Nginx镜像 docker pull nginx 好使的镜像如下&#x…

DockerCompose拉取DockerHub镜像,并部署OpenMetaData

参考博主:http://t.csdnimg.cn/i49ET 一、DockerCompose拉取DockerHub镜像 方法一(不太行): 在daemon.json文件中添加一些国内还在服务的镜像站(可能某些镜像会没有) ([ -f /etc/docker/daemon.json ] ||…

RK3568笔记三十五:LED驱动开发测试

若该文为原创文章,转载请注明原文出处。 字符设备驱动程序的基本框架,主要是如何申请及释放设备号、添加以及注销设备,初始化、添加与删除 cdev 结构体,并通过 cdev_init 函数建立 cdev 和 file_operations 之间的关联&#xff0c…

每日一练:奇怪的TTL字段(python实现图片操作实战)

打开图片,只有四种数字:127,191,63,255 最大数字为255,想到进制转换 将其均转换为二进制: 发现只有前2位不一样 想着把每个数的前俩位提取出来,组成新的二进制,然后每…

Python中的数据容器及其在大数据开发中的应用

在Python编程中,数据容器是存储和组织数据的基本工具。作为大数据开发者,了解并灵活运用各种容器类型对于高效处理大规模数据至关重要。今天,我们将从Set出发,探讨Python中的各种数据容器,以及它们在大数据处理中的应用…

社交App iOS审核中的4.3问题:深入分析与解决策略

社交App审核中的4.3问题:深入分析与解决策略 在iOS应用开发和审核过程中,开发者经常会遇到苹果审核4.3问题。这一问题往往涉及应用的设计和内容重复性,导致应用被拒绝上架。为了帮助开发者更好地理解和解决这一问题,本文将对4.3问…

基于复旦微JFMQL100TAI的全国产化FPGA+AI人工智能异构计算平台,兼容XC7Z045-2FFG900I

基于上海复旦微电子FMQL45T900的全国产化ARM核心板。该核心板将复旦微的FMQL45T900(与XILINX的XC7Z045-2FFG900I兼容)的最小系统集成在了一个87*117mm的核心板上,可以作为一个核心模块,进行功能性扩展,能够快速的搭建起…

C语言操作符优先级

1 C语言操作符优先级 熟悉操作符的优先级,避免意外的求值顺序。 2. 运算符优先级记忆方法 利用优先级表或常见记忆口诀来记忆运算符的优先级。

嵌入式人工智能应用-篇外-烧写说明

1 外部接线 1.1 前期准备 需要准备的工具 ⚫ 一根 Mini USB 线 ⚫ 嵌入式人工智能教学科研平台 ⚫ 12V DC 电源 ⚫ 一台电脑 1.2 接线 12V DC 电源接入 12V IN;Mini USB 线连接 USB OTG;如果有两条 Mini USB 线,可以接入 UART2 to USB 口…

python2

一、条件语句 具体有如下:if、if......elif、if......elif......else 注意格式: if后面的条件表达式没有(),以:作为结尾对于多分支的条件,不是写成else if 而是elif注意条件下一行要有缩进 …