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
- 修改表以协助分区或数据保留工作
- 替换现有索引以提供更好的查询性能
申请例外
要申请这些限制的例外:
- 使用数据库团队任务模板创建新问题
- 选择
schema_change_exception模板 - 提供详细的理由,说明为什么您的情况需要例外
- 在继续之前等待数据库团队的审查和批准
- 在为您的迁移禁用 cop 时链接批准的问题
减少表大小的技术
在申请例外之前,考虑这些管理表大小的方法:
数据归档
- 将旧的不常访问的数据移动到归档表
- 实现归档工作程序以实现数据迁移自动化
- 考虑使用按日期分区来促进归档,参见日期范围分区
数据保留
- 实施保留策略以删除旧数据
- 配置自动清理作业以清理过期数据,参见删除旧的 pipelines
表分区
列优化
- 使用适当的数据类型(例如,尽可能使用
smallint而不是integer) - 删除未使用或冗余的索引
- 考虑使用
NULL而不是空字符串或零 - 使用
text而不是varchar以避免存储开销
规范化
外部存储
- 将大型文本或二进制数据移动到对象存储
- 仅在数据库中存储元数据
- 使用Elasticsearch处理搜索特定的数据
- 考虑使用 Redis 处理临时或缓存数据
表修改的替代方案
处理大表时考虑这些替代方案:
- 为新列创建一个单独的表,特别是当该列并非所有行都存在时。新表通过外键引用原始表。
- 与全局搜索团队合作,将您的数据添加到 Elasticsearch 以增强过滤/搜索功能。
- 简化过滤/排序选项(例如,使用
id而不是created_at进行排序)。
表大小限制的好处
表大小限制提供了几个优势:
- 启用具有不同频率的独立清理操作
- 为列更新生成更少的预写日志(WAL)数据
- 防止在行更新期间不必要的数据复制
有关数据模型权衡的更多信息,请参阅数据库文档。
使用 has_one 关系
当表对于新列来说变得太大时,创建一个具有 has_one 关系的新表。例如,在合并请求 !170371中,我们在单独的表中跟踪问题的总权重计数。
这种方法的好处:
- 保持主表更窄,减少来自 PostgreSQL 的数据负载
- 为特定查询创建高效的窄表
- 根据需要允许选择性填充新表
这种方法在以下情况下特别有效:
- 新列适用于主表的子集
- 只有特定查询需要新数据
缺点
- 更多的表可能导致更多的"连接",这将使查询复杂化
- 具有多个连接的查询可能最终难以优化