PostgreSQL性能优化之体系结构

本文介绍 PostgreSQL 数据库的体系结构,包括实例结构(进程与内存)、存储结构(物理与逻辑)以及插件式存储引擎。

实例与数据库聚簇

PostgreSQL 使用典型的客户端/服务器(Client/Server)架构,客户端发送请求到服务端,服务端处理完成之后返回结果到客户端。下图显示了一个简化的 PostgreSQL 体系结构:

在这里插入图片描述

PostgreSQL 客户端可能是一个命令行工具、图形工具或者 Web 服务器,它们是数据库操作的请求者。

PostgreSQL 服务端由一个实例(Instance)以及一个数据库聚簇(Database Cluster)组成。

实例由一组后台进程和相关的内存组成,用于管理数据库。启动服务器进程时创建一个实例,关闭服务器进程时实例随之关闭。

数据库聚簇包含多个数据库,一个数据库由一组相关的对象组成,例如表、索引、视图、存储过程等。

提示:PostgreSQL 数据库聚簇代表了单个主机上单个实例管理的一组数据库,它不是由一组数据库服务器组成的集群。

客户端和服务端通常位于不同的主机中,它们之间通过 TCP/IP 网络协议进行连接和通信,默认端口为 5432。当客户端和服务端位于相同的主机时,也可以通过 Unix 域套接字进行通信。

实例结构

PostgreSQL 实例由一组进程和相关的内存组成,用于管理物理数据库。下图描述了实例的结构:

实例

每当客户端进程请求连接数据库时,PostgreSQL 服务进程(postgres)负责监听连接请求并验证客户端信息。验证通过之后主服务进程会为每一个客户端连接创建一个新的后端进程,然后客户端进程和对应的后端进程(postgres)直接通信,后端进程代表客户端执行各种数据库操作并返回结果。

数据库进程

PostgreSQL 服务进程(server process)是其他进程的父进程,当我们启动 PostgreSQL 服务时首先会创建该进程,然后它再分配共享内存(shared memory)并启动各种后台进程。服务进程还负责监听客户端连接请求,默认监听端口为 5432。在早期版本中,PostgreSQL 服务进程也被称为 postmaster。

PostgreSQL 后端进程(backend process)用于代表客户端执行数据库操作,服务进程在验证客户端连接请求后为其创建新的后端进程,在客户端断开连接时终止对应的后端进程。

提示:PostgreSQL 使用类似 Oracle 中的专用服务器模式,每个客户端进程连接到一个专用的后端进程。后端进程在客户端会话期间不被任何其他客户端共享。每个新的会话都会分配一个专用的后端进程。

PostgreSQL 支持的最大客户端连接数由系统参数 max_connections 控制,默认值为 100。

PostgreSQL 后台进程(background processes)用于执行各种数据库管理操作,主要包括:

  • 后台写进程(background writer),负责定期将共享缓冲池(shared buffer pool)中的脏页写入磁盘。
  • 检查点进程(checkpointer),发生检查点时负责将检查点记录写入 WAL 段文件,同时刷新共享缓冲池中的脏页。
  • 自动清理启动进程(autovacuum launcher),定期调用工作进程(autovacuum worker)完成清理工作。
  • WAL 写进程(wal writer),定期将 WAL 缓冲数据写入 WAL 段文件。
  • 统计收集进程(stats collector),收集数据库系统运行的统计信息,PostgreSQL 15 版本优化删除。
  • 归档进程(archiver),负责 WAL 段文件归档,也就是日志归档。
  • 日志收集进程(logger),记录数据库错误日志。

除了以上进程之外,PostgreSQL 还会基于不同配置启动其他后台进程。例如,流复制相关的 walsender(发送 WAL 数据)以及 walreceiver(接收 WAL 数据)进程,用户自定义实现的后台工作进程(Background Worker Process)等。

后台写进程

后台写进程负责定期将共享缓冲池中的脏页写入磁盘,默认情况下每隔 200 毫秒(bgwriter_delay)刷新一次磁盘,每次最多刷新 100 个缓冲页(bgwriter_lru_maxpages)。这种刷新脏页的方式可以尽量减少对数据库性能的影响。

另外,PostgreSQL 9.1 版本之前,后台写进程还需要负责检查点过程。PostgreSQL 9.2 开始,单独的检查点进程开始负责这部分工作。

检查点进程

检查点进程负责检查点(Checkpoint)操作,也就是将检查点记录写入 WAL 段文件并且刷新共享缓冲池中的全部脏页。

以下情况都会触发检查点操作:

  1. 距离上一次检查点操作的时间间隔到达参数 checkpoint_timeout 的配置,默认为 300 秒。
  2. PostgreSQL 9.4 以及更低版本,上一次检查点操作之后写入的 WAL 段文件数据到达参数 checkpoint_segments 的配置,默认值为 3。
  3. PostgreSQL 9.5 以及更高版本,pg_wal(pg_xlog)目录中 WAL 段文件总大小超过参数 max_wal_size 的配置,默认值为 1 GB。
  4. PostgreSQL 数据库服务以 smart(SIGTERM)或者 fast(SIGINT)模式关闭。
  5. 超级用户或者 pg_checkpoint 特权用户手动执行 CHECKPOINT 命令。

检查点机制可以将内存中的脏数据刷新到磁盘,并且生成一个一致性的数据库状态。系统崩溃后,执行数据库恢复时可以从最近的检查点开始,优化恢复性能。

自动清理启动进程

自动清理启动进程负责定期调用工作进程执行清理流程(VACUUM 以及 ANALYZE),默认情况下每隔 1 分钟(autovacuum_naptime)运行一次,每次最多调用 3 个(autovacuum_max_workers)工作进程。

WAL 写进程

WAL 写进程负责定期将 WAL 缓冲数据(XLOG)写入 WAL 段文件,这些文件位于 pg_wal 子目录中。

WAL 写进程默认 200 毫秒(wal_writer_delay)刷新一次缓冲,可以避免一次提交大量数据时的磁盘写入瓶颈。

统计收集进程

PostgreSQL 14 以及之前的版本中存在统计收集进程,负责收集系统运行时的统计信息,并且通过 pg_stat_activity 等动态视图提供数据。

PostgreSQL 15 版本开始使用累积统计系统,基于共享内存存储统计信息,优化了性能,同时删除了独立的统计收集进程。

归档进程

归档进程负责 WAL 段文件的连续归档,在发生 WAL 段切换时将其复制到归档区域。日志归档功能可以用于物理热备以及即时点恢复(PITR)。

如果想要启动 WAL 归档,需要将配置参数 wal_level 设置为 replica 或者更高级别,同时将配置参数 archive_mode 设置为 on,然后在 archive_command 参数中设置归档命令或者在 archive_library 参数中指定归档模块。

日志收集进程

日志收集进程负责将错误信息记录到错误日志文件,该进程由配置参数 logging_collector 控制,默认设置为 on。

内存结构

PostgreSQL 实例的内存结构可以分为以下两个大类:

  • 共享内存区(Shared Memory Area)。
  • 本地内存区(Local Memory Area)。
共享内存区

PostgreSQL 实例启动时分配共享内存区,它是所有服务端进程共享的内存区,具体可以分为共享缓冲池(shared buffer pool)、WAL 缓冲(WAL buffer)、提交日志缓冲(CLOG)等。

共享缓冲池用于加载磁盘中的表和索引数据,并且在内存中进行操作,从而减少磁盘 I/O,提高性能。共享缓冲池的大小通过参数 shared_buffers 进行配置,默认值为 128 MB。

虽然对于 shared_buffers 没有具体的推荐值,但是可以针对具体的系统计算出一个大概的值。一般来说,对于专用的数据库服务器,shared_buffers 大概可以设置为系统内存的 25%。增加 shared_buffers 的值通常可以提高性能,例如,当整个数据库都可以被加载到缓存中时,可以明显减少磁盘的读取操作。由于 PostgreSQL 还依赖于操作系统的缓存,大于内存 40% 的 shared_buffers 并不会带来性能的提示,反而可能会下降。

另外,增加 shared_buffers 的值通常也需要相应地增加 max_wal_size 的值,以便延长检查点的时间间隔。

PostgreSQL 使用预写日志(WAL)确保数据的持久性;与 shared_buffers 作用类似,PostgreSQL 将 WAL 日志(XLOG)写入缓冲并且批量写入磁盘。

默认的 WAL 缓冲大小由 wal_buffers 参数进行设置,初始值为 4MB(shared_buffers 的 1/32)。WAL 缓冲区在每次事务提交时都会写入磁盘,因此过大的值并不会带来显着的性能提升。不过,对于大量并发的写入操作,适当增加该参数的值可以提高系统的性能。

CLOG 缓冲存储了每个事务的状态(IN_PROGRESS、COMMITTED、ABORTED 以及 SUB_COMMITTED),用户事务管理和并发控制。当 PostgreSQL 关闭服务或者执行检查点过程时,会将 CLOG 数据写入 pg_xact(pg_clog)子目录文件中;当 PostgreSQL 服务启动时,会从文件中加载初始 CLOG。

共享内存区还包括许多其他子区,例如用于实现各种访问控制机制(信号量、轻量级锁、共享锁、排他锁等)的内存,各种后台进程(checkpointer、autovacuum 等)使用的内存,事务处理(保存点、两阶段提交等)所需的内存。

本地内存区

本地内存区是为每个后端进程动态分配的独享内存区,用于执行查询处理、数据排序、哈希连接等操作,以及存储临时表和会话级别的数据。

本地内存区主要包括工作内存(work_mem)、维护工作内存(maintenance_work_mem)以及临时缓冲(temp_buffers)。

工作内存用于查询处理过程中的数据排序(ORDER BY、DISTINCT)以及表之间的连接(Hash Join、Sort Merge Join)等操作。工作内存由参数 work_mem 进行配置,默认为 4 MB。

如果设置了合适的 work_mem,大部分的排序操作都在内存中执行,而不需要使用磁盘存储临时结果。对于复杂的查询,可能会执行并发的排序或者哈希操作,每个操作都可以最多使用该参数设置的内存。另外,多个会话可能同时执行排序操作。因此,排序占用的总内存可能是 work_mem 的许多倍;work_mem 的值不能设置的过高,因为它可能导致内存使用瓶颈。

维护工作内存主要用于数据库维护操作,例如 VACUUM、CREATE INDEX 以及 ALTER TABLE ADD FOREIGN KEY 等操作。这些操作在执行时可能需要较大的内存空间来优化性能。

配置参数 maintenance_work_mem 指定了维护工作内存的大小,默认值为 64 MB。由于一个数据库会话同时只能执行一个维护操作,一般不会存在并发的维护操作;所以将该参数设置的比 work_mem 大很多也不会有问题,更大的维护内存还能够提高数据库清理和数据导入的性能。

临时缓冲用于存储临时表数据。每个会话都可以使用单独的临时缓冲来存储临时表的数据,以提高访问效率。

配置参数 temp_buffers 用于设置临时缓冲的大小,默认为 8MB。

存储结构

一个 PostgreSQL 实例管理一个数据库聚簇,它可以包含多个数据库。这里的聚簇不是多台服务器组成的集群。

物理存储

一个数据库聚簇通常对应操作系统中的一个目录,也就是根目录(PGDATA)。使用 SHOW 命令查看如下:

SHOW data_directory;data_directory                     |
-----------------------------------+
D:/Program Files/PostgreSQL/17/data|

根目录包含多个子目录和文件:

PS D:\Program Files\PostgreSQL\17\data> lsMode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         2024/6/17     10:44                base
d-----         2024/7/11     14:35                global
d-----         2024/7/22     17:08                log
d-----         2024/6/17     10:44                pg_commit_ts
d-----         2024/6/17     10:44                pg_dynshmem
d-----         2024/7/11     14:39                pg_logical
d-----         2024/6/17     10:44                pg_multixact
d-----         2024/6/17     10:44                pg_notify
d-----         2024/6/17     10:44                pg_replslot
d-----         2024/6/17     10:44                pg_serial
d-----         2024/6/17     10:44                pg_snapshots
d-----         2024/7/11     14:34                pg_stat
d-----         2024/6/17     10:44                pg_stat_tmp
d-----         2024/6/17     10:44                pg_subtrans
d-----         2024/6/17     10:44                pg_tblspc
d-----         2024/6/17     10:44                pg_twophase
d-----         2024/6/17     10:44                pg_wal
d-----         2024/6/17     10:44                pg_xact
-a----         2024/7/23     17:16             45 current_logfiles
-a----         2024/6/17     10:44           5639 pg_hba.conf
-a----         2024/6/17     10:44           2712 pg_ident.conf
-a----         2024/6/17     10:44              3 PG_VERSION
-a----         2024/6/17     10:44             90 postgresql.auto.conf
-a----         2024/6/17     10:44          31602 postgresql.conf
-a----         2024/7/11     14:34             91 postmaster.opts
-a----         2024/7/11     14:34             70 postmaster.pid

下表列出了这些目录和文件的描述。

项目类型描述
base目录包含多个子目录,每个目录对应一个数据库。
global目录存储全局(聚簇)级别的数据表,例如 pg_database 等。控制文件也存储在这个目录中。
log目录存储服务器日志信息。
pg_commit_ts目录保存事务提交时间戳数据。
pg_dynshmem目录存储动态共享内存子系统使用的文件。
pg_logical目录存储逻辑解码状态数据。
pg_multixact目录存储用于共享行锁的多事务(multitransaction)状态数据。
pg_notify目录存储 LISTEN/NOTIFY(消息通知机制)状态数据。
pg_replslot目录存储复制槽数据。
pg_serial目录存储已提交的串行化事务信息。
pg_snapshots目录存储导出的快照。
pg_stat目录存储统计子系统使用的持久化文件。
pg_stat_tmp目录存储统计子系统使用的临时文件。
pg_subtrans目录存储子事务状态数据。
pg_tblspc目录存储表空间目录的符号链接。
pg_twophase目录存储预备事务(两阶段提交)的状态文件。
pg_wal目录存储预写式日志(WAL)文件。
pg_xact目录存储事务提交状态数据。
current_logfiles文件记录当前写入的服务器日志文件。
pg_hba.conf文件客户端认证配置文件。
pg_ident.conf文件用户名映射文件。
PG_VERSION文件记录 PostgreSQL 主版本号。
postgresql.auto.conf文件存储使用 ALTER SYSTEM 命令设置的参数信息。
postgresql.conf文件主配置参数文件。
postmaster.opts文件记录服务器上次启动时使用的命令行选项。
postmaster.pid文件记录主服务进程 ID,数据库聚簇根目录,主服务进程启动时间戳,服务端口、Unix 域套接字目录(可空),第一个有效的监听地址以及共享内存段 ID 等信息。该文件在服务启动时创建,服务停止时删除。

其中,base 子目录存储了每个数据库的数据文件和索引文件等内容:

PS D:\Program Files\PostgreSQL\17\data\base> lsMode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----         2024/6/20      9:09                1
d-----         2024/6/17     10:44                4
d-----         2024/7/11     14:35                5

每个数字子目录对应一个数据库的标识符(OID),使用 SQL 查询数据库信息如下:

select oid, datname
from pg_database;oid|datname  |
---+---------+5|postgres |1|template1|4|template0|

数据库中的对象存储在各自的子目录中,pg_relation_filepath 函数可以用于查询对象的文件路径(相对于根目录):

SELECT pg_relation_filepath('public.animal');pg_relation_filepath|
--------------------+
base/5/73734        |

animal 是数据库 postgres 中的一个表,它的 OID 为 73734,数据文件为根目录下的 base/5/73734。

表空间

在 PostgreSQL 中,表空间(tablespace)表示数据文件的存放目录,这些数据文件代表了数据库的对象,例如表或索引。创建数据库对象时,只需要指定存储对象的表空间的名称(或者使用默认值),而不需要指定磁盘上的物理路径。当我们访问表时,系统通过它所在的表空间定位到对应数据文件所在的位置。

PostgreSQL tablespace

PostgreSQL 中的表空间与其他数据库系统不太一样,它更偏向于一个物理上的概念。

表空间的引入为 PostgreSQL 的管理带来了以下好处:

  • 如果数据库集群所在的初始磁盘分区或磁盘卷的空间不足,又无法进行扩展,可以在其他分区上创建一个新的表空间以供使用。
  • 管理员可以根据数据库对象的使用统计优化系统的性能。例如,可以将访问频繁的索引存放到一个非常快速且可靠的磁盘上,比如昂贵的固态硬盘。与此同时,将很少使用或者对性能要求不高的归档数据表存储到廉价的低速磁盘上。

PostgreSQL 在集群初始化时将默认创建了两个表空间:

  • pg_default, template1 和 template0 默认的表空间,也是创建其他数据库时的默认表空间;对应的目录为 PGDATA/base。
  • pg_global,用于存储一些集群级别的共享系统表(system catalogs),例如 pg_database、pg_control;对应的目录为 PGDATA/global。

创建表和索引时的默认表空间使用参数 default_tablespace 进行配置。使用 CREATE 命令指定表空间的语法如下:

CREATE TABLE ...
TABLESPACE ts_name;

逻辑存储

一个数据库聚簇包含多个数据库。数据库由一组相关的对象组成,例如表、索引、视图、存储过程等。数据库中的对象使用模式(Schema)进行逻辑组织。准确地说,一个数据库由多个模式组成,模式由许多对象组成。

PostgreSQL 的逻辑存储结构如下图所示:

在这里插入图片描述
多个数据库之间是物理隔离的,每个数据库在 PostgreSQL 中都对应一个独立的目录,其中包含该数据库的所有数据文件和元数据。客户端连接服务器时需要指定数据库名称,连接到一个数据库的客户端无法查询另一个数据库中的数据,除非使用外部数据封装器(FDW)。

一个数据库中的多个模式之间是逻辑隔离的,不同模式中可以存在同名的对象,例如 schema1 和 schema2 中都可以存在名为 test 的数据表。PostgreSQL 权限管理系统控制模式对象的访问,访问对象时可以包含模式名称,例如 schema1.test。

每个数据库对象都有一个唯一的标识符(OID),它是一个无符号的四字节整数。这些标识符用于在系统表中唯一标识不同的数据库对象。例如,数据库的 OID 存储在 pg_database 表中,模式的 OID 存储在 pg_namespace 表中,关系(表、索引、序列、视图、复合类型等)的 OID 存储在 pg_class 表中。通过这些标识符,PostgreSQL 能够在内部有效地管理和引用各种数据库对象。

存储引擎

PostgreSQL 12 开始支持插件式表访问方法(Table Access Method),基于这个接口可以实现不同的数据存储引擎,针对特定的工作负载定制数据的存储和检索方式,从而提高系统的整体性能。

在这里插入图片描述

默认的数据存储引擎为 heap(堆表),使用参数 default_table_access_method 进行设置:

SHOW default_table_access_method;default_table_access_method|
---------------------------+
heap                       |

用户创建表或者物化视图时可以指定存储引擎,语法如下:

CREATE TABLE ...
USING method;

除了默认的 heap 之外,已知正在开发的存储引擎包括 columnar 和 OrioleDB 等。

PostgreSQL 也支持插件式索引访问方法(Index Access Method),并且基于这个接口实现了 B-Tree、Hash、GiST、GIN 等不同的索引类型,同时用户也可以扩展自定义的索引类型,从而优化不同场景下的查询性能。

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

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

相关文章

基于Intel x86+FPGA+AI工业整机,支持医疗CT扫描仪应用

众所周知,医学影像设备是医疗器械行业中最具发展潜力的细分领域之一,诸如CT扫描仪(简称:CT)便是医生用于多种疾病临床检查和诊治时的理想选择。 医疗CT扫描仪的发展潜力及难点 CT,即电子计算机X线断层扫描&…

计算机网络:构建联结的基础

目录 1. 网络拓扑结构 1.1 星型拓扑 1.2 环型拓扑 1.3 总线型拓扑 1.4 网状拓扑 2. 传输介质 2.1 双绞线 2.2 同轴电缆 2.3 光纤 2.4 无线电波 3. 协议栈模型 3.1 OSI模型 3.2 TCP/IP模型 4. 网络设备 4.1 交换机 4.2 路由器 4.3 网关 4.4 防火墙 5. IP地址…

2024年数字化社会、信息科学与风险管理研讨会(ICDIR 2024,9月20-22)

2024年数字化社会、信息科学与风险管理研讨会(ICDIR 2024)作为2024年人工智能与数字管理国际学术会议(ICAIDM 2024)的分论坛,将携手主会齐于2024年9月22-24日在中国江苏省南京市隆重召开。 会议旨在为从事数字化社会、…

DjangoRF实战-2-apps-users

1、用户模块 创建一个用户模块子应用,用来管理用户,和认证和授权。 1.1根目录创建apps, 为了使用方便,还需要再pycharm中设置一下资源路径,就可以自动提示 1.2注册子应用 1.3添加应用根目录到环境变量path python导…

Java---后端文件上传详解

袁门才俊志高远, 震古烁今意决然。 风采翩翩才情显, 雄姿英发立世间。 目录 一,简单案例演示 二,服务器本地存储 三,配置单个文件上传大小限制 一,简单案例演示 首先简单编写一个前端网页: &l…

vue3+openLayers点击标记事件

<template><!--地图--><div class"distributeMap" id"distributeMap"></div> </template> <script lang"ts" setup> import { onMounted, reactive } from "vue"; import { Feature, Map, View }…

C++中的依赖注入

目录 1.概述 2.构造函数注入 3.setter方法注入 4.接口注入 5.依赖注入框架 6.依赖注入容器 7.依赖注入框架的工作原理 8.依赖注入的优势 9.总结 1.概述 依赖注入是一种设计模式&#xff0c;它允许我们在不直接创建对象的情况下为对象提供其依赖项&#xff1b;它通过将…

模拟信号介绍

定义&#xff1a; 模拟信号是指用连续变化的物理量表示的信息&#xff0c;其信号的幅度、频率或相位随时间作连续变化&#xff0c;或在一段连续的时间间隔内&#xff0c;其代表信息的特征量可以在任意瞬间呈现为任意数值的信号。我们通常又把模拟信号称为连续信号&#xff0c;它…

Pytorch使用教学6-张量的分割与合并

在使用PyTorch时&#xff0c;对张量的分割与合并是不可避免的操作&#xff0c;本节就带大家深刻理解张量的分割与合并。 在开始之前&#xff0c;我们先对张量的维度进行深入理解&#xff1a; t2 torch.zeros((3, 4)) # tensor([[0., 0., 0., 0.], # [0., 0., 0., 0.…

java发送https请求支持tls1.3

说明&#xff1a;java 8_u201及以下版本不支持tls1.3协议发送。最直接的方法是升级到该版本之上。 另外&#xff1a;需要修改一下代码强行使用tls1.3协议。如果只修改代码&#xff0c;不升级java版本会报错找不到该协议。

【基于PSINS】UKF/SSUKF对比的MATLAB程序

UKF与SSUKF UKF是&#xff1a;无迹卡尔滤波 SSUKF是&#xff1a;简化超球面无迹卡尔曼滤波 UKF 相较于传统的KF算法&#xff0c;UKF能够更好地处理非线性系统&#xff0c;并且具有更高的估计精度。它适用于多种应用场景&#xff0c;如机器人定位导航、目标跟踪、信号处理等。…

【解决方案】华普微基于CMT2189D的低功耗广域网解决方案

一、方案概述 随着物联网的快速发展&#xff0c;对于无线通信的需求越来越高。传统的通信技术可能无法满足物联网设备的特殊要求&#xff0c;如低功耗、长距离覆盖和大规模连接。LPWAN技术应运而生&#xff0c;旨在为物联网设备提供低成本、低功耗的远距离通信解决方案。ZETA作…

【Qt】Qt容器和STL容器的区别

1、简述 Qt容器和STL容器略有不同,作为一个Qter,应该知道它们之间的异同。 Qt容器官网介绍:https://doc.qt.io/qt-5/containers.html STL容器官网介绍:https://zh.cppreference.com/w/cpp/container 2、Qt容器和STL容器的对应关系 注意:QList 与 std::list 无关,QSet …

<数据集>铁路工人安全帽安全背心识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;3065张 标注数量(xml文件个数)&#xff1a;3065 标注数量(txt文件个数)&#xff1a;3065 标注类别数&#xff1a;3 标注类别名称&#xff1a;[vest, helmet, worker] 序号类别名称图片数框数1vest305978832helmet…

谷粒商城实战笔记-59-商品服务-API-品牌管理-使用逆向工程的前后端代码

文章目录 一&#xff0c; 使用逆向工程生成的代码二&#xff0c;生成品牌管理菜单三&#xff0c;几个小问题 在本次的技术实践中&#xff0c;我们利用逆向工程的方法成功地为后台管理系统增加了品牌管理功能。这种开发方式不仅能快速地构建起功能模块&#xff0c;还能在一定程度…

Go语言常见序列化协议全面对比

先说结论 从易用性、性能、内存占用、编码后大小等几个方面综合考虑 ProtoBuf 胜出。 Gob 从性能和 I/O 带宽占用上都和 ProtoBuf 差不多&#xff0c;唯一劣势是编解码时内存占用较多。考虑到不用再写 IDL 带来的易用性&#xff0c;如果整个系统内不存在使用除 Go 以外其他语言…

使用 Snorkel 和 MinIO 的以数据为中心的 AI

如今&#xff0c;业界都在谈论大型语言模型及其编码器、解码器、多头注意力层和数十亿&#xff08;即将数万亿&#xff09;的参数&#xff0c;人们很容易相信好的人工智能只是模型设计的结果。不幸的是&#xff0c;事实并非如此。好的人工智能需要的不仅仅是一个精心设计的模型…

医疗器械ce认证办理流程介绍

CE认证是的产品安全认证&#xff0c;所有进入市场的医疗器械都必须进行医疗器械CE认证&#xff0c;医疗器械CE认证为了解决成员国之间的贸易壁垒&#xff0c;组织逐步将自己建成一个统一的大市场&#xff0c;以确保人员、服务、资本和产品(如医疗器械)的自由流通。在医疗器械领…

查找手机归属地轻松快捷,专业手机号码归属地数据源

在如今的信息社会中&#xff0c;手机已经成为了人们生活中不可或缺的一部分。当我们接到一个陌生的电话时&#xff0c;或者想了解一个电话号码的归属地时&#xff0c;我们可以借助一些工具来查找手机归属地。本文将介绍一种轻松快捷、专业的手机号码归属地数据源&#xff0c;并…

box-shadow属性的复合写法及高级用法,超详细!

前言&#xff1a;最近又叕看到了一个好看的特效&#xff0c;随后整理了一下&#xff0c;发现实现起来主要靠一个css属性就实现了&#xff0c;有一次刷新了我对css强大的认知&#x1f60e;&#xff0c;这个属性就是box-shadow&#xff0c;平常我们用到的比较少&#xff0c;但是针…