当前位置: 首页 > news >正文

第15章:索引的数据结构

一、为什么使用索引

1.索引是存储引擎用于快速找到记录的一种数据结构。相当于一本书的目录。在进行数据查找时,首先查看查询条件是否命中某条索引,符合则通过索引查找相关数据。如果不符合则需要全表扫描,一条一条查找记录,直到找到与条件符合的记录。

2.创建索引减少磁盘的I/O的次数,加快查询速度。

二、索引的优缺点

1.索引概述

①索引是MySQL高效获取数据的数据结构

②索引的本质:索引是数据结构,排好序的快速查找的数据结构

③索引是在存储引擎实现的,每种存储引擎不一定支持所有的索引类型。存储引擎定义表的最大索引数最大索引长度

2.索引优点

①索引提高数据检索的效率,降低数据库的IO成本

②通过创建唯一索引,保证数据库表每一行的数据唯一性

加速表和表之间的连接,对于有依赖关系的子表和父表联合查询时,可以提高查询速度

④使用分组和排序子句进行查询数据时,显著减少查询分组和排序的时间,降低CPU消耗

3.索引缺点

①创建索引和维护索引耗费时间,随着数据量增加,所耗费的时间增加

②索引占磁盘空间,存储在磁盘上

③索引提高查询速度,同时降低更新表的速度,在表中的数据增加,删除,修改,索引动态维护,降低数据的维护速度。

4.索引的提示

索引提高查询的速度,会影响插入的速度。这种情况下,最好的办法是先删除表中的索引,然后插入数据,插入完成再创建索引

三、InnoDB索引的推演

3.1没有索引情况下查找

3.1.1.在一个页查找

①主键查找

select *
from employees
where employee_id=101;

 在页目录使用二分法快速定位到对应的槽,然后再遍历槽对应分组的记录,快速找到指定的记录

②其他列作为条件(非主键的列)

select *
from employees
where last_name='Abel';

 只能从最小记录开始依次遍历单链表中的每条记录,判断是否符合条件,效率低。

3.1.2.在很多页查找

①定义到记录所在的页

②从所在的页查找对应的记录

没有索引情况下,不论根据主键还是其他列,只能从第一页沿着双向链表一直往下找,在每个页根据上面的查找方法查找指定的记录。非常耗时,所以索引来了。

3.2设计索引

建一个表

 ①index_demo表的行格式示意图

record_type:0是普通记录,2是最小记录,3是最大记录

next_record记录下一条数据的地址

②把一些记录存放到表里的示意图

3.2.1简单的索引设计方案

问题:想快速定位到需要查找的数据在哪些数据页,可以为数据页建立一个目录:

①所有数据页里面的记录的主键是递增的

 ②为数据页建立目录:当前页的主键最小值key,当前页号page_no

 

此时把目录项在物理存储器连续存储,实现主键快速查找某条记录的功能。

比如:查找主键20

①先从目录项根据二分法快速确定主键值为20在目录3中(12<20<209)

②在页中查找记录方法根据主键值二分法查找具体的记录

3.2.2InnoDB中的索引方案

①迭代1次:目录项记录的页,采用单向链表实现,便于增加和删除

 

record_type=1表示存放的是目录项

record_type=0 表示存放的是普通记录

目录项记录和普通用户记录的相同点:都会为主键值生成Page Directory(页目录),按照主键值进行查找时使用二分法加快查询速度。

比如:查找主键20

先从页30中通过二分法快速定位到对应目录项,因为(12<20<209),定位到页9

从页9使用二分法定位到主键值为20的用户记录

②迭代2次:多个目录项记录的页,双向链表

假设目录项记录的页最大记录是4,现在新添加的记录,所以要生成新的目录项的页

比如:查找主键20

确定目录项记录页,现在目录项页30和页32,页30的主键值范围是[1,320),页32是不小于320,所以在页30

通过目录项记录页根据二分法查找出对应的目录项,定位页9

在页9通过二分法定位到主键20的用户记录

③迭代3次:目录项记录页的目录页,大目录嵌套小目录

 生成存储高级目录项的页33,这个页中的两条记录代表页30和页32。

④这个结构就是B+树

B+树都不会超过4层,通过主键值查找某条记录最多需要4个页面内的查找。(3个目录项页,1个用户记录页),每个页面有page Directory页目录,可以通过二分法快速定位记录。

假设:普通数据页:100条用户记录 目录项记录页:1000条目录项记录

如果B+树只有1层,只有1个存放用户记录的节点,最多能存放 100 条记录。

如果B+树有2层,最多能存放 1000×100=10,0000 条记录。

如果B+树有3层,最多能存放 1000×1000×100=1,0000,0000 条记录。

如果B+树有4层,最多能存放 1000×1000×1000×100=1000,0000,0000 条记录

3.3常见索引的概念

3.3.1聚簇索引:主键构建的B+树

概念:

聚簇索引是一种数据存储方式,所有的用户记录都在叶子节点,索引即数据,数据即索引。

聚簇表示数据行和相邻的键值聚簇的存储在一起。InnoDB存储引擎会自动创建聚簇索引

特点:

①页内记录按照主键的大小排序成一个单向链表,有序的

②存放记录的页按照主键值大小顺序排成一个双向链表

③存放目录项记录的页按照主键值顺序排成一个双向链表

④B+树的叶子节点存储的是完整的用户记录

优点:

①数据访问快,聚簇索引将索引和数据保存在同一个B+树中。B+树的叶子节点就是完整的用户记录

②因为按照主键大小排序成一个单链表,排序查找和范围查找速度快

③查找范围的数据时,数据紧密相连,节省了大量IO操作

缺点:

①插入速度严重依赖插入顺序,否则会出现页的分裂,影响性能。因此InnoDB表,定义一个自增的ID列作为主键

②更新主键的代价很高。会导致更新行的移动。对于InnoDB表,定义主键不可更新

③二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。

限制:

①InnoDB支持聚簇索引,MyISAM不支持聚簇索引

②每个表只能有一个聚簇索引,该表的主键

③没有定义主键,InnoDB选择非空的唯一索引代替。没有的话,InnoDB隐式定义主键

④InnoDB的键尽量选择有序的id,不建议UUID,MD5,HASH,字符串作为主键

3.3.2非聚簇索引(二级索引,辅助索引):非主键构建的B+树

概念:

如果使用非主键字段进行查找,可以多建几棵B+树,每个树采用不同的排序规则。比如c2的列,进行查找。按照非主键列建立的B+树需要一次回表操作能定位到完整的用户记录,这种B+树是二级索引。

 叶子节点,数据页里面的数据按照c2的大小排序成单链表。用户记录不完整,存c2和主键项。

回表:(回聚簇索引)

根据c2的列(非主键列)大小排序的B+树,只能找到查找记录对应的主键值,二级索引没有完整的用户记录,所以需要到聚簇索引根据查找出的主键值再查一遍。这个过程就是回表。所以从非主键列条件查找一条记录需要2棵B+树

为什么要回表操作,把完整的用户记录存放到二级索引的叶子节点不行吗

太占内存空间。冗余大

一张表有1个聚簇索引和多个非聚簇索引。

 3.3.3联合索引:多个列作为排序规则,c2,c3组合

概念:

①把各个记录和页按照c2进行排序

②在c2列相同情况下,采用c3进行排序。

③本质上是二级索引,需要回表操作

④叶子节点用户记录是c2,c3和主键c1构成

3.4InnoDB的B+树索引的注意事项

3.4.1根页面内存位置万年不动

B+树的形成过程:

①当创建一个表的时候,底层为这个索引创建一个根节点,此时没有目录项和用户记录

②向表中插入数据时,先存储在根节点

③当根节点空间用满时(假设3条),此时根节点成为目录页复制一个新页(页a)

④再插入一个数据时,通过页分裂操作,得到页b。

⑤随着插入操作,叶子节点变多,目录项空间满了。此时根节点复制一个新目录页a

⑥当进行插入的时候,会把目录项存放到目录页b

当InnoDB用到这个索引的时候,都会从固定的地址找到这个根节点的页号,从而访问这个索引。

3.4.2内节点中目录项记录的唯一性(除了非叶子节点)

①B+树索引的内节点目录项是索引列+页号。假设一个表的数据是

 构建的二级索引B+树,如过插入一条数据 (8,1,’c’),就不知道是插入页4还是页5了。造成了目录项记录不唯一

②解决方法是目录项加入主键:索引列+主键值+页号

 3.4.3一个页面最少存储2条记录

四、MyISAM中的索引方案:B-Tree索引

1.介绍

MyISAM引擎使用B+Tree作为索引结构,但是叶子节点的data域存放的是数据记录的地址

2.原理

InnoDB中索引就是数据。但在MyISAM中索引和数据分开存储,非聚簇索引

 

①数据文件:用户记录的插入顺序单独储存的一个文件。不分页。不按照主键大小排序。不能使用二分法查找

②索引文件:存放索引信息的,为表中的主键创建一个索引。叶子节点存放的是主键值+数据记录的地址

3.MyISAM和InnoDB的对比

MyISAM的索引方式是“非聚簇的”,InnoDB包含1个聚簇索引

①在InnoDB中根据主键值对聚簇索引进行一次查找就能找到对应的记录。在MyISAM(非聚簇,二级索引)需要一次回表操作。

②InnoDB数据文件就是索引文件,索引即数据。但是MyISAM的数据文件和索引文件是分离的,索引文件保存的是数据的地址

③InnoDB的非聚簇索引的data域存放的是主键的值,而MyISAM存放的是记录的地址。

④MyISAM的回表十分迅速,拿着地址直接找数据。但InnoDB通过获取主键后在聚簇索引查找记录。

⑤InnoDB要求表必须有主键,MyISAM可以没有。在InnoDB如果没有指定,MySQL自动选择一个非空且唯一做主键。如果不存在这种类型,MySQL自动为InnoDB隐含字段做主键。

五、索引的代价

空间上代价

每次建立索引都是建立B+树,每一棵B+树的节点都是数据页。一个数据页默认16KB,许多数据页组成,就是一大片存储空间

时间上代价

每次对表中的数据增、删、改需要修改B+树的索引。B+树的节点按照索引列的值从小到大顺序排序双向链表。存储引擎需要额外的时间进行一些记录移位,页面分裂、页面回收等操作来维护好节点和记录的排序。

六、MySQL为什么选择B+树

选择标准

能让索引的数据结构尽量减少磁盘的I/O操作次数。索引是存储在外部磁盘上的,只能逐一加载到内存。MySQL衡量查询效率标准就是磁盘IO次数

1.Hash结构:数组+链表

 

问题1:为什么Hash效率高,索引结构使用的是树形呢?

①Hash索引仅能满足等于,不等于,in的等值查询。如果是范围查询,时间复杂度是O(n),树形是有序的,保持高效率

②Hash索引的缺陷是没有顺序的,order by 排序时要重新排序

③对于联合索引,Hash值是一起计算的,无法对单独一个键或几个索引键查询

④Hash索引不适合在重复值多的列上,比如性别,年龄。因为遇到Hash冲突时,需要遍历桶中的行指针进行比较,找到查询关键字非常耗时。

问题2:什么是InnoDB自适应的Hash索引?

如果某个数据经常被访问,当满足一定条件,当前的数据页地址就会放到Hash表中,当下次查询时,直接到找个页的位置。B+树也有了Hash的优点

 

 2.二叉搜索树

磁盘的IO次数跟索引树的高度是相关的。

为了提高查询效率,就需要 减少磁盘IO数 。为了减少磁盘IO的次数,就需要尽量 降低树的高度 ,需要把原来“瘦高”的树结构变的“矮胖”,树的每层的分叉越多越好。

3.AVL树:平衡二叉树

针对同样的数据,如果我们把二叉树改成 M 叉树 (M>2)呢?当 M=3 时,同样的 31 个节点可以由下面的三叉树来进行存储:

 4.B树:非叶子节点存放的也是数据

 

查找的关键字是 9步骤:

①与根节点的关键字 (17,35)进行比较,9 小于 17 那么得到指针 P1;

②按照指针 P1 找到磁盘块 2,关键字为(8,12),因为 9 在 8 和 12 之间,所以我们得到指针 P2;

③按照指针 P2 找到磁盘块 6,关键字为(9,10),然后我们找到了关键字 9。

5.B+

 

 

 

问题1:B+树和B树的区别

①B+树有K个关键字就有K个孩子,B树有K个关键字,孩子是K+1

②B+树中只有叶子节点存数据,B树叶子节点和非叶子节点都存放数据

③B+树所有的关键字都在叶子节点出现,构成一个有序链表,按照关键字从小到大排序。

问题2:为什么B+树非叶子节点不存放数据,好处是什么

①B+树查询效率更稳定:B+树访问到叶子节点才有数据,但是B树非叶子节点和叶子节点都有数据,查询不稳定

②B+树查询效率更高:B+树比B树更矮胖。查询IO次数少,B+树存储更多的节点关键字

③在查询范围上,B+树效率比B树高。B+树的数据都在叶子节点上,而且数据递增的。B树需要遍历才能完成查找,效率低。

问题3:为了减少IO,索引树会一次性加载吗?

①数据库索引是存储在磁盘上的,如果数据量很大。索引会很大,超过几个G

②当利用索引时,不能把几个G的索引加载到内存。逐一加载到每一个磁盘页,磁盘页对应着索引树的节点。

问题4:B+树的存储能力如何?为何说一般查找行记录,最多只需1~3次磁盘IO

InnoDB的存储引擎中页的大小为16KB,一个页大概存储1000个键值。深度为3的B+可以维护10亿条记录

实际情况每个节点不可能填充满,因此数据库中2-4层(包含根节点),因为根节点就在内存,所以只需1-3次磁盘的IO操作。

问题5:为什么说B+树比B-树更适合实际应用中操作系统的文件索引和数据库索引?

(回答B+树的优点)

①B+树查询效率更稳定:B+树访问到叶子节点才有数据,但是B树非叶子节点和叶子节点都有数据,查询不稳定

②B+树查询效率更高:B+树比B树更矮胖。查询IO次数少,B+树存储更多的节点关键字

③在查询范围上,B+树效率比B树高。B+树的数据都在叶子节点上,而且数据递增的。B树需要遍历才能完成查找,效率低。

问题6:Hash 索引与 B+ 树索引的区别

①Hash索引不能范围查找,B+树可以。Hash数据是无序,B+叶子节点是有序链表

②Hash索引的缺陷是没有顺序的,order by 排序时要重新排序。B+叶子节点是有序链表

③对于联合索引,Hash值是一起计算的,无法对单独一个键或几个索引键查询,B+树可以

④InnoDB不支持哈希索引

问题7:Hash索引与 B+ 树索引是在建索引的时候手动指定的吗?

根据MySQL的存储引擎决定的。

InnoDB和MyISAM存储引擎是B+树索引,但InnoDB提供自适应的Hash

Memory/Heap和NDB存储引擎,可以选择Hash索引

 

 

 

 

相关文章:

第15章:索引的数据结构

一、为什么使用索引 1.索引是存储引擎用于快速找到记录的一种数据结构。相当于一本书的目录。在进行数据查找时&#xff0c;首先查看查询条件是否命中某条索引&#xff0c;符合则通过索引查找相关数据。如果不符合则需要全表扫描&#xff0c;一条一条查找记录&#xff0c;直到…...

机械师曙光16电脑开机自动蓝屏怎么解决?

机械师曙光16电脑开机自动蓝屏怎么解决&#xff1f;有的用户在使用机械师曙光16电脑的时候&#xff0c;遇到了一些系统问题&#xff0c;导致自己无法正常的开机使用电脑。因为电脑总会变成蓝屏&#xff0c;无法进行任何操作。那么这个情况怎么去进行问题的解决呢&#xff1f;来…...

机器学习_Lasso回归_ElasticNet回归_PolynomialFeatures算法介绍_02---人工智能工作笔记0037

Lasso回归用的是L1正则化可以看到,这里的alpha就是这里的alpha对吧,就是 L1的权重 然后对于ElasticNet回归来说,这里的alpha可以看到是L1权重的超参数对吧,然后这里的p,表示的是 L2正则里面的(1-p)这里 这里要提一下: L1和L2为什么能防止过拟合,它们有什么区别?通过添加…...

第五篇:强化学习基础之马尔科夫决策过程

你好&#xff0c;我是zhenguo(郭震) 今天总结强化学习第五篇&#xff1a;马尔科夫决策过程 基础 马尔科夫决策过程&#xff08;MDP&#xff09;是强化学习的基础之一。下面统一称为&#xff1a;MDP MDP提供了描述序贯决策问题的数学框架。 它将决策问题建模为&#xff1a; 状态…...

Oracle面试题

1. 什么是存储过程&#xff0c;使用存储过程的好处&#xff1f; 存储过程&#xff08;Stored Procedure &#xff09;是一组为了完成特定功能的SQL 语句集&#xff0c;经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数&#xff08;如果该存储过程带有参数&#…...

用Vue写教务系统学生管理

文章目录 一.首先创建新的Demo二.在APP里面绑定DemoStudent三.源码附上四.效果图&#xff08;新增记录还未实现&#xff09; 一.首先创建新的Demo 二.在APP里面绑定DemoStudent <template><img alt"Vue logo" src"./assets/logo.png"><!--…...

专门用于管理企业与自己客户之间所有信息的客户管理系统

一、开源项目简介 关于 NXCRM NXCRM 是一套基于 Laravel 的 CRM 应用程序。它包含了一个管理中心&#xff0c;可以管理用户、客户、产品、订单、商机&#xff0c;合同&#xff0c;收款&#xff0c;附件&#xff0c;联系人&#xff0c;跟进动态&#xff0c;发票&#xff0c;业…...

(转载)基于多层编码遗传算法的车间调度算法(matlab实现)

以下内容大部分来源于《MATLAB智能算法30个案例分析》&#xff0c;仅为学习交流所用。 1 理论基础 遗传算法具有较强的问题求解能力&#xff0c;能够解决非线性优化问题。遗传算法中的每个染色体表示问题中的一个潜在最优解&#xff0c;对于简单的问题来说&#xff0c;染色体…...

Redis的常用数据结构之哈希类型

首先这里说的哈希类型针对的是redis中的value的k-v结构 常见的操作命令 hset设置值 hsetnx命令&#xff0c;不存在可以设置&#xff0c;存在设置不成功 hget取值&#xff0c;这里与字符串类型不同是要精确到filed。前面的判断也是基于field来实现的 要是field没有就返回null h…...

计算机组成原理-存储系统-缓存存储器(Cache)

目录 一、Cache基本概念 1.2性能分析 二、 Cache和主存的映射发生 ​​​​​​2.1全相连映射​编辑 2.2直接映射​编辑 2.3组相连映射 三、Cachae的替换算法 3.1 随机算法(RADN) 3.2 先进先出算法(FIFO) 3.3 近期最少使用(LRU) 3.4 最近不经常使用(LFU) 四、写策略 4…...

打开c语言生成exe文件,出现闪退的解决方法

为什么打开c语言生成的exe文件&#xff0c;立马闪退。 起初个别问的时候&#xff0c;我只是简单的说明程序运行完了&#xff0c;就自动关了&#xff0c; 首先&#xff0c;生成的exe文件本质是控制台程序&#xff0c;这些都是依赖于windows的控制台窗口&#xff0c;程序执行完…...

算法基础学习笔记——⑩DFS与BFS\树与图

✨博主&#xff1a;命运之光 ✨专栏&#xff1a;算法基础学习 目录 DFS与BFS\树与图 ✨DFS ✨BFS &#x1f353;宽搜流程图如下&#xff1a; &#x1f353;宽搜流程&#xff1a; &#x1f353;广搜模板 ✨树与图 &#x1f353;树是特殊的图&#xff08;连通无环的图&am…...

chatgpt赋能python:Python中可迭代对象的介绍

Python中可迭代对象的介绍 Python是一种高级编程语言&#xff0c;它具有简单易学、可读性强、功能强大等特点&#xff0c;成为了数据科学、机器学习、Web开发等领域的热门选择。Python中有很多重要的概念和功能&#xff0c;其中之一就是支持可迭代对象的概念。 在Python中&am…...

报表控件FastReport使用指南——如何打开WebP格式的图片

FastReport 是功能齐全的报表控件&#xff0c;可以帮助开发者可以快速并高效地为.NET&#xff0c;VCL&#xff0c;COM&#xff0c;ActiveX应用程序添加报表支持&#xff0c;由于其独特的编程原则&#xff0c;现在已经成为了Delphi平台最优秀的报表控件&#xff0c;支持将编程开…...

【鲁棒、状态估计】用于电力系统动态状态估计的鲁棒迭代扩展卡尔曼滤波器研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

整理6个超好用的在线编辑器!

随着 Web 开发对图像可扩展性、响应性、交互性和可编程性的需求增加&#xff0c;SVG 图形成为最适合 Web 开发的图像格式之一。它因文件小、可压缩性强并且无论如何放大或缩小&#xff0c;图像都不会失真而受到欢迎。然而&#xff0c;为了编辑 SVG 图像&#xff0c;需要使用 SV…...

ArcGIS10.8下载及安装教程(附安装步骤)

谷歌云&#xff1a; https://drive.google.com/drive/folders/10igu7ZSMaR0v0WD7-2W-7ADJGMUFc2ze?uspsharing ArcGIS10.8 百度网盘&#xff1a; https://pan.baidu.com/s/1s5bL3QsCP5sgcftCPxc88w 提取码&#xff1a;kw4j 阿里云&#xff1a; https://www.aliyundriv…...

AI智能照片编辑:AI Photo for Mac

AI Photo是一款Mac平台上的智能照片编辑软件&#xff0c;它基于人工智能技术&#xff0c;可以帮助用户快速、轻松地对照片进行编辑和美化。AI Photo提供了多种智能修复和美化功能&#xff0c;包括自动调整色彩、对比度、亮度、清晰度等&#xff0c;使得照片的质量得到有效提升。…...

Tuxera for Mac2023中文版读写硬盘U盘工具

在日常生活中&#xff0c;我们使用Mac时经常会遇到外部设备不能正常使用的情况&#xff0c;如&#xff1a;U盘、硬盘、软盘等等一系列存储设备&#xff0c;而这些设备的格式大多为NTFS&#xff0c;Mac系统对NTFS格式分区存在一定的兼容性问题&#xff0c;不能正常读写。 那么什…...

项目遇到的实际需求: java从信任所有证书到对server证书进行校验

最近项目上开发了一个rest api&#xff0c;放在了一台linux服务器上&#xff0c;并且启用了https连接&#xff1b;在另一台服务器上写了一个功能需要去调用linux机器上的api。 项目里面自己封装了一个HttpsClient的类&#xff0c;用来发送https请求&#xff0c;并且在里面重写了…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

rnn判断string中第一次出现a的下标

# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

springboot 日志类切面,接口成功记录日志,失败不记录

springboot 日志类切面&#xff0c;接口成功记录日志&#xff0c;失败不记录 自定义一个注解方法 import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;/***…...