RDBM最佳实践

RDBMS 可以做的事情比大多数人想象的要多得多:

1. 添加表通常比更改现有表更好
在大公司中尤其如此。对其他团队依赖的核心表进行更改是非常危险的,并且可能需要经过许多批准。这会大大降低团队的敏捷性。

取而代之的是,尝试添加一个完全归团队所有的新表。这有点像 "轻微服务";你可以在不破坏其他表的情况下破坏这个表,继续使用事务,并且不运行任何额外的基础设施。

(是的,这违反了数据库规范化原则,但在需要考虑性能的现实世界中,我们经常违反这些原则)

2.首先从索引的角度思考
每次编写查询时,都应首先考虑:"我应该使用哪个索引?如果没有可用的索引,就创建它(或者创建一个具有该索引的单独表,参见第 1 点)。在编写查询时,添加注释命名索引。

在将任何查询提交到代码库之前,请编写一个脚本,在本地开发数据库中填满 100k+ 行,然后在查询上运行 EXPLAIN。如果查询没有使用该索引,就不能提交。将此纳入自动化测试会更好,但很难做到。

3.考虑将非 COUNT(*) 聚合移出数据库。
我认为我的 RDBMS 是一个花哨的 hashtable,而不是一个关系引擎,因此我采用了像这样的快速模式。这通常意味着从数据库中获取成批的记录,并在应用代码中进行增量聚合。

(如果您有非常复杂和缓慢的聚合,很难或不可能转移到应用程序代码中,那么您最好使用 OLAP 存储器/数据仓库来代替)。

4.从 "节点 "表和 "边缘 "表的角度思考问题是有用的。
大多数人只使用 "节点 "表--每一行定义一个业务实体--并使用外键来建立关系。

外键让很多人感到困惑,无论何时,如果有人想添加新关系,都需要 ALTER TABLE(见第 1 点)。

相反,可以先创建一个 "边缘 "表,使用(source_id,destination_id)模式来建立关系。

这不仅具有第 1 点的所有优点,还能让您随着时间的推移更灵活地发展模式。您可以在边缘附加额外的字段和索引,并在将来将 1 对多的关系迁移为多对多的关系(这种情况经常发生)

5.通常每个表都需要 "创建日期 "和/或 "更新日期 "列。
我向你保证,总有一天,你会

  • 1) 想要过期的旧数据
  • 2) 需要在事件时间窗口中确定一组受影响的行,或
  • 3) 按照稳定的顺序遍历行以进行迁移

6.选择 ID 的结构方式超级重要。

  • 切勿使用自动递增。
  • 切勿使用用户提供的字符串,即使它们应该是唯一 ID。
  • 始终使用至少 64 位。

Snowflake ID 或 ULID (https://github.com/ulid/spec) 是不错的选择。

7.对查询进行注释,这样调试 prod 问题会更容易。
大多数大公司都有办法为每个 SQL 查询附加堆栈跟踪信息(行、源文件和 git 提交哈希值)。如果你的公司没有这种方法,至少也要添加一个包含团队名称的注释。

总结
以上很多都是不显而易见的,很多伟大的工程师也会不同意其中的一些或全部。当然,在某些情况下,你也不应该遵循它们。具体情况具体分析!