字节面试: Mysql为什么用B+树,不用跳表?

news2024/12/24 3:30:25

尼恩说在前面

在40岁老架构师 尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、希音、百度、网易、美团、蚂蚁、得物的面试资格,遇到很多很重要的相关面试题:

Mysql用B+树,不用跳表?

redis为什么用跳表不用B+吗?

最近有小伙伴在蚂蚁、面试字节,都问到了相关的面试题,可以说是逢面必问。

小伙伴没有系统的去梳理和总结,所以支支吾吾的说了几句,面试官不满意,面试挂了。

所以,尼恩给大家做一下系统化、体系化的梳理,使得大家内力猛增,可以充分展示一下大家雄厚的 “技术肌肉”,让面试官爱到 “不能自已、口水直流”,然后实现”offer直提”。

当然,这道面试题,以及参考答案,也会收入咱们的 《尼恩Java面试宝典PDF》V175版本,供后面的小伙伴参考,提升大家的 3高 架构、设计、开发水平。

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》的PDF,请到文末公号【技术自由圈】获取

本文作者:

  • 第一作者 Kevin
  • 第二作者 尼恩

索引的作用和重要性

索引是帮助MySQL高效获取数据的数据结构,注意,是帮助高性能的获取数据

索引好比是一本书的目录,可以直接根据页码找到对应的内容,目的就是为了加快数据库的查询速度

  • 索引是对数据库表中一列或多列的值进行排序的一种结构,使用索引可快速访问数据库表中的特定信息。
  • 索引是一种能帮助mysql提高了查询效率的数据结构:索引数据结构

索引的存储原理大致可以概括为一句话:以空间换时间

数据库在未添加索引, 进行查询的时候默认是进行全文搜索,也就是说有多少数据就进行多少次查询,然后找到相应的数据就把它们放到结果集中,直到全文扫描完毕。

数据库添加了索引之后,通过索引快速找到数据在磁盘上的位置,可以快速的读取数据,而不同从头开始全表扫描。

一般来说索引本身也很大,不可能全部存储在内存中,因此索引往往是存储在磁盘上的文件中的(可能存储在单独的索引文件中,也可能和数据一起存储在数据文件中)。

索引的作用和重要性

  • 加快数据检索速度

    索引允许数据库系统快速定位到符合查询条件的记录,从而显著提高查询操作的效率。

  • 降低数据库IO成本

    通过索引,数据库在查询时需要读取的数据量减少,这样可以减少磁盘IO操作的次数和压力,进而提升整体的数据库性能。

  • 保证数据的完整性

    索引可以包含唯一性约束,这有助于确保表中数据的唯一性,防止出现重复记录。

  • 加速表连接

    在涉及多表查询时,索引可以帮助加速表与表之间的连接操作,实现表与表之间的参照完整性。

  • 优化排序和分组操作

    当使用分组、排序等操作进行数据检索时,索引可以显著减少处理的数据量,从而提高这些操作的效率。

B+数和跳表的整体结构

整体上,B+数和跳表 都是 链表+ 多级索引组合 的结构

在这里插入图片描述

什么是MySQL中的B+Tree

MySQL中的B+Tree 原理

  • B+Tree一般由多个页、多层级组成,在MySQL中每个页 16 KB。

  • 主键索引的 B+ 树的叶子结点才是数据,非叶子结点(内节点)存放的是索引信息。

  • 上下层的页通过单指针相连。

  • 同一层级的相邻的数据页通过双指针相邻。

  • B+Tree的结构

    在这里插入图片描述

B+Tree的查询过程

B+Tree是由多个页组成的多层级结构,每个页16kb,对于主键索引来说,最末级的叶子节点放行数据,

非叶子节点放的是索引信息(主键ID和页号),用于加速查询。

我们想要查询数据5,会从顶层页的record开始,record里包含了主键Id和页号(页地址),

顶层页 向左最小id是1,最右最小id是7,

那id=5的数据如果存在,那必定在顶层页 左边箭头,于是顺着的record的页地址就到了6号数据页里,

再判断id=5>4,所以肯定在右边的数据页里,于是加载105号数据页。

105号数据页里,虽然有多行数据,但也不是挨个遍历的,数据页内还有个页目录的信息,里边是有序的。

所以,数据页内可以通过二分查找的方式加速查询行数据,于是找到id=5的数据行,完成查询。

从上面可以看出,B+Tree利用了空间换时间的方式,将查询时间复杂度从O(n)优化为O(lg(n))

B+Tree的优点和缺点

  • B+Tree是一种平衡树结构,它具有根节点、内部节点和叶子节点。

  • 每个节点包含一定数量的键值对,键值对按键值大小有序排列。

  • 内部节点只包含键,叶子节点同时包含键和指向数据的指针。

B+Tree的优点

  • 范围查询效率高:B+Tree支持范围查询,因为在B+Tree中,相邻的叶子节点是有序的,所以在查找范围内的数据时非常高效。
  • 事务支持:B+Tree是一种多版本并发控制(MVCC)友好的数据结构,适用于事务处理场景,能够保证事务的ACID属性。
  • 数据持久性:B+Tree的叶子节点包含所有数据,这意味着数据非常容易持久化到磁盘上,支持高可靠性和数据恢复。

B+Tree的缺点

  • 插入和删除开销较高:由于B+Tree的平衡性质,插入和删除操作可能需要进行节点的分裂和合并,这会导致性能开销较大。
  • 高度不稳定:B+Tree的高度通常比较大,可能需要多次磁盘I/O才能访问叶子节点,对于某些特定查询可能效率不高。

跳表

跳表的原理

跳表是一种采用了用空间换时间思想的数据结构。

跳表会随机地将一些节点提升到更高的层次,以创建一种逐层的数据结构,以提高操作的速度。

跳表的结构

跳表的做法就是给链表做索引,而且是分层索引,

单层跳表

单层跳表, 可以退化到一个链表

查找的时间复杂度是 O(N)

在这里插入图片描述

两层跳表

两层跳表 = 原始链表 + 一层索引

在这里插入图片描述

两层跳表查询

如查询id=11的数据,我们先在上层遍历,依次判断1,6,12,

很快就可以判断出11在6到12之间,

第二步,然后往下一跳,进入原始链表,就可以在遍历6,7,8,9,10,11之后,确定id=11的位置。

通过第一级索引,直接将查询范围从原来的1到11,缩小到现在的1,6,7,8,9,10,11。

三层跳表

三层跳表 = 原始链表 + 第一层索引 + 第二层索引

在这里插入图片描述

三层跳表查询

如果还是查询id=11的数据,就只需要查询1,6,9,10,11就能找到,比两层的时候更快一些。

在这里插入图片描述

跳表查找的时间复杂度

在一个单链表中查询某个数据的时间复杂度是 O(n)。也就是说,单层的跳表, 时间复杂度是 O(n)。

跳表 就是 为链表 增加多级索引, 完成空间换时间, 实现 时间复杂度是 O(logn)。

在这里插入图片描述

这个时间复杂度的分析方法比较难想到。

先问题分解一下,先来看这样一个问题,如果链表里有 n 个结点,会有多少级索引呢?

在跳表中,假设每两个结点,会抽出一个结点作为上一级索引的结点。

那么,索引有多少级,每一级有多少个node呢:

  • 第一级索引的结点个数大约就是 n/2,

  • 第二级索引的结点个数大约就是 n/4,

  • 第三级索引的结点个数大约就是 n/8,

依次类推,也就是说,

  • 第 k 级索引的结点个数是第 k-1 级索引的结点个数的 1/2,

  • 那第 k级索引结点的个数就是 n/(2的k次方)。

在这里插入图片描述

假设索引有 h 级,最高级的索引有 2 个结点。

通过上面的公式,我们可以得到 n/(2^h)=2,从而求得 h=log2n-1。

如果包含原始链表这一层,整个跳表的高度就是 log2n。

我们在跳表中查询某个数据的时候,如果每一层都要遍历 m 个结点,那在跳表中查询一个数据的时间复杂度就是 O(m*logn)。

那m到底是多少呢?

假设我们要查找的数据是 x,在第 k 级索引中,我们遍历到 y 结点之后,发现 x 大于 y,小于后面的结点 z,所以我们通过 y 的 down 指针,从第 k 级索引下降到第 k-1 级索引。

在第 k-1 级索引中,y 和 z 之间只有 3 个结点(包含 y 和 z),所以,我们在 K-1 级索引中最多只需要遍历 3 个结点,依次类推,每一级索引都最多只需要遍历 3 个结点。

在这里插入图片描述

过上面的分析,我们得到 m=3,

所以在跳表中查询任意数据的时间复杂度就是 O(logn)。

这个查找的时间复杂度跟二分查找是一样的,这也体现了空间换时间的效率之高。

跳表(Skip List)的优点和缺点

跳表是一种多层级的数据结构,每一层都是一个有序链表,

最底层包含所有数据,而上层包含的数据是下层的子集,通过跳跃节点快速定位目标数据。

跳表(Skip List)的优点

  • 平均查找时间较低:跳表的查询时间复杂度为O(log n),与平衡树结构相似,但实现起来较为简单。
  • 插入和删除操作相对较快:由于跳表不需要进行节点的频繁平衡调整,插入和删除操作的性能较好。

跳表(Skip List)的缺点

  • 难以实现事务和数据持久性:跳表的更新操作可能涉及多个层级,实现事务和数据持久性要求更复杂。
  • 空间开销较大:跳表需要额外的指针来连接不同层级,占用的内存空间较多。

B+Tree 和 跳表(Skip List) 的在数据结构上的区别

都是 多级索引 +链表

在这里插入图片描述

IO 操作的单位 不同

B+Tree 是page (16K)

跳表(Skip List) 是 node 节点 ,一个node 几十个字节

树的高度 不同

B+树是多叉树结构,每个结点都是一个16k的数据页,能存放较多索引信息。

同样的数据,树的高度比较小。 三层B+左右就可以存储2kw左右的数据。

如果,把三层B+树塞满,那大概需要2kw左右的数据。 也就是说查询一次数据,如果这些数据页都在磁盘里,那么最多需要查询三次磁盘IO

跳表是链表结构,一条数据一个结点,

如果最底层要存放2kw数据,且每次查询都要能达到二分查找的效果,2kw大概在2的24次方 左右,

所以,2kw数据的跳表大概高度在24层左右。 如果要一个节点要进行一次磁盘IO,大概要进行 24次。

B+Tree 和 跳表(Skip List) 的新增数据区别

了解了二者的基本情况之后,接下来,对B+Tree 和 跳表(Skip List) 的数据插入进行对比。

B+Tree和跳表的叶子层,都包含了所有的数据,且叶子层都是顺序的,适合用于范围查询。

来看看,B+Tree和跳表新增和删除数据的差异

B+Tree 新增数据

场景1: 叶子结点和索引结点都没满

B+Tree 直接插入到叶子结点中就好了。

在这里插入图片描述

场景2:叶子结点满了,但索引结点没满

B+Tree 需要拆分叶子结点,同时索引结点要增加新的索引信息。

在这里插入图片描述

场景3:叶子结点满了,且索引结点也满了

叶子和索引结点都要拆分,同时往上还要再加一层索引。

在这里插入图片描述

B+树是一种多叉平衡二叉树,要维护各个分支的高度差距,不能太大,平衡意味着子树们的高度层级尽量一致(一般最多差一个层级)。

为啥要平衡呢?平衡意味着在搜索的时候,不管走哪个子树分支,搜索次数都差不了太多。

所以,为了维持B+树的平衡,在插入新的数据时,B+树会不断将进行 数据页的 分裂

跳表新增数据

跳表同样也是很多层,新增一个数据时,最底层的链表需要插入数据,

然后,考虑是否需要在上面几层中加入数据做索引 ? 这个就靠随机函数了。

例如: 如果跳表中插入数据id=6,且随机函数返回第三层(有25%的概率),那就需要在跳表的最底层到第三层都插入数据。

跳表跟B+树不一样,跳表是否新增层数,纯粹靠随机函数,不太关心平衡的问题。

B+Tree和跳表的在新增数据上的区别

B+Tree 需要维护 树的平衡

为了维持B+树的平衡,在插入新的数据时,B+树会不断将进行 数据页的 分裂

维护平衡意味维护搜索的稳定性, 意味着着在搜索的时候,不管走哪个子树分支,搜索次数都差不了太多。

跳表 需要不太关心平衡问题

跳表在新增数据 时,不太关心平衡的问题。跳表插入数据的时候,跟B+树不一样,是否新增层数,纯粹靠随机函数去决定。

为什么B+Tree 采用Page作为 IO操作的单位?

前面讲到,B+Tree和跳表 IO 操作的单位 不同

  • B+Tree 是page (16K) ,粗粒度IO

  • 跳表(Skip List) 是 node 节点 ,一个node 几十个字节 , 细粒度IO

这是和 Mysql的存储介质有关系, Mysql的数据需要持久化存储, 并且需要事务机制保证持久性,所以,必须存储在磁盘上。

内存和磁盘的访问速度对比

机械硬盘的读写速度,大致如下

在这里插入图片描述

固态硬盘的读写速度,大致如下

在这里插入图片描述

内存的读写速度,和磁盘读写速度的对比

在这里插入图片描述

为什么磁盘慢,和磁盘的结构有关。

机械硬盘的扇区(sector)

机械硬盘的性能为啥那么慢? 看看结构就知道:

在这里插入图片描述

机械磁盘上的每个磁道被等分为若干个弧段,这些弧段称之为扇区。

如何在磁盘中读/写数据? 需要 物理动作,去移动 “磁头” 到目标 扇区

在这里插入图片描述

机械磁盘的读写以扇区为基本单位。

硬盘的物理读写以扇区为基本单位。通常情况下每个扇区的大小是 512 字节。linux 下可以使用 fdisk -l 了解扇区大小:

$ sudo /sbin/fdisk -l
Disk /dev/sda: 20 GiB, 21474836480 bytes, 41943040 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7d9f5643

其中 Sector size,就是扇区大小,本例中为 512 bytes。

注意,扇区是磁盘物理层面的概念,不是操作系统的概率。

操作系统是不直接与扇区交互的,而是与多个连续扇区组成的磁盘块交互。由于扇区是物理层面的概念,所以无法在系统中进行大小的更改。

操作系统 IO 块 Block

文件系统读写数据的最小单位,也叫磁盘簇,IO区块 BLOC。

什么是IO 块 Block? 扇区是磁盘最小的物理存储单元,操作系统将相邻的扇区组合在一起,形成一个块,对块进行管理。

每个Block 磁盘块可以包括 2、4、8、16、32 或 64 个扇区。

所以,Block 磁盘块是操作系统所使用的逻辑概念,而非磁盘的物理概念。

Block 磁盘块的大小可以通过命令 stat /boot 来查看:

$ sudo stat /boot
  File: /boot
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: 801h/2049d  Inode: 655361      Links: 3
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2019-07-06 20:19:45.487160301 +0800
Modify: 2019-07-06 20:19:44.835160301 +0800
Change: 2019-07-06 20:19:44.835160301 +0800
 Birth: -

其中 IO Block 就是磁盘块大小,本例中是 4096 Bytes,一般也是 4K。

Mysql的InnoDB Page 数据页

磁盘IO是低性能的,如何提升性能, 最好是 减少IO, 基于时间局部性和空间局部性原理, 一次读取足够多的数据到内存。

Mysql的 InnoDB将数据划分为若干页,以Page 页作为磁盘与内存交互的基本单位,一般页的大小为16KB。

InnoDB,为了通过减少内存与磁盘的交互次数,把一次读取和写入的 数据量, 从4K 扩大到了16K,也就是一次操作 4个 OS Block,从而提升性能。

这样的话,一次性至少读取1Page 页数据到内存中或者将1 Page页数据写入磁盘。而不是一个操作系统的block。

Page 本质上就是一种典型的缓存设计思想,一般缓存的设计基本都是从时间局部性和空间局部性进行考量的:

  • 时间局部性:如果一条数据正在在被使用,那么在接下来一段时间内大概率还会再被使用。可以认为热点数据缓存都属于这种思路的实现。
  • 空间局部性:如果一条数据正在在被使用,那么存储在它附近的数据大概率也会很快被使用。InnoDB的数据页和操作系统的页缓存则是这种思路的体现。

InnoDB Page 数据页的结构

2f3cbd5423f4715e64b4482c852cf38f.JPEG

一开始生成页的时候,并没有User Records这个部分.

每当我们插⼊⼀条记录,都会从Free Space部分,也就是尚未使⽤的存储空间中申请⼀个记录⼤⼩的空间划分到User Records部分,当Free Space部分的空间全部被User Records部分替代掉之后,也就意味着这个页使⽤完了,如果还有新的记录插⼊的话,就需要去申请新的页了。

一次IO一个page的优势

MySQL的InnoDB存储引擎使用B+树而不是跳表,这是因为B+树一次IO一个page,大大节省了磁盘IO的操作。

如果使用跳表,那么一个node节点一次io, 存储的性能 估计要下降1000倍以上。

总结:Mysql的索引为什么使用B+树而不使用跳表

B+树更适合磁盘IO

B+Tree一个节点是一个page,是一种多叉树结构,每个结点都是一个16k的数据页,能存放较多索引信息。一次IO一个page,大大节省了磁盘IO的操作。

B+Tree一个page 能存放较多索引信息 ,所以树的层数比较低, 三层左右就可以存储2kw左右的数据也就是说查询一次数据,如果这些数据页都在磁盘里,那么最多需要查询三次磁盘IO

原生跳表不适合磁盘IO

跳表是链表结构,一条数据一个结点,那么一个node节点一次磁盘io, 一个page 页规模的IO存储的性能 估计要下降1000倍以上。

原生跳表 一个node存放一个 索引信息 ,所以树的层数比较高

如果最底层要存放2kw数据,且每次查询都要能达到二分查找的效果,2kw大概在2的24次方 左右,

所以,2kw数据的跳表大概高度在24层左右。 如果要进行查找,大概要进行 24次磁盘IO。

这里讲的是原生跳表, 如果经过各种改进,那个不在此文讨论范围。

所以,虽然在理论上,跳表的时间复杂度和B+树相同 ,但是:

  • B+树更适合 磁盘IO, 更合适MYSQL。

  • 从反面来说, 跳表更适合内存IO, 更适合redis。

那么,为啥 redis 用跳表而不用B+树?

请参考 技术自由圈的下一篇文章 《字节面试: 请手写一个跳表》

说在最后:有问题找老架构取经

字节面试: Mysql为什么用B+树,不用跳表?,如果大家能对答如流,如数家珍,基本上 面试官会被你 震惊到、吸引到。

最终,让面试官爱到 “不能自已、口水直流”。offer, 也就来了。

在面试之前,建议大家系统化的刷一波 5000页《尼恩Java面试宝典PDF》,里边有大量的大厂真题、面试难题、架构难题。很多小伙伴刷完后, 吊打面试官, 大厂横着走。

在刷题过程中,如果有啥问题,大家可以来 找 40岁老架构师尼恩交流。

另外,如果没有面试机会,可以找尼恩来改简历、做帮扶。

遇到职业难题,找老架构取经, 可以省去太多的折腾,省去太多的弯路。

尼恩指导了大量的小伙伴上岸,前段时间,刚指导一个40岁+被裁小伙伴,拿到了一个年薪100W的offer。

狠狠卷,实现 “offer自由” 很容易的, 前段时间一个武汉的跟着尼恩卷了2年的小伙伴, 在极度严寒/痛苦被裁的环境下, offer拿到手软, 实现真正的 “offer自由” 。

尼恩技术圣经系列PDF

  • 《NIO圣经:一次穿透NIO、Selector、Epoll底层原理》
  • 《Docker圣经:大白话说Docker底层原理,6W字实现Docker自由》
  • 《K8S学习圣经:大白话说K8S底层原理,14W字实现K8S自由》
  • 《SpringCloud Alibaba 学习圣经,10万字实现SpringCloud 自由》
  • 《大数据HBase学习圣经:一本书实现HBase学习自由》
  • 《大数据Flink学习圣经:一本书实现大数据Flink自由》
  • 《响应式圣经:10W字,实现Spring响应式编程自由》
  • 《Go学习圣经:Go语言实现高并发CRUD业务开发》

……完整版尼恩技术圣经PDF集群,请找尼恩领取

《尼恩 架构笔记》《尼恩高并发三部曲》《尼恩Java面试宝典》PDF,请到下面公号【技术自由圈】取↓↓↓

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

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

相关文章

JVM垃圾收集器-serial.parNew,parallelScavnge,serialOld,parallelOld,CMS,G1

垃圾收集器 分代模型 适用于新生代: serial parNew parallel Scaavenge 适用于老年代: CMS serial Old(msc) paraller Old 分区模型 适用于超大容量: G1 分代模型 serial /serial Old收集器 1.单线程收集器 2.收集时会暂停其他线程&…

java学习之路-程序逻辑控制

目录 1.分支结构 1.1 if语句 栗子 判断奇数还是偶数 判断一个年份是否为闰年 1.2switch语句 栗子 2. 循环结构 2.1while 循环 栗子 2.2break和continue break continue 2.3for循环 基本语法 栗子 2.4 do while 循环 3.输入输出 3.1输出 3.2从键盘输入 栗子…

19 OpenCV 霍夫曼变换检测圆

文章目录 cv::HoughCircles算子参数示例 cv::HoughCircles 因为霍夫圆检测对噪声比较敏感,所以首先要对图像做中值滤波。 基于效率考虑,Opencv中实现的霍夫变换圆检测是基于图像梯度的实现,分为两步: 检测边缘,发现可能…

2024年初中生古诗文大会备考:多选题真题和独家解析(持续更新)

今天我们继续来做初中古诗文大会的一道难题:多选题,让大家了解初中生古诗文大会的考察内容和形式,并且提供了我独家的题目解析和答案,供初中的同学们学习和参考。 Tips:古诗文大会的许多题目都来自于中考、高考&#…

【Twinmotion】Twinmotion导入UE5

步骤 1. 在虚幻商城中安装“Datasmith Twinmotion导入器插件” 安装“面向虚幻引擎的Twinmotion内容” 2. 打开虚幻引擎,在插件中搜索“twinmotion”,勾选如下两个插件,然后重启虚幻引擎 3. 打开Twinmotion,随便添加一个物体 导出…

html canvas怎么在图片上面加文字

在HTML canvas中,要让文字显示在图片上方,你需要按照以下步骤操作: 首先,使用drawImage()方法将图片绘制到canvas上。 然后,使用fillText()或strokeText()方法在canvas上绘制文本。 以下是一个简单的示例代码&#…

Springboot 整合 Elasticsearch(五):使用RestHighLevelClient操作ES ②

📁 前情提要: Springboot 整合 Elasticsearch(三):使用RestHighLevelClient操作ES ① 目录 一、Springboot 整合 Elasticsearch 1、RestHighLevelClient API介绍 1.1、全查询 & 分页 & 排序 1.2、单条件查询…

C++第五弹---类与对象(二)

✨个人主页: 熬夜学编程的小林 💗系列专栏: 【C语言详解】 【数据结构详解】【C详解】 类与对象 1、类对象模型 1.1、如何计算类对象的大小 1.2、类对象的存储方式猜测 1.3、结构体内存对齐规则 2、this指针 2.1、this指针的引出 2.2…

Android U pipeline-statusbar

Android U - statusbar pipeline 写在前面 Android原生从T开始对SystemUI进行MVVM改造,U上状态栏部分进行了修改;第一次出现修改不会删除原有逻辑,而是两版并行,留给其他开发者适配的时间;在下一个大版本可能会删除原…

flask库

文章目录 flask库1. 基本使用2. 路由路径和路由参数3. 请求跳转和请求参数4. 模板渲染1. 模板变量2. 过滤器3. 测试器 5. 钩子函数与响应对象 flask库 flask是python编写的轻量级框架,提供Werkzeug(WSGI工具集)和jinjia2(渲染模板…

SpringBoot+Vue.js协同过滤算法美食推荐小程序

摘 要 伴随着我国社会的发展,人民生活质量日益提高。于是对各种需求进行规范而严格是十分有必要的,所以许许多多的微信小程序应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套协同过滤算法美食推荐小程序,帮助…

【SQL Server】实验四 数据更新

1 实验目的 掌握SQL数据更新语句的基本使用方法,如UPDATE、DELETE、INSERT。掌握更新语句条件中的嵌套查询使用方法。 2 实验内容 2.1 掌握SQL更新语句的基本使用方法 INSERT基本语句。UPDATE基本语句。DELETE基本语句。 2.2 掌握SQL更新语句的高级使用方法 …

SimpleDateFormat类 --java学习笔记

SimpleDateFormat 代表简单日期格式化,可以用来把日期对象、时间毫秒值格式化成我们想要的形式 常见构造器和方法: pattern 代表需要应用的时间格式—— 时间格式的常见符号: 时间格式的应用举例: import java.text.SimpleDate…

(二)丶RabbitMQ的六大核心

一丶什么是MQ Message Queue(消息队列)简称MQ,是一种应用程序对应用程序的消息通信机制。在MQ中,消息以队列形式存储,以便于异步传输,在MQ中,发布者(生产者)将消息放入队列&#xff…

基于信号分解的几种一维时间序列降噪方法(MATLAB R2021B)

自适应信号分解算法是一种适合对非平稳信号分析的方法,它将一个信号分解为多个模态叠加的形式,进而可以准确反应信号中所包含的频率分量以及瞬时频率随时间变化的规律。自适应信号分解算法与众多“刚性”方法(如傅里叶变换,小波变换)不同&…

最后十几天!未备案小程序将会被清退

微信官方通知 2023年8月9日,微信公众平台发布了“关于开展微信小程序备案的通知”: 去年就已经在逐步推进备案了,新注册小程序必须备案才可以上架。若微信小程序已上架,须于2024年3月31日前完成备案,逾期未完成备案&a…

苹果大模型MM1强势来袭!300亿参数所向披靡

功能展示 左图问:图片中有多少个苹果? 苹果大模型答:7个 左图问:这些州中哪一个是最北的? 回答:Delaware 追问:其他的州是什么? 回答:Arizona, Oklahoma, North Caro…

Ant Design Pro complete版本的下载及运行

前言 complete 版本提供了很多基础、美观的页面和组件,对于前端不太熟练的小白十分友好,可以直接套用或者修改提供的代码完成自己的页面开发,简直不要太爽。故记录一些下载的步骤。 环境 E:\code>npm -v 9.8.1E:\code>node -v v18.1…

[HTML]Web前端开发技术24(HTML5、CSS3、JavaScript )JavaScript基础JavaScript,Netscape,事件处理代码,外部JS——喵喵画网页

希望你开心,希望你健康,希望你幸福,希望你点赞! 最后的最后,关注喵,关注喵,关注喵,佬佬会看到更多有趣的博客哦!!! 喵喵喵,你对我真的…

Java学习笔记(12)

包 导包 Final 不能被改变的,修饰方法 类 变量 方法不能被重写 类不能被继承 变量,赋值一次,变成常量,不能再被赋值 final修饰引用数据类型,地址值不能变,里面的内容可以变 字符串是不可变的 源码中使…