MySQL之流程控制,索引

news2024/11/23 4:07:23

一、条件语句

if 条件语句

delimiter //
CREATE PROCEDURE proc_if ()
BEGIN

    declare i int default 0;
    if i = 1 THEN
        SELECT 1;
    ELSEIF i = 2 THEN
        SELECT 2;
    ELSE
        SELECT 7;
    END IF;

END //
delimiter ;

二、循环语句

while循环

delimiter //
CREATE PROCEDURE proc_while ()
BEGIN

    DECLARE num INT ;
    SET num = 0 ;
    WHILE num < 10 DO
        SELECT
            num ;
        SET num = num + 1 ;
    END WHILE ;

END //
delimiter ;
delimiter //
CREATE PROCEDURE proc_repeat ()
BEGIN

    DECLARE i INT ;
    SET i = 0 ;
    repeat
        select i;
        set i = i + 1;
        until i >= 5
    end repeat;

END //
delimiter ;

loop循环

BEGIN

    declare i int default 0;
    loop_label: loop

        set i=i+1;
        if i<8 then
            iterate loop_label;
        end if;
        if i>=10 then
            leave loop_label;
        end if;
        select i;
    end loop loop_label;

END

三、索引概述

数据库索引是一个数据结构,其改善了数据检索操作的速度数据库表以额外写入和存储空间的费用来维持索引数据结构。索引用于快速定位数据,而不必每次访问数据库表时都在数据库表中搜索每一行。可以使用数据库表的一列或多列来创建索引,这为快速随机查找和有效访问有序记录提供了基础。

1、什么是索引

我们为数据建立索引,在一定程度上和为书籍建立目录类似.大家可以联想一下,为书建目录有什么好处?当你没有为书建立目录之前,如果你需要找到书具体的某一页内容,你只能通过一页一页地去翻,这种操作我们可以称之为遍历,但这么做其实相当不可靠,可能在前几页你就能找到你所需要的内容,但也可能在最后几页才找到,这样查询次数就会变得非常不可控,效率很低.可是一旦你为书建立了目录,你的查找方式就改变了,你就可以通过目录来查询到你所需要的内容,

那么到底什么是索引?索引是一种数据数据结构,用通俗的话来说,就是一种组织数据的方式。为数据库表中的一行行数据创建索引就好比是为书的一页页内容创建目录。

2、为什么要用索引?

显而易见地,我们为数据创建索引是为了提高查询数据的速度。

由于在增加,删除或修改数据时,如果建立了索引,需要额外建立键值对的对应关系,所以创建完索引后增、删、改的效率反而会降低。

然而在我们日常的工作中,对数据库进行的读写比例大约在10:1,而且增删改的操作几乎都是在一张表中进行,很少会遇到效率问题,而查询有时候很复杂,会横跨多张表,所以使用索引总体上能大幅提升我们的工作效率。

3、我们应该如何正确看待索引?

很多人会有一个误区,在一个软件开发完之后,等到发现这个软件运行地较慢时,才去添加索引,这就是一个错误的观点。因为如果当一个软件上线之后,发现运行速度很慢,这种“慢”可能并不是绝对意义上的很长时间,但即使某一条SQL语句只卡顿2~3秒,也会严重影响用户的体验。一旦这个问题出现以后,如果你再去“亡羊补牢”,就会发现并不一定是数据库结构带来的问题,当你将其他问题一一排除,并确定是由于SQL语句引起的,可能已经过去了很长时间。此外很多负责运维的人并不擅长分析SQL语句。

那么,究竟应该如何正确看待索引呢?

第一, 最好是在程序准备上线时,就提前考虑好索引的问题,分析有哪些功能是用户可能频繁使用到的,给这部分加上索引

索引并不是加的越多越好,诚然如果你给所有字段都加上索引,那么查询所有字段的速度都会相应提升,可是如果你真的这么做了,即使你进行一个非常简单的“写”操作,都意味着硬盘上的索引结构要重新变化,可能带来非常多的IO行为。

二、索引的数据结构

尽管为数据建立索引与为书籍建立目录十分类似,但两者也略有不同,不同的地方在于索引的创建分为两步

第一步,以索引字段作为键,与数据进行对应,

第二步,以键为基础,构造B+树

我们之前提到过,MySQL使用的默认存储引擎是InnoDB引擎,而InnoDB存储引擎中创建的是B+树结构的索引,那么问题来了,究竟什么是B+树结构的索引?

在介绍B+树索引结构之前,我们再引入一个例子来帮助更好地理解索引,比如你过年回家要买火车票,全国的火车票就相当于表中的一行行记录,如果要你直接查询具体回家的那一趟列车,由于全国有那么多趟列车,很明显无异于大海捞针,那你会怎么去查询?

你可以先搜索出发地,目的地,这样就可以筛选出一部分记录,范围就缩小了,然后再搜索具体的时间段,范围又进一步缩小了。于是你可以不断地缩小范围,这样就可以大大提高查询效率。而火车站规定筛选的这些条件其实就相当于索引。

现在我们来看下B+树的发展历程。

B+树是由二叉查找树,平衡二叉树,B树一步步发展而来,下面我们就介绍一下B+树的发展历史

二叉查找树

在上图的user表中,最初数据是杂乱无章地进行排列的,现在,我要将这张表变为二叉树结构,那如何操作呢?

第一步,我们首先要给它加上索引,假设我们以ID字段的值作为基础给它创建索引,比如第一条记录的id是10,我们就将它作为key取出,和后面的名字作为value一一对应,当我们依次将所有的记录都进行一遍类似的提取操作后,提炼完以后的表就相当于每一个key都对应一条记录。

第二步,我们可以以这个key值的大小作为依据,对整张表进行排序,放入类似于上图中右边的二叉树结构。在这张图里,每一个圆圈我们称之为一个节点,其中没有子节点的我们称之为叶子节点,处于最上层的节点我们称为根节点,而位于中间的都称之为树枝。很容易发现,二叉查找树任何节点的左子节点的键值都小于当前节点的键值,右子节点的键值都大于当前节点的键值。

上图中,如果我们想查询id为8的数据,如果不使用索引,我们要按顺序遍历,第五次能查询到数据,但如果使用二叉树索引,因为8比10小,我们直接可以定位到左边的树枝,而到了第二层,由于8比7大,我们又可以定位到右边的分支,最后在第三层找到了我们需要的数据,一共需要查找3次。更重要的是,在这张表中,无论你要查询什么数据,由于树的结构一共只有3层,所以最多只需要3次查询就能找到。这里的3层我们称之为二叉树的高度,很明显,二叉树的高度就是所需要查到的数据的最大IO次数

平衡二叉树

然而根据二叉查找树的特点,上图也可以称之为二叉查找树,可是这种二叉查找树的高度很高,根本无法达到减少IO次数的目的,于是我们引进了一个新的概念——平衡二叉树。平衡二叉树的特点是每个节点的左右子树的高度差不能超过1。可是平衡二叉树的数据结构也会有一定的问题,以上图中的模型为例,我们创建索引时要将索引的键值对写入硬盘,然后每次IO读取一个节点的数据,放入内存,这样固然能提速,但就好比开卡车运货,为什么我们每辆卡车只放一个很小的货物呢?

B树

很容易想到,我们从硬盘往内存读取数据,读取的是一个磁盘块,或者叫数据库中的一页数据。于是我们又过渡到了下一个阶段,B树。B树是在平衡二叉树的基础上,引入了磁盘块的概念,在一个磁盘块中放入较多的节点。在B树的每一页中,引入了一个指针的概念,比如在上图中,根页根据不同的范围划分,用指针指向一个分枝,进一步提升了查询的效率。然而B树仍存在一些问题,B树每一页中的节点既存放key,又存放对应的记录,这意味着每个节点都要占用较大的空间,也就是说每页只能存放较少的节点,这样在存放同等数据量的情况下,树的高度会偏高,有没有办法进一步降低树的高度呢?

B+树

B+树可以看作是在B树的基础上,非叶子节点不存储数据而只存放key,只有叶子节点才存储key和记录的值,这样,每个节点就能存储更多的键值,进一步降低树的高度。此外,B+树的叶子节点之间也有指针指向,是有序排列的,这意味着B+树在排序操作中和有天然的优势,此外在范围查询中,一旦匹配到某个叶子节点,就可以直接按顺序去找其它的叶子节点,不必再一次从树根查起,这些优点使查找的效率得到大幅提升。

三、索引的分类与区别

1、hash 索引
索引可分为hash索引以及B+树索引

在查询速度上,如果是等值查询,那么hash索引明显有绝对优势,因为只需要经过一次 Hash 算法即可找到相应的键值,当然了,这个前提是键值都是唯一的。如果键值不是唯一,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据,会大大降低Hash索引的查找效率

Hash 索引是无序的,如果是范围查询检索,这时候 Hash 索引就无法起到作用,即使原先是有序的键值,经过 Hash 算法后,也会变成不连续的了,所以hash算法不支持范围查询和排序运算,且无法支持多列联合索引和部分模糊查询

大多数场景下,都会有组合查询,范围查询、排序、分组、模糊查询等查询特征,Hash 索引无法满足要求,建议数据库使用B+树索引。但在一些离散型高,数据基数大,且等值查询时候,Hash索引更有优势。

2、B+树索引的分类与区别

B+树的索引可分为聚簇索引和辅助索引

聚簇索引 : 又名聚集索引,是以主键字段的值(通常是id)作为key创建的索引(一张表中只有一个),如果没有指定主键字段,会自动使用不为空且唯一的字段作为主键字段,如果没有符合条件的,Innodb存储引擎会自动创建一个隐藏的字段作为主键字段,聚簇索引叶子节点中存放的是id对应的一整条数据记录。

辅助索引:针对非主键字段创建的索引(一张表中可以包含多个),辅助索引叶子节点中存放的是对应的主键字段

总结:

聚集索引与辅助索引的相同点:它们都是B+树结构,非叶子节点只存放key值,而叶子节点存放key和value

不同点:聚集索引key对应的value是一整行完整的记录

辅助索引key对应的value是其对应的主键字段的值

此处还涉及到两个概念:回表查询和覆盖索引

接着,我们来举个例子详细说明一下覆盖索引和回表查询

首先,建立一张表,插入数据

create table t3(
	id int primary key auto_increment,
	name varchar(16),
	age int
)engine=innodb;

insert into t3(name,age) values
("egon",18),
("tom",18),
("lili",18);

Id

name

age

1

ly

18

2

tom

18

3

lili

18

覆盖索引:在当前命中的索引结构中,就能拿到所有你需要的数据

比如以下两条SQL语句查询这个表就能覆盖索引

select * from t3 where id = 3;  -- 覆盖了索引
select name,id from t3 where name="ly";  -- 覆盖了索引

回表查询:通过辅助索引拿到主键值,然后再回到聚集索引从根出发再查一下,获取其他字段的值
比如这条SQL语句

select name,id,age from t3 where name="ly";

因为无法直接查询到年龄,我们就要通过辅助索引拿到主键id,再从聚集索引中找到年龄的值,这就是回表操作

四、联合索引与最左前缀匹配原则

联合索引是指对表上各个列(多个字段)合起来做一个索引

最左前缀匹配:从联合索引的最左边开始匹配,一定要带着最左边的那个字段

最左前缀举例:

表结构

create index idx_id_name_gender on s1(id,name,gender);

当查询条件中出现以下字段,可以命中联合索引,因为符合最左前缀原则

id
id name
id gender
id name gender

例如下面的查询语句可以命中

where  age = 18 and name = "egon"  and gender="male"

而如果查询条件中只出现一个gender字段,不能命中

where gender="male"

五、索引下推技术

索引下推(index condition pushdown )简称ICP,在Mysql5.的版本上推出,用于优化查询。

在不使用索引下推技术的情况下,在使用辅助索引进行查询时,存储引擎通过索引检索到数据,然后返回给MySQL服务器,服务器然后判断数据是否符合条件 。

在使用索引下推技术的情况下,如果存在某些列符合索引的的判断条件时,MySQL服务器会将这一部分判断条件传递给存储引擎,然后由存储引擎通过判断索引是否符合MySQL服务器传递的条件,只有当索引符合条件时才会将数据检索出来返回给MySQL服务器 。

索引下推技术可以减少存储引擎查询基础表的次数,也可以减少MySQL服务器从存储引擎接收数据的次数。

六、如何正确使用索引?

看到这里,相信不少读者一定会有个疑问,命中索引是否一定会明显加速?

答案应该是不一定,当查询的过程中出现以下情况时,比如查询范围过大,字段占用空间过多或区分度低,或是索引被放入函数或参与运算,即使索引命中了,也不会显著提高查询的速度

为此,我们总结一下应该如何正确使用索引。

1 对区分度高并且占用空间小的字段建立索引

2 针对范围查询命中了索引,如果范围很大,查询效率依然很低

解决方法:把查询范围缩小,或分段/分页取值,一段一段取最终把大范围给取完,也可以搭配使用缓存

3 使用索引下推技术(默认开启)

4 不要把查询字段放到函数或者参与运算

举例:

不推荐的sql语句(把查询字段放入函数)

	select count(*) from where id*12 = 3;

5 索引覆盖:在命中索引的前提下,select查找值存在于本索引树中

	create index idx_name on s1(name);
	select name,id from s1 where name="egon";  -- 覆盖了索引
	select name,id,age from s1 where name="egon";  -- 没有覆盖索引,需要回表操作

注意:如果查询条件是用的主键字段,那么无论select查什么都会覆盖索引,都不需要回表。所以,在查询语句中,能用主键字段作为查询依据就尽量用它

6 创建联合索引,并遵循最左前缀匹配原则

	create index idx_xxx on s1(name,age,gender);

7 我们可以使用explain语句来优化查询的效率

 

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

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

相关文章

测试用例设计背后的底层逻辑你一定不知道

目录 前言 1、万物皆可测 2、用例的本质 3、业务建模 4、其他一些测试法 总结&#xff1a; 前言 测试用例是每位测试人员都绕不开的话题&#xff0c;也是大家习以为常的事情。几乎所有测试相关的公众号、博客、专栏&#xff0c;都会提及测试用例&#xff0c;由此可见它的…

华为OD机试真题 JavaScript 实现【矩阵稀疏扫描】【2023 B卷 100分】,附详细解题思路

一、题目描述 如果矩阵中的许多系数都为零&#xff0c;那么该矩阵就是稀疏的。对稀疏现象有兴趣是因为它的开发可以带来巨大的计算节省&#xff0c;并且在许多大的实践中都会出现矩阵稀疏的问题。 给定一个矩阵&#xff0c;现在需要逐行和逐列地扫描矩阵&#xff0c;如果某一…

备战金九银十,互联网大厂最全“Java 面试宝典 +Java 核心知识集”汇总

搬砖也有好几年了&#xff0c;本想在金三银四跳槽来着&#xff0c;结果我想你们应该猜到了&#xff0c;于是计划着下半年跳槽试试&#xff0c;算是提前为金九银十做准备吧&#xff01; 现在着手准备着以防万一自己措手不及&#xff0c;这不&#xff0c;这几天刚整理出炉的两份…

强化学习笔记-11 Off-policy Methods with Approximation

前几章我们讨论了off-policy方式&#xff0c;其同on-policy方式最大的不同之处在于其在训练所采取的动作&#xff0c;是根据behavior policy进行决策的&#xff0c;而不是根据target policy。这种方式的好处在于兼顾了exploitation and exploration。本节将讨论如何通过模型近似…

Spring MVC 的创建连接和使用

目录 前言&#xff1a; MVC 是什么&#xff1f; 1. Spring MVC 项目的创建和连接&#xff1a; 1.1 创建 1.2 连接 2. RequestMapping 注解使用详析&#xff1a; 2.1 指定请求类型&#xff1a; 2.1.1 指定 GET 请求 2.1.2 指定 POST 请求 3. 参数的获取与传递&#xff1a; 3.1 传…

CTR预估之WideDeep系列模型:DeepFM/DCN

前言 在CTR预估中&#xff0c;FM系列模型使用浅层网络&#xff08;线性模型&#xff09;&#xff0c;让模型自己学习特征组合交互&#xff0c;为显式建模的方式&#xff1b;而DNN系列模型使用深层网络&#xff0c;隐式挖掘模型的高阶特征交互。 本文继续介绍结合这两者优点的…

在我电脑中待了很久的5款使用办公软件

你电脑中用的最久的软件是哪些&#xff1f;以下是否有你曾经使用过的软件呢&#xff1f;工欲善其事&#xff0c;必先利其器&#xff0c;今天继续分享五款实用的办公软件。 矢量图绘制——Inkscape Inkscape是一款用于绘制和编辑矢量图形的工具。它可以让你用简单的操作来创建…

AI学术交流——“人工智能”和“神经网络学习”

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​ 目录 前言 一.人工智能 1.“人工智能之父” 2.达特茅斯会议&#xff08;人工智能起源&a…

2023四大服装管理软件,第1款最受欢迎!

对于服装行业来说&#xff0c;依靠传统的方式管理服装门店或工厂&#xff0c;很难实现精准高效的管理&#xff0c;往往是耗费了大量的时间和精力&#xff0c;也没有挣到什么钱。 这就需要借助服装管理软件&#xff0c;来降低管理和运营的成本&#xff0c;减少工作量的同时&…

自带海量设计模板的网站 精准尺寸一键套用出图

现在大家通过手机去购物时都是通过查看商品的详情页&#xff0c;因为详情页会介绍产品的功能和产品的设计优势等&#xff0c;还有产品的基本信息。那么对于刚接触电商的商家来讲&#xff0c;制作详情页和商品主图是一件困难的事情&#xff0c;但如果套用模板或者是直接选择一个…

vue结合elementui表格el-table实现弹窗checkbox自定义列显示隐藏,刷新保持上次勾选不丢失,附完整代码

el-table实现自定义列显示隐藏 有时候表格太多列,要是默认全都显示就会很拥挤,又不能固定只显示某些列,这时候我们可以让用户自定义要显示隐藏哪些列。 网上很多教程都是用的v-if,但是v-if非常麻烦,每一列都要写判断条件,本篇文章将用动态渲染的方式来控制表格列的显示隐…

【Linux】perf使用和FrameGraph

本文主要说明perf和FrameGraph的使用&#xff0c;例如&#xff1a;火焰图的输出&#xff0c;系统性能状态查看等。 Author:mayimin perf version 3.10.0-1160.80.1.el7.x86_64.debug 参考资料&#xff1a;perf example&#xff1a; https://www.brendangregg.com/perf.html 一…

100天精通Golang(基础入门篇)——第7天:深入学习键盘输入和打印输出,掌握常用函数和包

&#x1f337; 博主 libin9iOak带您 Go to Golang Language.✨ &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &#x1f30a; 《I…

【UE】滑动UI

效果 步骤 1. 新建一个控件蓝图&#xff0c;这里命名为“WBP_Slide” 2. 在关卡蓝图添加如下节点来显示控件蓝图 3. 打开“WBP_Slide”&#xff0c;添加一个滚动框控件 设置滚动框的锚点 设置滚动朝向为水平 在滚动框中添加一个画布面板 在画布面板中添加一个图像控件 由于我有…

设计优质微信小程序的实用指南!

微信小程序是一种快速发展的应用形式&#xff0c;设计良好的小程序能够提升用户体验并吸引更多的用户。在设计微信小程序时&#xff0c;有一些关键的指南可以帮助我们做出出色的设计。以下是即时设计总结的一些设计指南&#xff0c;希望能对准备设计微信小程序的人有所帮助。 …

64位和32位相比优势是什么(二)

程序的执行过程 当 CPU 执行程序的时候&#xff1a; 1.首先&#xff0c;CPU 读取 PC 指针指向的指令&#xff0c;将它导入指令寄存器。具体来说&#xff0c;完成读取指令这件事情有 3 个步骤&#xff1a; 步骤 1&#xff1a;CPU 的控制单元操作地址总线指定需要访问的内存地…

[CKA]考试之备份还原 etcd

由于最新的CKA考试改版&#xff0c;不允许存储书签&#xff0c;本博客致力怎么一步步从官网把答案找到&#xff0c;如何修改把题做对&#xff0c;下面开始我们的 CKA之旅 题目为&#xff1a; Task 首先&#xff0c;为运行在https://127.0.0.1:2379上的现有 etcd 实例创建快照…

36 # 加载 json 的处理流程

require 源码大致过程 mod.require 会默认调用 require 语法Module.prototype.require 模块的原型上有 require 方法Module._load 调用模块的加载方法&#xff0c;最终返回的是 module.exportsModule._resolveFilename 解析文件名&#xff0c;将文件名变成绝对路径&#xff0c…

UTF是变长编码

在阅读关于UTF8变长编码的文档时&#xff0c;看到如下内容&#xff0c; 文档中1110表示涉及3个字节&#xff0c;10表示涉及一个字节&#xff0c;还有后面的1110高位有三个1&#xff0c;表示从当前字节起有3字节参与表示UNICODE&#xff0c;后面的高位有1个1&#xff0c;表示从当…

Netty实战(十六)

UDP广播事件&#xff08;二&#xff09;编写广播者和监视器 一、编写广播者二、编写监视器三、运行 LogEventBroadcaster 和 LogEventMonitor 一、编写广播者 Netty 提供了大量的类来支持 UDP 应用程序的编写。下面我们列出一些要用到的类型&#xff1a; 名 称描 述interface…