Help us learn about your current experience with the documentation. Take the survey.

大表限制

GitLab 对大型数据库表的架构变更实施了一些限制,以提高 GitLab 及其客户的管理能力。受这些限制的表列表在 rubocop/rubocop-migrations.yml 中定义。

表大小限制

以下限制适用于 GitLab.com 上的表架构变更:

限制 操作后的最大大小(包括索引和列大小)
不能添加索引 50 GB
不能添加带外键的列 50 GB
不能添加新列 100 GB

这些限制符合我们的目标,即保持所有表在 100 GB 以下,以改善稳定性和性能

例外情况

这些大小限制的例外情况仅应在以下情况下授予:

  • 将表的列从 int4 迁移到 int8
  • 添加分片键以支持 cells
  • 修改表以协助分区或数据保留工作
  • 替换现有索引以提供更好的查询性能

申请例外

要申请这些限制的例外:

  1. 使用数据库团队任务模板创建新问题
  2. 选择 schema_change_exception 模板
  3. 提供详细的理由,说明为什么您的情况需要例外
  4. 在继续之前等待数据库团队的审查和批准
  5. 在为您的迁移禁用 cop 时链接批准的问题

减少表大小的技术

在申请例外之前,考虑这些管理表大小的方法:

数据归档

  • 将旧的不常访问的数据移动到归档表
  • 实现归档工作程序以实现数据迁移自动化
  • 考虑使用按日期分区来促进归档,参见日期范围分区

数据保留

  • 实施保留策略以删除旧数据
  • 配置自动清理作业以清理过期数据,参见删除旧的 pipelines

表分区

  • 按日期、ID 范围或其他标准对大表进行分区
  • 根据访问模式考虑范围列表分区

列优化

  • 使用适当的数据类型(例如,尽可能使用 smallint 而不是 integer
  • 删除未使用或冗余的索引
  • 考虑使用 NULL 而不是空字符串或零
  • 使用 text 而不是 varchar避免存储开销

规范化

  • 将大表拆分为相关的小表
  • 将很少使用的列移动到单独的表
  • 使用连接表处理多对多关系
  • 考虑对宽表进行垂直分区

外部存储

  • 将大型文本或二进制数据移动到对象存储
  • 仅在数据库中存储元数据
  • 使用Elasticsearch处理搜索特定的数据
  • 考虑使用 Redis 处理临时或缓存数据

表修改的替代方案

处理大表时考虑这些替代方案:

  1. 为新列创建一个单独的表,特别是当该列并非所有行都存在时。新表通过外键引用原始表。
  2. 与全局搜索团队合作,将您的数据添加到 Elasticsearch 以增强过滤/搜索功能。
  3. 简化过滤/排序选项(例如,使用 id 而不是 created_at 进行排序)。

表大小限制的好处

表大小限制提供了几个优势:

  • 启用具有不同频率的独立清理操作
  • 为列更新生成更少的预写日志(WAL)数据
  • 防止在行更新期间不必要的数据复制

有关数据模型权衡的更多信息,请参阅数据库文档

使用 has_one 关系

当表对于新列来说变得太大时,创建一个具有 has_one 关系的新表。例如,在合并请求 !170371中,我们在单独的表中跟踪问题的总权重计数。

这种方法的好处:

  1. 保持主表更窄,减少来自 PostgreSQL 的数据负载
  2. 为特定查询创建高效的窄表
  3. 根据需要允许选择性填充新表

这种方法在以下情况下特别有效:

  • 新列适用于主表的子集
  • 只有特定查询需要新数据

缺点

  1. 更多的表可能导致更多的"连接",这将使查询复杂化
  2. 具有多个连接的查询可能最终难以优化

相关链接