【PostgreSQL内核学习(二十五) —— (DBMS存储空间管理)】

news2025/7/9 7:03:50

DBMS存储空间管理

  • 概述
    • 块(或页面)
      • PageHeaderData 结构体
      • HeapTupleHeaderData 结构
    • 表空间
      • 表空间的作用:
      • 表空间和数据库关系
      • 表空间执行案例
    • 补充 —— 模式(Schema)

声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果,力求遵循合理使用原则,并在适用的情况下注明引用来源。
本文主要参考了 postgresql-10.1 的开源代码和《OpenGauss数据库源码解析》和《PostgresSQL数据库内核分析》一书以及一些相关资料。

概述

  在数据库管理系统(DBMS)中,空间管理是指如何在物理存储介质上组织、管理和优化数据的存储。这是 DBMS 性能和效率的关键因素之一。空间管理通常涉及以下概念:块(或页面)区间(区域或范围)表空间数据库。下面详细解释这些概念:

  1. 块(或页面)
      块(在 Oracle 中称为,在 SQL ServerPostgreSQL 中称为页面是数据库管理系统存储数据的基本单位。一个块通常是从磁盘上以固定大小读取和写入的数据块,这个大小可以是 2KB、4KB、8KB 等,根据数据库的配置而定。每个块包含了一系列的记录,这些记录是数据库中存储的实际数据。
  2. 区间(Extents)
      区间是一系列连续的块。当表或索引等数据库对象需要更多空间时,DBMS 会分配一个或多个区间。每个区间包含固定数量的块。区间使得数据库对象能在物理上连续存储,从而提高访问速度。

  3.   段是一个或多个区间的集合,通常用于存储特定类型的数据库对象,如索引回滚数据。段内的空间管理旨在优化数据存储访问性能。当一个段的现有区间被填满时,数据库会分配新的区间以供进一步的数据存储。
  4. 表空间
      表空间是数据库中存储数据的逻辑容器,它将数据文件与数据库的物理结构分离。一个数据库可以包含多个表空间,每个表空间由一个或多个数据文件组成。表空间允许数据库管理员管理数据库的存储结构,例如,通过指定特定的表或索引应该存储在哪个表空间中,或者通过为特定的表空间分配更多的磁盘空间。
  5. 数据库
      数据库是最高级别的存储结构,包含了所有的表空间、段、区间和块它是所有数据库对象和数据的逻辑集合,由多个物理文件(如数据文件、日志文件等)支持。数据库的设计和结构反映了如何在整个系统中组织和管理数据。

  在 DBMS 中,这些概念共同工作,形成了一个复杂的存储管理框架,旨在优化数据存取性能、提高数据管理的灵活性以及确保数据的完整性和安全性。通过有效地管理空间,DBMS 能够支持大规模的数据存储,同时保持良好的性能和高效的数据访问速度。

块(或页面)

  在 PostgreSQL 中,表数据存储在称为pages)或blocks)的结构中,每个页的大小通常是 8KB。下图是 page 的整体结构图:(图片来源:这一次终于把PostgreSQL Page结构搞懂了)
在这里插入图片描述
  下面是对图中的各个组成部分的解释:(更多详细信息可以参考 Postgresql手册)

  1. 表文件: 表数据存储在多个连续的页或块中,这些页按块编号顺序存储在文件系统中。图中显示了第 0 个(0th)、第 1 个(1st)和第 N 个(N-th)页,意味着这是一个表文件的序列。
  2. 页(Page): 每个页的大小是 8192 字节(8KB)。这是 PostgreSQL 中默认的页大小,虽然在编译时可以配置为其他大小。
  3. 页头信息(Header Info): 每个页的开始部分是页头信息,包含以下字段:
    pd_lsn: 日志序列号(Log Sequence Number),记录了最后一次修改该页的事务日志位置。
    pd_checksum: 页的校验和,用于检测数据损坏。
    pd_flags: 页的标志,表明页的状态或属性。
    pd_pagesize_version: 包含页大小和版本信息。
    pd_special: 指向页中特殊数据区域的指针。
    pd_prune_xid: 可以修剪该页的最小事务ID
    pd_lower: 指向该页中第一个空闲空间的指针。
    pd_upper: 指向该页中最后一个空闲空间的指针。
  4. 行指针(Line Pointers): 页头之后是一系列的行指针,它们指向页内部的各个记录(也称为元组或 tuple)。这些行指针是排序的,行指针 1 指向第一个元组,行指针 2 指向第二个元组,以此类推。
  5. 元组(Tuples): 元组是实际存储记录(record data)的地方,即表中的一行。图中显示了两个元组,元组 1 和元组 2
  6. 空闲空间(Free Space / Hole): 页中未被使用的部分称为空闲空间或洞(hole)。当页中的数据被删除或更新时,可能会在页中产生空闲空间。

  在 PostgreSQL 中,页(或块)是表数据存储的基本单位。每次数据插入或更新时,数据都被写入这些页中。数据库管理系统会管理这些页的分配和回收,以有效利用存储空间。图中的表示是一个典型的 PostgreSQL 数据页的抽象表示,它展示了如何在页中组织数据。

PageHeaderData 结构体

  下面我么来看一下 PageHeaderData 结构体,一个数据库页可以包含多个元组。PageHeaderData 负责管理页级别的信息,包括页中有多少空间可用,以及元组在页中的位置。
  PageHeaderData 结构体用于表示 PostgreSQL 数据库中的页头。它包含了一系列的元数据字段,用于描述页(或块)的状态和内容。其结构体源码如下所示:(路径:src\include\storage\bufpage.h

typedef struct PageHeaderData
{
    /* LSN 是 *任何* 块的成员,不仅仅是页组织的块 */
    PageXLogRecPtr pd_lsn;      /* 日志序列号(LSN):最后一次更改此页的xlog记录的下一个字节 */
    uint16        pd_checksum;  /* 页校验和 */
    uint16        pd_flags;     /* 标志位,具体含义见下文 */
    LocationIndex pd_lower;     /* 自由空间开始的偏移量 */
    LocationIndex pd_upper;     /* 自由空间结束的偏移量 */
    LocationIndex pd_special;   /* 特殊空间开始的偏移量 */
    uint16        pd_pagesize_version; /* 页大小和页布局版本号 */
    TransactionId pd_prune_xid; /* 最老的可裁剪事务ID,如果没有则为零 */
    ItemIdData    pd_linp[FLEXIBLE_ARRAY_MEMBER]; /* 行指针数组 */
} PageHeaderData;

在这里插入图片描述

HeapTupleHeaderData 结构

  页中的每个元组都有一个 HeapTupleHeaderData 结构,这个结构跟踪了与该元组相关的特定信息,例如元组的事务可见性信息元组的长度,以及元组中哪些列是空值。当数据库需要读取或写入一行数据时,它会先查找包含该行的页,然后使用 PageHeaderData 中的信息找到该页中的具体元组位置,最后读取或更新该元组的 HeapTupleHeaderData 以及它后面的实际数据。
  简而言之,PageHeaderData 用于管理页级别的结构和空间,而 HeapTupleHeaderData 用于管理页内单个元组级别的结构和元数据。两者结合起来允许 PostgreSQL 管理和维护表中行的存储和检索。HeapTupleHeaderData 结构体源码如下所示:(路径:src\include\access\htup_details.h

struct HeapTupleHeaderData
{
	union
	{
		HeapTupleFields t_heap;    /* 如果是一个普通的元组,则使用此结构 */
		DatumTupleFields t_datum;  /* 如果是一个只有一个数据项的元组(比如返回函数结果),则使用此结构 */
	}			t_choice;          /* 用于存储元组的不同数据类型 */

	ItemPointerData t_ctid;		/* 当前元组的元组标识符(TID),或者新元组的TID,
                                 * 或者是一个推测性插入的标识 */

	/* 以下字段必须与MinimalTupleData结构匹配! */

	uint16		t_infomask2;	/* 属性数量加上各种标志位 */

	uint16		t_infomask;		/* 各种标志位,详细内容见下文 */

	uint8		t_hoff;			/* 包括位图、填充在内的头部大小 */

	/* ^ - 23 字节 - ^ */

	bits8		t_bits[FLEXIBLE_ARRAY_MEMBER];	/* 用于表示NULL值的位图 */

	/* 结构体末尾还有更多数据 */
};

解释一些关键部分:

  1. t_choice 字段是一个联合体union),它根据元组的使用上下文存储不同的数据。如果元组是表的一部分,它会使用 t_heap;如果元组是一个单独的数据项,它会使用 t_datum
  2. t_ctid 是一个 ItemPointerData 类型,用来存储当前元组的位置信息。这个位置可以是元组在表中的实际位置,或者在某些情况下(例如,一个尚未提交的插入操作),它可能是一个推测性插入的标记。
  3. t_infomask2t_infomask 是两个掩码字段,包含了元组的元数据,比如属性数量是否有空值等。
  4. t_hoff头部的大小,包括任何位图必要的填充
  5. t_bits 是一个位图,用来表示元组中每个属性是否为 NULL。这个数组是可伸缩的,其大小取决于表的属性数量。

  详细信息参考下表(更多详细信息可以参考 Postgresql手册)
在这里插入图片描述

表空间

  表空间是 PostgreSQL 中数据文件的物理存储位置。它允许数据库管理员定义数据库对象在磁盘上的存储位置。每个表空间可以指向文件系统中的一个目录,不同的数据库对象(如表和索引)可以存储在不同的表空间中。
  表空间概念与数据库关系如下图所示:(图片来源:地址)
在这里插入图片描述
  上图显示了 PostgreSQL 数据库集群的物理存储布局。图中展示了 PostgreSQL 数据库集群(Database Cluster)如何组织,以及数据在文件系统中的存储方式。图中的布局说明了 PostgreSQL 数据库集群的层次性和模块化设计它允许多个数据库独立存在于同一个数据库集群中每个数据库可以有自己的表空间用户和权限设置。同时,通过 PGDATA表空间的物理路径,数据库管理员可以在文件系统级别管理和优化数据存储。以下是每个组件的详细解释:

  1. Database Cluster(数据库集群):
  • 这是最外层的绿色虚线框,代表 PostgreSQL 的数据库集群。数据库集群是指一个 PostgreSQL 服务实例,它可以包含多个数据库
  1. PGDATA/:
  • 这个文件夹代表 PostgreSQL 的数据目录,通常环境变量 PGDATA 指向这个位置。这个目录包含了所有数据库文件配置文件(如 postgresql.confpg_hba.conf)、WAL 日志等。
  1. template0:
  • 这是 PostgreSQL 中的一个特殊数据库,作为创建新数据库的模板。它是只读的,以防止用户更改可能会影响新数据库创建的设置。
  1. newdb1 和 newdb2:
  • 这些代表在数据库集群中创建的用户数据库每个数据库都有自己的用户和表集合,这些都被存储在数据库对应的文件和目录中。
  1. tablespace/:
  • 这个文件夹代表一个表空间目录PostgreSQL 中的表空间允许数据库管理员定义数据文件在文件系统中的存储位置。用户可以创建多个表空间来组织数据文件的物理存储。
  1. 数据库对象:
  • 图中的蓝色圆柱代表数据库对象,如表和索引。图中的网格状图标代表

表空间的作用:

  表空间是数据库中的一个逻辑存储单位,它定义了数据在底层文件系统中的存储位置,使得数据库管理员能够有效地组织和管理数据文件。通过将数据分配到不同的表空间,管理员可以优化数据库性能,实现灵活的存储管理,提高数据安全性,以及更容易地进行数据库的备份与恢复。表空间的使用还允许进行细粒度的数据隔离和容量规划,它们是数据库架构中关键的元素,尤其在大型、分布式或高性能的数据库系统中扮演着至关重要的角色。
  在 PostgreSQL 中,利用表空间,管理员可以细致地规划和调整数据库的磁盘布局。首先,当数据库的默认存储位置因为空间耗尽而无法扩展时,表空间可以创建在其他分区,为系统的维护和扩展提供了灵活性。其次,表空间使得管理员能够根据数据库对象的实际访问和性能需求进行调优,例如,将高频访问的索引放置在快速的存储介质上,而将低频访问的档案数据放置在成本较低的存储解决方案上
  执行\db可以查看表空间:

postgres=# \db
       List of tablespaces
    Name    |  Owner  | Location
------------+---------+----------
 pg_default | kuchiki |
 pg_global  | kuchiki |
(2 rows)

  pg_defaultpg_global 是两个预定义的表空间,它们有特定的用途和作用:

pg_default 表空间
  pg_defaultPostgreSQL默认的表空间。如果在创建数据库对象(如索引)时未指定特定的表空间,这些对象会默认存储在 pg_default 表空间中。实际上,如果你创建一个数据库而不指定表空间,它也会被创建在 pg_default 表空间。这个表空间通常位于 PostgreSQL 数据目录的基础路径下,也就是 PGDATA/base 目录。

pg_global 表空间
  pg_global 表空间用于存储跨越整个数据库集群(或实例)的全局数据,例如共享的系统目录。这些数据不属于特定数据库,而是对整个 PostgreSQL 实例的所有数据库可见。pg_global 包含了一些全局表,这些表对所有数据库都很重要,比如存储用户信息和权限的表。pg_global 通常位于 PGDATA/global 目录。

表空间和数据库关系

  下面描绘了从 PostgreSQL 的系统目录 pg_catalog.pg_database 中检索数据库的相关信息。pg_catalog.pg_database 是一个系统表,包含了 PostgreSQL 实例中所有数据库的元数据

postgres=# select oid, datname, datlastsysoid, dattablespace from pg_catalog.pg_database;
  oid  |  datname  | datlastsysoid | dattablespace
-------+-----------+---------------+---------------
     1 | template1 |         15093 |          1663
 15093 | template0 |         15093 |          1663
 15098 | postgres  |         15093 |          1663
(3 rows)

  下面这条 SQL 命令从 pg_catalog.pg_tablespace 系统目录中查询了所有表空间的信息

postgres=#  select oid,* from pg_catalog.pg_tablespace;
 oid  |  spcname   | spcowner | spcacl | spcoptions | spcmaxsize | relative
------+------------+----------+--------+------------+------------+----------
 1663 | pg_default |       10 |        |            |            | f
 1664 | pg_global  |       10 |        |            |            | f
(2 rows)

  其中,spcowner表空间的所有者,用其用户的 OID 表示。在这个例子中,OID10 的用户是这两个表空间的所有者。OID 10 通常是初始设置的超级用户,如 postgresspcacl访问控制列表,定义了哪些用户和角色拥有该表空间的访问权限。spcoptions 为表空间的其他选项。spcmaxsize 为表空间的最大大小,这里为空,意味着没有设置最大大小限制。relative 这个字段标识表空间路径是否是相对于 PostgreSQL 数据目录的。这里的 ‘f’ 表示 “false”,意味着这些表空间的路径是绝对路径,不是相对于 PostgreSQL 数据目录的。

  在 PostgreSQL 中,表空间Tablespace)是存储数据的物理位置,而数据库Database)是存储和组织数据的逻辑容器。从查询结果来看,所有列出的数据库(template1、template0postgres默认使用同一个表空间 OID 1663,即 pg_default,来存储它们的数据。这表明在这个实例中,所有用户定义的数据和对象默认存储在 pg_default 表空间,而 pg_global 表空间(OID 1664)是用来存储全局数据,如跨数据库的共享目录。这样的设计允许数据库管理员在必要时将数据库对象的物理存储与数据库逻辑结构分离,从而提供了更大的灵活性和对磁盘布局的控制。

  查看表的存储路径与大小如下所示:

postgres=# select pg_size_pretty(pg_relation_size('test'));
 pg_size_pretty
----------------
 8192 bytes
(1 row)

表空间执行案例

  1. 创建表空间
-- 创建一个名为 test_tablespace 的表空间,指向一个真实存在的目录
CREATE TABLESPACE test_tablespace LOCATION '/path/to/test_tablespace_directory';
-- 请确保 /path/to/test_tablespace_directory 路径存在,且 PostgreSQL 服务有权限读写该路径。

postgres=# CREATE TABLESPACE test_tablespace LOCATION '/home/kuchiki/tablespace';
CREATE TABLESPACE
postgres=# select oid,* from pg_catalog.pg_tablespace;
  oid  |     spcname     | spcowner | spcacl | spcoptions | spcmaxsize | relative
-------+-----------------+----------+--------+------------+------------+----------
  1663 | pg_default      |       10 |        |            |            | f
  1664 | pg_global       |       10 |        |            |            | f
 32784 | test_tablespace |       10 |        |            |            | f
(3 rows)

在这里插入图片描述
2. 在新创建的表空间中创建一个表并插入数据

postgres=# CREATE TABLE test (
postgres(#     id SERIAL PRIMARY KEY,
postgres(#     data TEXT
postgres(# ) TABLESPACE test_tablespace;
NOTICE:  CREATE TABLE will create implicit sequence "test_id_seq" for serial column "test.id"
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"
CREATE TABLE
postgres=# INSERT INTO test (data) VALUES ('Sample data 1'), ('Sample data 2'), ('Sample data 3');
INSERT 0 3
postgres=# SELECT * FROM test;
 id |     data
----+---------------
  1 | Sample data 1
  2 | Sample data 2
  3 | Sample data 3
(3 rows)

  查看 test 表的 oid

postgres=# SELECT oid, relname AS table_name
postgres-# FROM pg_class
postgres-# WHERE relname = 'test';
  oid  | table_name
-------+------------
 32798 | test
(1 row)

  在新建的表空间下查询到对应的 testoid:
在这里插入图片描述
  插入数据后可以看到表空间大小变大:
在这里插入图片描述
  查看一下 3280232804 对应的是什么表?

postgres=# SELECT relname AS table_name
postgres-# FROM pg_class
postgres-# WHERE oid = 32802;
   table_name
----------------
 pg_toast_32798
(1 row)

postgres=# SELECT relname AS table_name
FROM pg_class
WHERE oid = 32804;
      table_name
----------------------
 pg_toast_32798_index
(1 row)

  这里 pg_toast_32798pg_toast_32798_index 分别是什么呢?下面来解释一下:
  在 PostgreSQL 中,当你创建一个新表(例如 test 表)时,除了表本身对应的 OID 外,你可能还会注意到与该表相关的其他几个 OID 出现在系统目录中。这些通常与 TOAST 机制有关。对于你提到的 pg_toast_32798pg_toast_32798_index,它们分别代表 TOAST 表TOAST 表的索引

注:TOAST (The Oversized-Attribute Storage Technique)
  TOASTPostgreSQL 用来处理大数据字段(如 TEXT、BYTEA)的一种机制。当一个表的行中包含的数据超过页面大小(默认为 8KB)时,PostgreSQL 会使用 TOAST压缩和/或分割这些大字段,将它们存储在一个专门的 TOAST 表中。这样做的目的是为了提高存储效率和查询性能。

  pg_toast_32798 是针对 test自动生成的 TOAST 表,用于存储 test 表中超过页面大小的大型字段数据32798test 表的 OID,而 pg_toast_32798 使用这个 OID 来确保 TOAST 表的名称是唯一的。TOAST 表本身就像普通的 PostgreSQL 表,但它是系统自动管理的,通常用户不需要直接与之交互
  pg_toast_32798_indexpg_toast_32798 TOAST 表的索引,用于快速定位和检索 TOAST 表中的数据。这个索引同样是系统自动生成的,目的是优化对 TOAST 表数据的访问。索引的 OID(在这个例子中是 32804)与 TOAST 表的 OID 相关联,确保索引的唯一性

  1. 删除表
      执行drop table test;后可以观察到表空间清零;
    在这里插入图片描述
  2. 删除表空间
      执行DROP TABLESPACE test_tablespace;后可以观察到表空间被删除;
    在这里插入图片描述

补充 —— 模式(Schema)

  数据库中的模式(Schema)是定义和组织数据库内部数据结构的逻辑框架,它包含了一组数据库对象,如视图索引函数。模式的作用在于提供了一种方式来逻辑上对数据库对象进行分组管理,使得数据组织更为清晰,同时支持对数据访问的细粒度控制。通过使用模式,可以在同一数据库内创建隔离的环境,以便不同的用户或应用可以在不相互干扰的情况下操作自己的数据集合,这对于多用户数据库系统尤为重要。此外,模式也是数据库设计的一个关键组成部分,有助于实现数据的逻辑结构规划,确保数据完整性和安全性,以及简化数据库的维护和管理工作。

postgres=# \dn
    List of schemas
    Name     |  Owner
-------------+---------
 cstore      | kuchiki
 dbe_perf    | kuchiki
 pkg_service | kuchiki
 public      | kuchiki
 snapshot    | kuchiki
(5 rows)

  这个 PostgreSQL 命令 \dn 的输出显示了数据库中存在的模式(Schema)列表及其所有者。在给出的输出中,列出了五个不同的模式,以及每个模式的所有者。这里的所有者是 kuchiki(本人),这意味着 kuchiki 用户拥有这些模式,并且有权限对它们进行管理和操作。此外:

  1. cstore: 用于特定的存储或应用,与列存储有关。
  2. dbe_perf: 这个模式的表示它与数据库性能Database Performance)相关,用于存储性能测试监控数据
  3. pkg_service: 这个模式用于某种服务包管理
  4. public: PostgreSQL 默认创建的模式,所有用户默认都有访问这个模式的权限。通常,如果没有指定模式,对象会被创建在 public 模式下。
  5. snapshot: 这个模式用于保存数据库的快照或某种形式的备份数据

与模式相关的详细内容可以查看这篇文章:【PG】PostgreSQL 模式(Schema)。

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

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

相关文章

小华和小为的聚餐地点 - 华为OD统一考试

OD统一考试(C卷) 分值: 200分 题解: Java / Python / C 题目描述 小华和小为是很要好的朋友,他们约定周末一起吃饭。 通过手机交流,他们在地图上选择了多个聚餐地点(由于自然地形等原因,部分聚…

支付宝直连商户处理支付交易投诉管理,支持多商户

大家好,我是小悟 1、问题背景 玩过支付宝生态的,或许就有这种感受,如果收到投诉单,不会通知到手机端,只会在支付宝商家后台-账号中心-安全中心-消费者投诉-支付交易投诉那里显示。那你能一直盯着电脑看吗?…

多维时序 | Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序列预测

多维时序 | Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序列预测 目录 多维时序 | Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 Matlab实现CNN-RVM卷积神经网络结合相关向量机多变量时间序…

梳理cuda算子编译与python调用的流程_以vllm为例

最近在使用vllm框架,部署大语言模型的时候。发现吞吐量提升比较明显。对里面用到的技术比较感兴趣。后来发现vllm使用了一些新的技术,如kv cache,page attention等。其中很多是用cuda编写加速的。并且对cuda算子如何应用到python服务中比较感兴趣,现在就自己的了解,用文章…

如何进行嵌入式系统的软件性能监测和优化

嵌入式系统的软件性能监测和优化是确保系统能够高效运行和性能稳定的关键步骤。嵌入式系统通常包含有限的计算资源和受限的能源消耗,因此对其进行有效的性能监测和优化是至关重要的。本文将介绍嵌入式系统软件性能监测和优化的基本概念、常见方法和技术,…

SQL报错注入

SQL注入报错注入 报错注入原理:报错注入是通过特殊函数错误使用并使其输出错误结果来获取信息的在遇到有报错回显的时候,但是没有数据回显的情况下可以利用报错注入的函数: 1.floor():向下取整 2.extractvalue(): 对XML文档进行查询的函数,当参数的格式…

代码随想录算法训练营第42天 | 01背包问题,你该了解这些! 01背包问题,你该了解这些! 滚动数组 416. 分割等和子集

目录 01背包问题,你该了解这些! 01 背包 二维dp数组01背包 💻实现代码 01背包问题,你该了解这些! 滚动数组 一维dp数组(滚动数组) 💻实现代码 416. 分割等和子集 &#x1f…

位运算之妙用:识别独特数字(寻找单身狗)

目录 找单身狗1 图解: 代码如下: 找单身狗2 图解: 代码如下: 寻找单身狗1 从数组中 的1 2 3 4 5 1 2 3 4 中找出没有另一个相同的数与其匹配的数 这个问题的原理是利用异或运算的性质。异或运算(XOR&#xff09…

游戏如何选择服务器

一个网络游戏要想长期运行下去,关键是用户体验,在初期阶段的游戏服务器租用环节就显得尤为重要。那么问题来了,游戏公司如何才能够在众多的服务器商中租用找到高性能、高性价比的游戏服务器租用呢?租用游戏服务器时需要考虑的因素…

vite, vue3, vue-router, vuex, ES6学习日记

学习使用vitevue3的所遇问题总结&#xff08;2024年2月1日&#xff09; 组件中使用<script>标签忘记加 setup 这会导致Navbar 没有暴露出来&#xff0c;导致使用不了&#xff0c;出现以下报错 这是因为&#xff0c;如果不用setup&#xff0c;就得使用 export default…

Leetcode—2881. 创建新列【简单】

2024每日刷题&#xff08;一零九&#xff09; Leetcode—2881. 创建新列 实现代码 import pandas as pddef createBonusColumn(employees: pd.DataFrame) -> pd.DataFrame:employees[bonus] employees[salary] * 2return employees 运行结果 之后我会持续更新&#xf…

Deepin如何开启与配置SSH实现无公网ip远程连接

文章目录 前言1. 开启SSH服务2. Deppin安装Cpolar3. 配置ssh公网地址4. 公网远程SSH连接5. 固定连接SSH公网地址6. SSH固定地址连接测试 前言 Deepin操作系统是一个基于Debian的Linux操作系统&#xff0c;专注于使用者对日常办公、学习、生活和娱乐的操作体验的极致&#xff0…

leetcode刷题(剑指offer)113.路径总和Ⅱ

113.路径总和Ⅱ 给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [5,4,8,11,null,13,4,7,2,null,null,5,1], tar…

解锁教育系统源码的定制奥秘:企业培训平台开发详解

今天&#xff0c;小编将为大家讲解教育系统源码的奥秘&#xff0c;详细解释企业培训定制开发的关键步骤和技术要点。 一、需求分析与设计阶段 设计阶段则包括系统的整体架构设计、数据库设计以及用户界面设计等方面。 二、技术选型与开发环境搭建 通过使用版本控制系统、集成…

解决WARNING: IPv4 forwarding is disabled. Networking will not work的具体操作步骤

IPv4转发禁用警告&#xff1a;网络无法正常工作 在使用网络连接的过程中&#xff0c;我们可能遇到警告消息“WARNING: IPv4 forwarding is disabled. Networking will not work”&#xff08;警告&#xff1a;IPv4转发已禁用&#xff0c;网络将无法正常工作&#xff09;。这个…

2024美赛E题数学建模思路代码数据分享

2024 ICM Problem E: Sustainability of Property Insurance 本题要求选取不同大陆上经历极端天气的两个地区来为保险公司开发模型&#xff0c;本题的重点是找到尽可能多而全的数据&#xff0c;包括天气数据&#xff0c;经济数据&#xff0c;人口数据等。 模型选择&#xff1a…

【Python】【完整代码】解析Excel文件内容,按每列首行元素名打印出某个字符串的统计占比(超详细)

目录 1.示例&#xff1a; 1.1 实现代码1&#xff1a;列数为常量 运行结果&#xff1a; 1.2 实现代码2&#xff1a;列数为变量 运行结果&#xff1a; 1.示例&#xff1a; 开发需求&#xff1a;读取Excel文件&#xff0c;统计第3列到第5列中每列的"False"字段占…

C语言——P/文件操作

一、为什么使用文件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久…

数据结构—基础知识:哈夫曼树

文章目录 数据结构—基础知识&#xff1a;哈夫曼树哈夫曼树的基本概念哈夫曼树的构造算法哈夫曼树的构造过程哈夫曼算法的实现算法&#xff1a;构造哈夫曼树 数据结构—基础知识&#xff1a;哈夫曼树 哈夫曼树的基本概念 哈夫曼&#xff08;Huffman&#xff09;树又称最优树&…

gtest测试框架

文章目录 前言1 单元测试2 gtest安装3 gtest原理4 断言4.1 明确指定或失败4.2 布尔条件4.3 二元比较4.4 谓词断言4.5 死亡测试5 gtest使用5.1 测试函数5.2 测试类5.3 测试夹具5.4 类型参数化5.5 事件总结前言 GoogleTest(GTest) 是谷歌开源的 C++ 单元测试框架。 1 单元测试…