更好的 PK 用于未来安全的数据密集型数据库
Better PK for future safe data intensive Databases
我们在为新的数据密集型项目设计主键时遇到了技术难题。
请解释一下哪种PK设计更适合我们的数据密集型数据库。
- 数据库是数据密集型和持久化的。
- 每秒至少有 3000 个用户访问它。
请从技术上告诉我们哪种类型的 PK 更适合我们的数据库,并且这些表将来更改的可能性较小。
1.INT/BIGINT 自动递增列作为 PK
2.Composite 键。
3.Unique varchar PK.
我会选择选项 1,使用 BIGINT 自动增量列作为 PK。原因很简单,每次写都会写到当前页的末尾,意味着插入新行非常快。如果你使用组合键,那么你需要一个顺序,除非你是按照组合键的顺序插入,否则你需要分页插入,例如想象一下 table:
A | B | C
---+---+---
1 | 1 | 4
1 | 4 | 5
5 | 1 | 2
其中主键是(A,B,C)上的复合键,假设我要插入(2,2,2),则需要插入如下:
A | B | C
---+---+---
1 | 1 | 4
1 | 4 | 5
2 | 2 | 2 <----
5 | 1 | 2
以便聚集键保持其顺序。如果您已经插入的页面也已经满了,那么 MySQL 将需要拆分页面,将一些数据移动到新页面以为新数据腾出空间。这些页面拆分非常昂贵,因此除非您知道要插入顺序数据,否则使用自动增量列作为聚类键意味着除非您弄乱增量,否则您永远不必拆分页面。
您仍然可以向作为主键的列添加唯一索引以保持完整性,您仍然会遇到与索引拆分相同的问题,但由于索引会比聚集索引窄拆分的频率会降低,因为页面上将容纳更多数据。
或多或少相同的论点适用于唯一的 varchar 列,除非你有某种过程确保 varchar 是连续的,但生成连续的 varchar 比自动增量列的成本更高,我看不出直接优势。
这个问题不好回答。
首先,使用组合键作为主键是最直接的方法。当数据库结构发生变化时,ID 会派上用场。
假设您在不同国家/地区销售不同尺寸的产品。主键是粗体。
- 产品(product_no,名称,supplier_no,...)
- product_size (product_no, 大小, ean, 度量, ...)
- product_country (product_no, country_isocode, translated_name, ...)
- product_size_国家(product_no,尺寸,country_isocode,增值税,...)
写入数据非常容易,因为您正在处理自然键,这就是用户使用的。 dbms保证数据一致性。
现在与技术 ID 相同:
- 产品(product_id、product_no、名称、supplier_no、...)
- product_size (product_size_id, size, product_id, ean, measures, ...)
- product_country (product_country_id, product_id, country_id, translated_name, ...)
- product_size_country (product_size_country_id, product_size_id, country_id, 增值税, . ..)
现在插入数据时,获取 ID 是一个额外的步骤。而且您仍然必须确保 product_no 是唯一的。所以 product_id 上的唯一约束并没有取代 product_no 上的约束,而是增加了它。 product_size、product_country 和 product_size_country 也一样。此外 product_size_country 现在可能 link 到 product_country 和 product_size_country 不同的产品。 dbms 不能再保证数据的一致性了。
但是,当必须更改数据库结构时,自然键有其弱点。假设在数据库中引入了一家新公司,并且每个公司的产品编号都是唯一的。使用基于 ID 的数据库,您只需将公司 ID 添加到产品 table 即可。在基于自然键的数据库中,您必须将公司添加到所有主键中。更多的工作。 (但是,必须多久对数据库进行一次此类更改。在许多数据库中永远不会。)
还有什么要考虑的?当数据库变大时,您可能希望对 tables 进行分区。使用自然键,您可以按上述公司划分您的 table,假设您通常想要 select 来自一家公司或另一家公司的数据。有了 ID,您会根据什么来划分 table 以增强访问权限?
好吧,这两个概念当然各有利弊。至于创建唯一 varchar 的第三个选项,我认为这比使用整数 ID 没有任何好处。
我们在为新的数据密集型项目设计主键时遇到了技术难题。
请解释一下哪种PK设计更适合我们的数据密集型数据库。
- 数据库是数据密集型和持久化的。
- 每秒至少有 3000 个用户访问它。
请从技术上告诉我们哪种类型的 PK 更适合我们的数据库,并且这些表将来更改的可能性较小。
1.INT/BIGINT 自动递增列作为 PK
2.Composite 键。
3.Unique varchar PK.
我会选择选项 1,使用 BIGINT 自动增量列作为 PK。原因很简单,每次写都会写到当前页的末尾,意味着插入新行非常快。如果你使用组合键,那么你需要一个顺序,除非你是按照组合键的顺序插入,否则你需要分页插入,例如想象一下 table:
A | B | C
---+---+---
1 | 1 | 4
1 | 4 | 5
5 | 1 | 2
其中主键是(A,B,C)上的复合键,假设我要插入(2,2,2),则需要插入如下:
A | B | C
---+---+---
1 | 1 | 4
1 | 4 | 5
2 | 2 | 2 <----
5 | 1 | 2
以便聚集键保持其顺序。如果您已经插入的页面也已经满了,那么 MySQL 将需要拆分页面,将一些数据移动到新页面以为新数据腾出空间。这些页面拆分非常昂贵,因此除非您知道要插入顺序数据,否则使用自动增量列作为聚类键意味着除非您弄乱增量,否则您永远不必拆分页面。
您仍然可以向作为主键的列添加唯一索引以保持完整性,您仍然会遇到与索引拆分相同的问题,但由于索引会比聚集索引窄拆分的频率会降低,因为页面上将容纳更多数据。
或多或少相同的论点适用于唯一的 varchar 列,除非你有某种过程确保 varchar 是连续的,但生成连续的 varchar 比自动增量列的成本更高,我看不出直接优势。
这个问题不好回答。
首先,使用组合键作为主键是最直接的方法。当数据库结构发生变化时,ID 会派上用场。
假设您在不同国家/地区销售不同尺寸的产品。主键是粗体。
- 产品(product_no,名称,supplier_no,...)
- product_size (product_no, 大小, ean, 度量, ...)
- product_country (product_no, country_isocode, translated_name, ...)
- product_size_国家(product_no,尺寸,country_isocode,增值税,...)
写入数据非常容易,因为您正在处理自然键,这就是用户使用的。 dbms保证数据一致性。
现在与技术 ID 相同:
- 产品(product_id、product_no、名称、supplier_no、...)
- product_size (product_size_id, size, product_id, ean, measures, ...)
- product_country (product_country_id, product_id, country_id, translated_name, ...)
- product_size_country (product_size_country_id, product_size_id, country_id, 增值税, . ..)
现在插入数据时,获取 ID 是一个额外的步骤。而且您仍然必须确保 product_no 是唯一的。所以 product_id 上的唯一约束并没有取代 product_no 上的约束,而是增加了它。 product_size、product_country 和 product_size_country 也一样。此外 product_size_country 现在可能 link 到 product_country 和 product_size_country 不同的产品。 dbms 不能再保证数据的一致性了。
但是,当必须更改数据库结构时,自然键有其弱点。假设在数据库中引入了一家新公司,并且每个公司的产品编号都是唯一的。使用基于 ID 的数据库,您只需将公司 ID 添加到产品 table 即可。在基于自然键的数据库中,您必须将公司添加到所有主键中。更多的工作。 (但是,必须多久对数据库进行一次此类更改。在许多数据库中永远不会。)
还有什么要考虑的?当数据库变大时,您可能希望对 tables 进行分区。使用自然键,您可以按上述公司划分您的 table,假设您通常想要 select 来自一家公司或另一家公司的数据。有了 ID,您会根据什么来划分 table 以增强访问权限?
好吧,这两个概念当然各有利弊。至于创建唯一 varchar 的第三个选项,我认为这比使用整数 ID 没有任何好处。