数据存储结构B+树 vs LSM Tree

news2024/11/17 9:50:33

关于存储的几个概念

对于一个存储系统来说,底层的存储结构基本上就决定了这个存储系统的功能,或者说性能偏向。比如

  • 使用B+树的存储系统,那就是查询友好的;

  • 使用倒排索引结构的,那就主要是用来做全文搜索的;

  • 使用key-value结构的,在分布式系统中,nosql基本上都是采用了key-value来存储的,这类系统往往是偏向于等值查询,比如缓存等场景。但是在newsql发展中,计算和存储分离后,底层的存储好多都是采用key-value的存储,然后再次基础之上,叠加一个计算组件,来满足二维表的结构化数据的查询和维护。

  • ...

对于一个存储系统来说,肯定不会是单一的数据结构就能够满足要求的,上面列出出来的,只是说一个特定偏向领域的存储系统主要的这种数据结构,比如mysql的数据是以B+树来组织的,但并不表示mysql的实现里没有用到hash表、跳表等等呢个数据结构。

不过这里需要单独说一下的是,LSM-Tree,也是本文重点会去讨论的,这个虽然叫xxx-Tree,我觉得它和二叉树、红黑树等等这种数据结构还是有本质的差别,LSM-Tree不是一个树结构,而是一种实现数据存储的工程方式,通过一些工程手段来解决读写放大的问题,但是其背后的数据结构可以上任何一种现有的数据结构。

另外,其实还有一个概念非常容易混淆,就是存储方式(数据的组织方式),这个在讨论OLTP、OLAP的时候,一定会讨论到。和这些概念揉到一起,比较容易混淆。

行存 vs 列存

为了解释清楚,我们以逻辑结构是二维表来举例,就可以一目了然了,比如有如下一张二维表数据(逻辑结构):

列式存储:数据在存储介质中是按照列来组织的。

通俗点来说就是将一列的数据进行连续存储,即id这这一列的数据都是连续存放的、姓名这一列的数据也是连续存放的(即geoge、snoopy、粽子这三个值在磁盘上是连续存放在一起的,当然也可能按列的范围进行拆分,所以不一定是一列所有的数据都是连续存放的,得看具体的实现)。对于OLAP场景,其实往往是要将一列或者几列的数据全部取出来,然后就这一列/几列数据进行分析,所以列式存储对于OLAP分析场景,就比较有又是。

行式存储:数据在存储介质中是按照行来组织的。

也就是说子啊存储介质中,会将id=1的这一行(1、geoge、180)数据进行连续存储、将id=2的这一行进行连续存储,依次类推。在OLTP场景中,一行数据往往存储了一个实体的一类数据,比如上述例子就是一行代表了一个人员的进本信息。在OLTP场景中,都是面向一个或者一个范围内的实体进行操作,所以往往会将一个实体的很多数据都查出来,那这种按行组织的方式对这种场景就很友好,不用随机IO/随机内存操作到处去找数据,然后才能将一行数据给组装完。

所以说行存还是列存,指的是数据在存储介质中的是按照逻辑行、还是逻辑列来连续存储的。所以行存和列存根给用户是否以表格的形式展示,没有任何关系(mysql是行存、hbase是列存,但会发现都可以给用户以二维表的方式来展示数据)

这里说明出了二维表的逻辑结构和行存/列存的关系后,其实还有一个概念和表比较容易混淆,顺便这简单说一下,那就是:结构化和非结构化。

结构化 vs 非结构化

要说清楚这个问题,只需要回到一个问题就清楚了,这也是以前一直困扰我的问题:我们说mysql是结构化的存储,它的结构化体现在哪儿?ES存储的是非结构化的数据,但是使用上看一样的有:document、field这些,感觉跟二维表没有任何区别,那么为啥说它存储的是非结构化的信息。

总结到一句话就是:是否结构化,跟给用户展示的逻辑结构、以及数据模型没有任何关系(不管他是不是有行、字段这些概念),就看一个:是否有一个模式来约束数据。

比如mysql,我们首先就是先创建一张表,其实创建表就是创建了一个约束数据的模式(schema),后续往mysql里写入数据,就只能按照这个模式的约束来写入,不满足约束,就不允许写入。而这个模式,我个人理解就是在定义数据的结构,那么根据这个模式落下去的数据,自然是满足这个模式定义的结构约束的。

比如,如果我定义了一张表有id、姓名、身高、胸毛,那么这个表里存放的任何数据,都必须有这几个字段,哪怕是george、snoopy和粽子都没有尾巴,但由于schema定义了这个字段,我们就不得不给这个字段一个值(哪怕是null值,也得给它一个值),否则就不满足schema结构约束。

再看ES(hbase也是一样的),虽然Lucene在给用户的api中,一样是将数据建模成了:Document、Field的概念,但是一个document里到底可以有哪些字段、字段的类型是什么,这个是没有任何约束的,可以随便在Document里增加、减少。但是对于非结构化,就不一样了,没有就不需要就好了,注意哦,不是没有值,是连这个字段都没有,这是两个概念。也就是说,documentId=1/2/3是没有尾巴这个字段的,是连字段都没有,不是这个字段取值为null。

所以,当你使用ES的时候,你会发现,ES里都没有null这个特殊值,它给的查询接口里面,只有exits,根本就么有判断一个字段是否是null,但mysql里对null的判断是有特殊语法的:is null/is not null。

到这,几个概念性的东西都解释过了,接下来就进入正题:阐述一下B+树和LSM-Tree

B+树

B+树本质上是一个平衡的m-n树,其中m是指一个节点里能够存放的数据个数,n是指指向叶子节点的指正个数。其中+的意思就是同层节点是从小到大排序的,且有指向右兄弟的指正(换句话说,同层节点是一个从小到大排序的链表),下图就是一个B+树(2-3树)。

在B+树中,对范围查找非常友好,比如要等值查询,id=9的数据。

  • 首先就从根节点判断,9是小于40的(如果m更大,那么在节点内部就是一个二分查找,目标值在哪个区间里),所以去最左指正的指向的子树中继续查找。

  • 到了子树上,发现9是小于10的(m较大的时候就是个二分查找),然后继续到最左指正指向的节点

  • 发现是叶子节点,且值是0,所以就向右遍历,一直遍历到id=9,则找到对应的数据。

如果是范围查找9<=id<10,那么遍历到id=9的时候,继续往后遍历,发现15是大于10的,所以结果集中也就只有id=9的数据;

如果9<=id<20,同样的继续向右遍历,遍历到id=15、id=40,发现已经比右边界大了,所以收集到结果是id=9和15的数据。

如果是id<20,同样的使用树定位到倒数第二层的(10,15),那么就会利用mptr找到id=15的叶子节点,开始向右遍历。

总结起来,B+树的查找分为三部分:

  1. 节点内的二分查找

  1. 非叶子节点树的遍历查找

  1. 叶子节点链表的遍历查找

所以B+树的查询其实是hi比较高效的,二分查找和树查找的效率都是O(logN),而最后的叶子节点遍历虽然是个O(N)的操作,但实际上,只要遍历到不满足条件的节点,就会终止。所以对于一些OLTP的业务,其实更多的是等值或者少量数据的查询,所以B+树的查询效率是非常高的。但也需要注意,对于大批量的数据扫描,那其实就是遍历整个叶子节点链表了,这个效率就会比较低,比如Id>1,那基本就是全表扫描。所以对于用B+树作为存储引擎的数据结构的时候,对于大量数据的扫描其实也不是很友好,直接会全表遍历的。

再来看写入,写入的时候的一个最大的成本就是要维护B+树的结构:

  • 节点内数据是有序的

  • 子树里维护的数据,要满足非叶子节点维护数据的范围。

  • 同层节点,要是排序的。

因为要维护这些结构,所以就会存在额外的数据写入,即写放大问题。比如要插入一个35的节点,

除了会插入35这个叶子节点外,还有额外的一个中间节点指针的修改,以及新增了一个中间节点,为了数据的均衡,其实还可能修改原有叶子节点里的数据的范围,那就会进一步放大写入操作。

另外在mysql的实现中,哪怕是叶子节点,也不是一个节点只是存储一条数据,而是以page为单位,一个page里存放了多条数据(按索引排序的多条数据,主键索引就是按主键排序、辅助索引就是按照辅助索引排序的),那么对于mysql来讲,其实还多了页内数据的维护。而且mysql的page的大小是固定的,所以在写入数据的时候,为了保证页内数据的有序性,以及同层page之间的有序性,那在写入一条数据的时候,就有可能出现页分裂的问题。比如按page组织的叶子节点如下,要插入数据8

其实三个page都需要重新写入的,想下如果数据量很大的时候,本来只是想插入一个数据,那所有的page都需要修改一下,那这个效率是会有多慢。所以在mysql的使用中,也是建议使用递增的主键,以避免主键索引树发生页分裂的问题。而mysql内存中的page和磁盘中的page是对应的,那么也就是说,这里所有的page都需要刷一次磁盘。

衡量写放大问题有个写放大系数(Write Amplification Factor,WAF)就是来衡量写放大的一个指标,它指实际写入磁盘的数据量和应用程序要求写入数据量之比。比如上述的例子WAF=100kb/1kb=100。

对于写放大的的优化方式,常见的方式就是:预留填充,基本思路就是在page中预留一些空间,这样不会因为少量的数据写入造成树结构的大幅变动。但是到底预留多大就是个问题:

  • 过大则无法解决写放大问题;

  • 过小会造成页表数量膨胀,增大对磁盘的扫描范围,降低查询性能

B+树的另外一个问题就是实际存储是不连续的,也就是说在逻辑结构上,同层节点是链表结构,通过指正链接到一起,但实际上,各个page存储到磁盘,不是连续空间存放的,所以这种不连续的存储就会导致查询的时候寻址成本的增加。

在一个存储系统中,关于读、写、空间三个方面的优化中,有一个RUM猜想:对任何数据结构来说,在Read Overhead(读)、Update Overhead(写)和Memoryor Storage Overhead(存储)中,同时优化两项时,需要以另一项劣化作为代价。

这跟分布式系统的CAP理论一样,在一个存储系统中,就需要权限读、写、占用空间之间的一个权衡。

LSM-Tree

B+树作为存储引擎的结构时候,由于存在写放大、和存储的不连续的问题,所以一些新兴的存储型的组件,开始采用LSM-Tree(Log Structured-MergeTree)来作为底层的存储结构,比如很多分布式数据库,如TiDb、OceanBase等,以及ES的新版本的数据存储也开始采用LSM-Tree了。

首先需要明确一点,LSM-Tree是google提出来的,虽然它的名字里有个tree,但它不是一个数据结构里的那个树。其核心在于前面的LSM:Log Structured-Merge

LSM-Tree的核心思想是将数据的写入分成了两部分:内存部分和磁盘部分。写入过程:

  1. 首先写入内存的memTable,以及wal日志,写入就直接返回了。所以正常情况下,写入操作会非常的快。只是涉及一个内存操作和一个磁盘的顺序写操作。

  1. 当memTable达到一定的阈值的时候。就会将memTable flush到磁盘中。

  1. 新创建一个memTable,使用新的memTable来服务新的写入请求。

  1. 原来的memTable就变成了imutable memTable。然后将imutable memTable中的数据进行整理:按照key进行排序。

  1. 将排序后的imutable memTable直接刷到磁盘,在磁盘里对应的就是SStable。所以,在磁盘中,会不断新增SStable。

  1. 随着系统的运行SStable越来越多,这个时候就会按照一定的规则对SStable进行compact整理合并。

通过整个写入过程会发现,会发现其实LSM-Tree不是没有写放大,而是将写放大的过程给转移了,转移到compact过程了。

所以,LSM-Tree的写放大指数,就看compact过程的合并策略了。

Size-Tiered Compact Strategy合并策略

Size-Tiered Compact Strategy,简称Tiered,其基本能思想就是每当某个尺寸的SSTable数量达到既定个数时,将所有SSTable合并成一个大的SSTable。这种策略的优点是比较直观,实现简单,但是缺点也很突出

Tiered合并策略的读放大问题

SSTable文件是按照时间间隔产生的,所以在不同的SSTable文件中,就有可能存在相同的key的数据。所以每次读取的时候,都需要遍历所有的SSTable,然后合并key的值后,才能确定某个key的最终取值是什么。

SSTable内部是按照Key排序的,所以查找方法可以是二分查找,所以查找单个SSTable的时间复杂度是O(logN),其中N是SSTable中key的个数。有M个SSTable,整体时间复杂度就是O(MlogN)。当然执行Compact后,读的复杂度会有所下降,因为SSTable的文件减少了。

当然也可以发现,如果系统中只有一个SSTable的时候,其实是没有读放大的。

Tiered合并策略的写放大问题

Compact后会减少SStable的个数,从而降低读放大。但是Compact过程会带来更多的写放大和空间放大。

通过LSM-Tree的写入过程会发现,LSM-Tree不是没有写放大问题,而是将将写放大转移了,只是说在实际写入操作的时候没有写放大,从而可以承载大量的并发写入。

但如果持续写入,产生大量的SStable,就会执行Comapct过程,而Compact过程就会有比较大的I/O开销、内存、cpu的开销。而Tiered合并策略是在Compact的过程,会合并当前系统中的所有SSTable,所以相比于B+树写入时候的写放大成本,总体上Tiered合并策略在Compact时的成本可能会更大。而且由于Compact会占用I/O、cpu等资源,其实反过来就会可能影响写入操作以及读操作。

Tiered合并策略的空间放大问题

从空间放大的角度看,Tiered策略需要分别存储合并前的多个SSTable和合并后的一个SSTable,所以需要两倍于数据大小的空间。所以空间放大指数(SAF)就是2,而B+树的SAF是1.33.

一通分析过后,LSM-Tree只是在短时间内写入速度快以外,还存在更多的读放大、写放大、空间放大的问题,而且Compact时会耗费大量的I/O的资源,反过来还会影响读写操作,看起来比B+树没有什么优势。

其实这些问题只是Tiered合并策略的问题,LSM-Tree的核心优势在于另外一个合并策略:Leveled Compact Strategy合并策略,这个合并策略将有效的解决这些问题

Leveled Compact Strategy合并策略

Tiered策略之所以有严重的写放大和空间放大问题,根问问题是因为每次Compact需要全量SSTable参与,开销自然就很大。

那么如果每次Compact的时候都只是部分SSTable参与,那么Compact过程的写放大和空间放大的问题就能够缓解。

Leveled合并策略的主要思想就是在Compact的时候,只是合并部分SSTable。它将SSTable进行了分层。

  • 将数据分成一系列Key互不重叠且固定大小的SSTable文件,并分层(Level)管理

  • 同时,系统记录每个SSTable文件存储的Key的范围。

LSM-Tree的核心思想是将数据的写入分成了两部分:内存部分和磁盘部分。写入过程:

  1. 首先写入内存的memTable,以及wal日志,写入就直接返回了。所以正常情况下,写入操作会非常的快。只是涉及一个内存操作和一个磁盘的顺序写操作。

  1. 当memTable达到一定的阈值的时候。就会将memTable flush到磁盘中。

  1. 新创建一个memTable,使用新的memTable来服务新的写入请求。

  1. 原来的memTable就变成了imutable memTable。然后将imutable memTable中的数据进行整理:按照key进行排序。

  1. 将排序后的imutable memTable直接刷到磁盘,在磁盘里对应的就是SStable。所以,在磁盘中,会不断新增SStable。这种直接由imutable memTable刷盘得到的SStable称为L0 SStable。L0 SStable也是按照时间生成的,只是按照key进行了排序,不会去做重复key的整理,所以L0 SStable中也是有重复的交叉key的。这么做的目的就是为了权衡flush效率,

  1. 随着系统的运行L0层的SStable越来越,系统中就会存在很多L0 SStable对应的很多小文件。这个时候就会按照一定的规则多(一般系统都会支持一层SStable数量和大小的策略)对L0层的SStable进行compact合并:将所有L0 SStable中的key进行排序、去重合并后,形成一个更大的L1 SStable,然后删除L0的SStable。因为L1 SStable生成的时候会有key的重复整理,L1中的各个SStable中的key都不是重复的。

另外就是在后续的L0 SStable compact过程中,还会结合现有的L1 SStable的情况,进行数据的均衡处理,让数据尽量均匀分散到各个L1 SStable中。

  1. 当L1 SStable越来越多的时候,还会继续将L1 SStable进行整理合并成L2 SStable。因为L1中各个SStable中的key是没有重复的,所以compact的时候是没必要所有的L1 SStable都参与,只是合并整理部分就好了,这样主要是可以减少单次compact的I/O等的开销。

Leveled策略的读放大

其实相比于Tired compact策略,Leveled策略并没有减少多少读放大。SStable依然是按照key有序的,那么读取的时候,如果有M个SSTable,每个SSTable文件中有N个key,那么复杂度依然是O(MLgo(N))

但是在实际实现的时候,会有一些优化措施:Leveled会有一个类似于协调节点的角色,来记录每个SStable的meta信息,比如该SStable中保存的key的范围,读取的时候通过这份meta数据,就可以精准的去对应的SStable找到对应的key的数据。而实际实现这个meta数据,可能就是给每个SStable维护一个BloomFilter过滤器,来快速获取某个key是否在该SSTable中存在。

但是需要注意的是,L0 SStable,因为有key的交叉,在读取数据的时候是分两步:

  1. 大于L0(L1及以上)的SStable中找到对应的key,因为这些SStable中都key都是没有重复的,那么只要找到一个就可以返回了。

  1. 遍历L0 SStable,找出对应key的值。因为L0 SStable按时间生成,是有key重复的情况,所以必须遍历所有L0 SStable,只是说可以利用给L0 SStable维护的BloomFilter加速遍历,不需要真的需要都去打开对应的文件。

  1. 合并从L0 SStable找到的key的值(可能是0个或者多个),以及从L1及以上SStable找到的key的值(可能是0个或者1个),合并后的就是最终的值。

所以整理的读取复杂度O(XlogN + (L-1)logN)=O((X+L-1)logN),其中X是L0中的SStable数量、L是层数、N是一个SSTable中的key的个数

但是需要注意的是,其实内存中还有一份数据,即memtable,这部分在读取的时候,还可以充当读取缓存,对于一些热数据,基本上都是在内存中,都不一定有IO发生。

Leveled策略写放大

Leveled策略对写放大是有明显改善的,除了L0以外,每次更新仅涉及少量SSTable。但是L0的Compact比较频繁,所以仍然是读写操作的瓶颈

Leveled策略空间放大

数据在同层的SSTable不重叠,这就保证了同层不会存在重复记录。而由于每层存储的数据量是按照比例递增的,所以大部分数据会存储在底层。因此,大部分数据是没有重复记录的,所以数据的空间放大也得到了有效控制

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

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

相关文章

idea debug elasticsearch8.6.2 源码

前置依赖&#xff1a; gradle 7.5.1&#xff1a;Gradle | Releases openJDK 17&#xff1a;https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe idea&#xff1a;IntelliJ IDEA 2022.1 (Ultimate Edition) 1、下载源码 8.6.2 zip包 并解压 地址&…

算法训练营 day57 动态规划 最长公共子序列 不相交的线 最大子序和(动态规划)

算法训练营 day57 动态规划 最长公共子序列 不相交的线 最大子序和&#xff08;动态规划&#xff09; 最长公共子序列 1143. 最长公共子序列 - 力扣&#xff08;LeetCode&#xff09; 给定两个字符串 text1 和 text2&#xff0c;返回这两个字符串的最长 公共子序列 的长度。…

spark为什么比hadoop快

网上一堆人根本对计算框架一知半解就出来糊弄人&#xff0c;常见解答有&#xff1a; spark是基于内存计算&#xff0c;所以快。这跟废话似的&#xff0c;mr计算的时候不也是基于内存&#xff1f; mr shuffle落盘。这也是胡扯&#xff0c; spark shuffle不落盘&#xff1f; 实际…

智能家居Homekit系列一智能灯泡

一、什么是智能灯 传统的灯泡是通过手动打开和关闭开关来工作。有时&#xff0c;它们可以通过声控、触控、红外等方式进行控制&#xff0c;或者带有调光开关&#xff0c;让用户调暗或调亮灯光。 智能灯泡内置有芯片和通信模块&#xff0c;可与手机、家庭智能助手、或其他智能…

[C++]string类模拟实现

目录 前言&#xff1a; 1. string框架构造 2. 默认函数 2.1 构造函数 2.2 析构函数 2.3 拷贝构造 2.4 赋值重载 3. 迭代器 4. 整体程序 前言&#xff1a; 本篇文章模拟实现了C中string的部分功能&#xff0c;有助于大家了解和熟悉string类&#xff0c;虽然这个类不难实…

SSM知识快速复习

SSM知识快速复习SpringIOCDIIOC容器在Spring中的实现常用注解Autowired注解的原理AOP相关术语作用动态代理实现原理事务Transactional事务属性&#xff1a;只读事务属性&#xff1a;超时事务属性&#xff1a;回滚策略事务属性&#xff1a;事务隔离级别事务属性&#xff1a;事务…

JSP+ACCESS网上拍卖平台系统

技术&#xff1a;Java、JSP等摘要&#xff1a;电子商务就是通过互联网来进行的各项商务活动&#xff0c;包括广告、交易、支付、服务等活动。电子商务源于英文Electronic Commerce,简写为EC或E-Commerce。它是人类社会、经济、科学、文化发展的必然产物&#xff0c;是信息化社会…

【计算机考研408】置换选择排序 + 代码 PAT 甲级 1171 Replacement Selection

王道-置换选择排序b站教学视频 置换选择排序的流程 图片比文字更好理解&#xff0c;故不加文字解释 当当前工作区已经满了并且找不到合适的放入当前归并段的元素的时候&#xff0c;开始生成下一个归并段。 此后重复上述过程。 计算机考研可能考察置换选择排序的知识点 …

网易蜗牛读书产品体验报告(1.9.6版本)

本文导览本文是网易蜗牛读书的产品体验报告&#xff0c;在移动阅读市场&#xff0c;网易蜗牛读书以其独特的深度阅读和领读人的阅读机制吸引了一大批的阅读爱好者和忠实用户。本文通过对网易蜗牛读书的体验分析&#xff0c;希望进一步加深对网易蜗牛读书产品的认识了解。产品概…

详细的IO面试题汇总

IO 流简介 IO 即 Input/Output&#xff0c;输入和输出。数据输入到计算机内存的过程即输入&#xff0c;反之输出到外部存储&#xff08;比如数据库&#xff0c;文件&#xff0c;远程主机&#xff09;的过程即输出。数据传输过程类似于水流&#xff0c;因此称为 IO 流。IO 流在…

pom依赖产生的各种问题

文章目录问题一(org.apache.ibatis.session.Configuration)解决方法问题二(ERROR StatusLogger No log4j2)解决方法问题三(com.google.common.util.concurrent)解决方法问题四(start bean documentationPluginsBootstrapper)解决方法问题五(Unable to infer base url. )解决办法…

(01)Unity 中使用 HDRP

概述Unity在2019.2版本中推出HDRP&#xff08;高清渲染管线&#xff09;&#xff0c;目的是为了提高图形质量&#xff0c;实现从照片写实到风格化的图像。先看一下官方对HDRP的概述&#xff1a;高清渲染管线 &#xff08;HDRP&#xff09; 是由 Unity 构建的高保真脚本化渲染管…

【golang/go语言】Go语言之反射

本文参考了李文周的博客——Go语言基础之反射。 一、反射初识 1. 什么是反射 在计算机科学中&#xff0c;反射是指计算机程序在运行时&#xff08;run time&#xff09;可以访问、检测和修改它本身状态和行为的一种能力。用比喻来说&#xff0c;反射就是程序在运行的时候能够…

【genius_platform软件平台开发】第八十八讲:arm公司的V架构和内核发展史(整理)

1. ARM公司简介 ARM&#xff08;Advanced RISC Machines&#xff09;有三种含义&#xff1a;它是一个公司的名称、它是一类微处理器的通称、它是一种技术的名称。 ARM 公司是微处理器行业的一家知名企业&#xff0c;它是知识产权供应商&#xff0c;设计基于ARM体系的处理器&a…

5-Azidopentanoic acid,79583-98-5,5-Azidopentanoic COOH具有高效稳定,高特异性

5-Azidopentanoic acid&#xff0c;5-Azidopentanoic COOH&#xff0c;5-叠氮基戊酸产品规格&#xff1a;1.CAS号&#xff1a;79583-98-52.分子式&#xff1a;C5H9N3O23.分子量&#xff1a;143.074.包装规格&#xff1a;1g&#xff0c;5g&#xff0c;10g&#xff0c;包装灵活&a…

Spring Data JPA 之 理解 Persistence Context 的核心概念

21 理解 Persistence Context 的核心概念 21.1 Persistence Context 相关核心概念 21.1.1 EntityManagerFactory 和 Persistence Unit 按照 JPA 协议⾥⾯的定义&#xff1a;persistence unit 是⼀些持久化配置的集合&#xff0c;⾥⾯包含了数据源的配置、EntityManagerFacto…

WideDeep模型

google提出的Wide&deep模型&#xff0c;将线性模型与DNN很好的结合起来&#xff0c;在提高模型泛化能力的同时&#xff0c;兼顾模型的记忆性。wide&deep这种将线性模型与DNN的并行连接模式&#xff0c;后来称为推荐领域的经典模式&#xff0c;奠定了后面深度学习模型的…

Containerd容器运行时将会替换Docker?

文章目录一、什么是Containerd&#xff1f;二、Containerd有哪些功能&#xff1f;三、Containerd与Docker的区别四、Containerd是否会替换Docker&#xff1f;五、Containerd安装、部署和使用公众号&#xff1a; MCNU云原生&#xff0c;欢迎微信搜索关注&#xff0c;更多干货&am…

一条 SQL 查询语句是如何执行的?

MySQL是典型的C/S架构&#xff08;客户端/服务器架构&#xff09;&#xff0c;客户端进程向服务端进程发送一段文本&#xff08;MySQL指令&#xff09;&#xff0c;服务器进程进行语句处理然后返回执行结果。 问题来了。服务器进程对客户端发送的请求究竟做了什么处理呢&#…

【大数据基础】Hadoop3.1.3安装教程

来源&#xff1a; https://dblab.xmu.edu.cn/blog/2441/ 前言&#xff1a;重装解决一切bug&#xff01;事实上&#xff0c;问题中的绝大部分衍生问题都可以通过重装解决。 实验内容 创建Hadoop用户 首先按 ctrlaltt 打开终端窗口&#xff0c;输入如下命令创建新用户 : sudo…