百亿美金的设计,深度剖析 GitLab 的 Postgres 数据库 schema

lunix gitlab+postgresql搭建gitlab私服实现高可用 搭建内网高可用gitlab私服,lunix下gitlab+postgresql实现高可用。实现方法:两台服务器上部署完全一样的gitlab,其中gitlab有关文件采用 inotify + rsync 进行同步,数据库采用psql主从,且实现开机自启与数据自动备份。 阅读详情

原文链接

这篇文章写于 2022 年,前一年 GitLab 刚好完成 IPO。目前 GitLab 市值超过 100 亿美金,它的所有收入都来源于同名产品 GitLab,而这篇文章就是全面分析 GitLab 这个产品的数据库 schema。

我花了一些时间研究 GitLab 的 Postgres schema。GitLab 是 Github 的一个替代品。你可以自部署 GitLab,因为它是一个开源的 DevOps 平台。

我之所以要了解 Gitlab 这样的大项目的 schema,是为了与我正在设计的 schema 进行比较,并从他们的 schema 定义中学到一些最佳实践。我确实从中受益良多。

我清楚的知道,最佳实践取决于具体情况,不能盲目应用。

GitLab 的数据库 schema 文件 structure.sql [1] 包含超过 34000 行代码。GitLab 本质上是一个集成式的 Ruby on Rails 应用。虽然通常我们会用 schema.rb 文件来管理数据库的版本迁移,但 GitLab 团队在他们的问题追踪系统中的一个讨论 [2] 说明了他们选择 structure.sql 的原因。

原因在于 schema.rb 只能包含标准的迁移操作(使用 Rails DSL),这样做是为了使数据库 schema 文件对数据库系统保持中立,抽象化特定的 SQL 操作。这导致我们无法利用 PostgreSQL 的一些高级特性,如触发器、分区、物化视图等。

为了充分利用这些高级特性,我们应该考虑使用纯 SQL 格式的schema 文件 structure.sql,而不是 Ruby/Rails 的标准架构文件 schema.rb。

这意味着我们需要修改配置 config.active_record.schema_format = :sql,并重新以 SQL 格式生成数据库 schema。这可能还需要调整一些构建流程。 现在,让我们回顾一下我从 GitLab Postgres schema 中学到的东西。

为表使用正确的主键类型

在我的工作中,我犯了主键类型标准化的错误。这意味着将 bigint 或 uuid 标准化,这样所有表无论其结构、访问模式和增长速度如何,都将具有相同的类型。

当数据库规模较小时,这不会产生任何明显的影响,但当数据库规模扩大时,主键就会对存储空间、写入速度和读取速度产生明显的影响。因此,我们在为表选择正确的主键类型时应进行适当的思考。

正如我在之前的一篇文章 [3] 中所讨论的,当你使用 Postgres 本地 UUID v4 类型而不是 bigserial 类型时,表的大小会增加 25%,插入率则会下降到 bigserial 类型的 25%。这是一个很大的差别。我还与 ULID 进行了比较,但它的性能也很差。其中一个原因可能是 ULID 的实现。

在这种情况下,我很想了解 GitLab 是如何选择主键类型的。

在 573 个表中,380 个表使用 bigserial 主键类型,170 个表使用 serial4 主键类型,其余 23 个表使用复合主键。他们没有使用 uuid v4 主键或其他类似 ULID 的深奥键类型的表。

file

1 quintillion = 10 亿 billion

选择 serial 还是 bigserial 取决于表中记录的数量。

application_settings、badges、chat_teams、notification_settings、project_settings 等表使用串行类型。对于一些表,如 issues、web_hooks、merge_requests 和 projects,我很惊讶地发现它们使用了 serial 类型。

这个 serial 类型可能适用于自部署的社区或企业版本,但对于 GitLab.com SaaS 服务,这可能会造成问题。例如,GitHub 在 2020 年拥有 1.28 亿个公共仓库 [4]。即使每个仓库有 20 个问题,也会超过序列范围。此外,更改表格类型的成本也很高。表需要被重写,意味着你需要耐心等待。如果要对表进行分片,这同样会成为一个问题。

我做了一个快速实验,结果表明,对于我这个有两列和 1000 万条记录的表,将数据类型从 integer 改为 bigint 需要 11 秒。

create table exp_bs(id serial primary key, n bigint not null)

插入 1000 万条记录

insert into exp_bs(n) select g.n from generate_series(1,10000000) as g(n)

变更数据类型

alter table exp_bs alter column id TYPE bigint;

ALTER TABLE
Time: 10845.062 ms (00:10.845)

您还必须更改序列以改变其类型。这种操作很快。

alter sequence exp_bs_id_seq as bigint;

ALTER SEQUENCE
Time: 4.505 ms

所有 bigserial 序列都从 1 开始,直到 bigint 的最大值。

CREATE SEQUENCE audit_events_id_seq
    START WITH 1
    INCREMENT BY 1
    NO MINVALUE
    NO MAXVALUE
    CACHE 1;

使用内部和外部 ID

通常,不向外部世界公开主键是一个好习惯。这在你使用 integer 或 bigint 型的顺序自增标识符时尤为重要,因为它们是可预测的。

因此,我很想知道在创建 GitLab 问题时会发生什么。是向外部用户公开主键 id,还是使用其他 id?如果公开 issues 表的主键 id,那么在项目中创建 issue 时,它就不会以 1 开头,你可以很容易猜出 GitLab 中存在多少个问题。这既不安全,用户体验也很差。

为了避免将主键暴露给终端用户,常见的解决方案是使用两个 ID。第一个是你的主键 id,它保持在系统内部,从不暴露于任何公共环境。第二个 id 是我们与外部世界共享的。根据我过去的经验,我使用 UUID v4 作为外部 id。正如我们在前一点中讨论的,使用 UUID 有存储成本。

GitLab 也在需要与外部世界共享 id 的表中使用内部和外部 id。像 issues、ci_pipelines、deployments、epics 以及其他一些表有两个 id - id 和 iid。下面是 issue schema 的一部分。如下所示,iid 的数据类型为 integer。

CREATE TABLE issues (
    id integer NOT NULL,
    title character varying,
    project_id integer,
    iid integer,
    // ……)

正如你所看到的,有 id 和 iid 两列。iid 列的值与最终用户共享。一个 issue 使用 project_id 和 iid 进行唯一标识。这是因为可能有多个 issue 具有相同的 iid。为了更清楚地说明这一点,如果您创建了两个项目,并在每个版本库中创建了一个 issue,那么这两个项目的可见 ID 都必须是 1,如下图所示。sg 和 sg2 项目都以 issue ID 1 开始。

https://gitlab.com/shekhargulati123/sg/-/issues/1
https://gitlab.com/shekhargulati123/sg2/-/issues/1

它们在 project_id 和 iid 上都有一个唯一索引,以便快速有效地获取 issue。

CREATE UNIQUE INDEX index_issues_on_project_id_and_iid ON public.issues USING btree (project_id, iid);

使用带有检查约束的 text 字符类型

Postgres 文档 [5] 中描述了三种字符类型。

file

我主要使用 character varying(n) 或 varchar(n) 来存储字符串值。GitLab schema 既使用character varying(n),也使用 text,但更常用的是 text 类型。下面是一个这样的示例表。

CREATE TABLE audit_events (
    id bigint NOT NULL,
    author_id integer NOT NULL,
    entity_id integer NOT NULL,
    entity_ty
gitlab 使用postgresql数据库的一些说明 # cd /var/opt/gitlab/postgresql/data # vim pg_hba.conf         host    all         all  192.168.1.0/24  trust    添加这行,192.168.1.0/24这个段的ip地址不需要密码可以连接 # vim postgresql.conf     listen_address 阅读详情

相关推荐

GitLab: 如何使用外部提供的PostgreSQL数据库

缺省的情况下GitLab的官方镜像中提供了一个PostgreSQL,如果希望把此数据库放在GitLab的容器之外的话需要怎么做呢?这篇文章结合示例进行说明具体的做法。

知行合一 止于至善 6032

腾讯大佬总结的170道 python面试题

简述基于 TCP 协议的套接字通信流程。19.面向对象中`__new__` 和 `__init__` 区别。86. 解释 Python 中的`//`,`%`和`**`运算符。45.isinstance 的作用以及与 type()的区别。3. 简述下 Python 中的字符串、列表、元组和字典。143. 如何高效的找到 redis 中的某个 KEY。140. 如何保证 redis 中的数据都是热点数据。147. redis 中的 watch 的命令的作用。108. 简述 进程、线程、协程的区别以及应用场景。

AudiA6LV6的博客 491

DL-FWI基础入门培训视频学习1、2

DL-FWI基础知识

shengMio的博客 711

MiniMax H3本地部署实战:ComfyUI整合包安装与提速插件验证指南

在AIGC工具链快速演进的当下,本地部署内容生成模型成为许多创作者和开发者的关注焦点。本地部署意味着数据不出本机、可按需定制工作流,还能规避云端排队与外部依赖,其核心价值在于为内容生产提供可控、私密且可编程的生成环境。ComfyUI作为模块化节点式AI绘画工具,凭借灵活的工作流编排和API接口能力,成为承载这类模型的热门平台。MiniMax H3作为支持文本、参考图等多种输入的内容生成模型,与ComfyUI结合后,既适合个人进行概念验证,也能用于团队私有化流程搭建。实际落地过程中,中文整合包显著降低了环境配

weixin_29042035的博客 298

告别理论推导!用Matlab工具箱5步搞定相机标定(附张正友法原理白话解读)

本文详细介绍了如何使用Matlab工具箱在5步内完成相机标定,无需复杂理论推导。通过棋盘格拍摄和Matlab的Camera Calibrator工具箱,用户可以快速获取相机的内参和外参,显著提升3D视觉的准确性。文章还提供了张正友标定法的白话解读,适合初学者和工程师快速上手。

weixin_42548816的博客 415

Sigmastar平台WDR调试实战:从参数解析到鬼影消除的完整指南

本文提供了Sigmastar平台宽动态(WDR)技术的实战调试指南。针对逆光、运动场景下的核心痛点,系统性地解析了从多曝光采集、HDR融合到色调映射的完整管线,并重点阐述了如何通过调整曝光比、运动阈值与调整曲线等关键参数,有效消除运动鬼影、平衡暗部噪声与细节,最终实现清晰稳定的图像效果。

Jerry的专栏 930

cuMotion 入门教程(一)面向机器人学的GPU加速运动生成技术

NVIDIA cuMotion是一款高性能机器人运动生成库,专注于机械操作任务,利用GPU加速技术提升性能。开发者预览版支持运动学/逆运动学、碰撞感知路径规划、轨迹优化等功能,兼容任意自由度机器人。该库提供C++和Python接口,支持从URDF/XRDF文件加载机器人模型,包含世界建模、碰撞检测等工具。教程详细介绍了安装配置、机器人描述加载、运动学计算、世界建模、逆运动学求解以及轨迹优化等核心功能。cuMotion整合了Lula和cuRobo库的技术优势,将成为Isaac ROS的核心组件,适用于工业机器

2506_90492529的博客 2205

DeepSeek Harness 工程实践与高级特性:从测试到安全的完整指南

AI Agent 能执行命令、读写文件、自主决策,能力越强风险越大——删文件、泄密钥、死循环、竞态条件随时可能发生。本文是 DeepSeek Harness 系列第三篇,深入剖析其工程实践与高级特性:从单元测试到真实 API 冒烟测试的分层策略,拒绝 Mock 依赖、坚持"验证世界而非自我报告";从正交结果、规范化契约到 Dispose 静止的防御式编程铁律;以及跨平台多层进程沙箱、文件系统版本守卫、fail-closed 审批机制、模型编写的工作流引擎与上下文压缩等高级能力。

program哲学 209

Coze智能体开发:如何搭建一个生成长文本的工作流

扣子工作流提供了流程定制化的能力,我们可以把长文生成的流程拆分为多个步骤,例如先通过大模型节点生成大纲、再使用循环节点依次扩写各个段落,最后将各个段落组合起来,从而实现长文生成流程。此工作流可适用于学术写作、商业报告、小说创作等多种场景。

王国平的博客 1791

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

贝叶斯统计 [韦来生编]

贝叶斯(Bayes)统计是近几十年来迅速发展起来的数理统计的一个重要分支。贝叶斯方法与经典统计方法的主要不同之处是进行统计推断时除了利用样本信息外,还要利用参数的先验信息,因此可以提高统计推断或统计决策的效果。它在经济、金融、生物、医学、自然科学和社会科学等许多领域具有广泛的应用。贝叶斯方法的研究已渗透到了统计学的几乎所有领域。作者在给中国科学技术大学概率论与数理统计专业本科生开设的“数理统计”课程中有一章专门讲授“贝叶斯方法和统计决策理论”,近十年来也给中国科学技术大学概率统计专业研究生开设过几次“贝叶斯分析”课。本书是在对过去讲稿的内容作了适当的增减和调整的基础上完成的。  本书共分六章。第1章是绪论,介绍了贝叶斯统计的若干基本概念,同时对必要的数理统计的基础知识有重点地作了回顾。第二章介绍了确定先验分布的若干可供选择的方法。第三章介绍了几类常见统计模型参数的后验分布的主要结果和计算方法。第四章和第五章分别介绍了“贝叶斯统计推断”和“贝叶斯统计决策”的内容。第六章介绍了贝叶斯统计计算的若干方法,包括蒙特卡洛方法和马尔可夫链蒙特卡洛(MCMC)方法以及相关统计软件的简介。本书的每一章附右大量的例题和习题,书末附有常用的几个表格和部分习题解答供读者查用。  大约可在54学时内讲授本书的第1章至第六章的主要内容,教师可根据学时需要选讲本书第1章至第六章的部分内容。书中标“*”号的章节可略去不讲,留给读者作为阅读材料。第六章例题中的R代码和部分例题的数据文件等可从作者个人主页下载。  作者在编写本书的过程中参考了J.O.Berger教授的《统计决策论及贝叶斯分析》和茆诗松教授编写的《贝叶斯统计》等书中的一些内容,以及《贝叶斯分析》一书中由张伟平博士编写的有关贝叶斯统计计算的一些内容。在此表示衷心感谢。  本书编写准备过程中,中国科学技术大学统计与金融系的几个研究生帮助完成了本书部分中文的录入和排版,作者对他们的辛勤工作表示真诚的感谢。高等教育出版社为本书的出版给予了大力支持。在此一并致谢。

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

上一篇: 头疼管理 MySQL 数据库 Schema?开源工具大盘点!
下一篇: 分享一个基本的故障复盘报告模版
Bytebase
博客等级 码龄5年 1349粉丝 258原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值