AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 6468
Accepted
Jon of All Trades
Jon of All Trades
Asked: 2011-10-04 18:09:27 +0800 CST2011-10-04 18:09:27 +0800 CST 2011-10-04 18:09:27 +0800 CST

使用广泛的 PK 与单独的合成密钥和 UQ 之间的性能考虑因素是什么?

  • 772

我有几个表,其中的记录可以用几个广泛的业务领域进行唯一标识。过去,我将这些字段用作 PK,考虑到这些好处:

  • 简单; 没有无关的字段,只有一个索引
  • 集群允许快速合并连接和基于范围的过滤器

但是,我听说过创建合成IDENTITY INTPK 的案例,而不是使用单独的UNIQUE约束来强制执行业务密钥。优点是窄 PK 使得二级索引小得多。

如果一个表除了 PK 之外没有其他索引,我看不出有任何理由支持第二种方法,尽管在一个大表中最好假设将来可能需要索引,因此支持窄合成 PK . 我是否遗漏了任何注意事项?

顺便说一下,我并不是反对在数据仓库中使用合成密钥,我只是对何时使用单个宽泛 PK 以及何时使用窄 PK 加上宽泛 UK 感兴趣。

database-design primary-key
  • 4 4 个回答
  • 845 Views

4 个回答

  • Voted
  1. Best Answer
    gbn
    2011-10-04T20:49:39+08:002011-10-04T20:49:39+08:00

    使用自然键作为聚簇索引没有明显的缺点

    • 没有非聚集索引
    • 没有引用此表的外键(它是父行)

    缺点是会增加页面拆分,因为数据插入将分布在整个数据中,而不是在末尾。

    如果您确实有 FK 或 NC 索引,则使用窄的、数字的、递增的聚集索引具有优势。您只需为每个 NC 或 FK 条目重复几个字节的数据,而不是 while 业务/自然键。

    至于为什么,请阅读谷歌的 5 篇文章

    注意我避免使用“主键”。

    您可以在代理键上使用聚集索引,但将 PK 保留在业务规则上,但作为非聚集索引。只要确保集群是唯一的,因为 SQL 会添加一个“uniquifier”来实现它。

    最后,在每个表上都有一个代理键但不是盲目地使用代理键可能是有意义的:许多表不需要代理键,或者父表中的复合键就足够了

    • 11
  2. Mike Sherrill 'Cat Recall'
    2011-10-05T17:00:28+08:002011-10-05T17:00:28+08:00

    尽管我冒着风险陈述显而易见的事实,但如果您需要通过 ID 号定位事物,则代理键(ID 号)上的索引很有用。用户不会去处理id号;他们将处理人类可读的文本。因此,您必须多次传递文本及其 ID 号,以便用户界面可以显示文本并对 ID 号进行操作。

    dbms 将使用那种索引来支持外键,如果你这样定义的话。

    有时可以通过使用 ID 号作为外键来提高性能,但这不是绝对的提高。在我们的 OLTP 系统上,在大约 130 个(我认为)代表性查询的测试套件中,使用自然键的外键优于使用 ID 号的外键。(因为重要信息通常包含在键中,所以使用自然键避免了很多连接。)中值加速是 85 倍(使用 id 号的连接花费 85 倍的时间返回行)。

    测试表明,在某些表达到数百万行之前,对 ID 号的连接不会比对我们数据库中自然键的读取执行得更快。行的宽度与此有很大关系——较宽的行意味着页面上适合的行数较少,因此您必须阅读更多页面才能获得“n”行。几乎我们所有的表都是 5NF;大多数桌子都很窄。

    当连接开始执行简单读取时,将关键表和索引放在固态磁盘上可能会使性能达到数亿行。

    • 4
  3. Catalin Adler
    2011-10-04T21:29:39+08:002011-10-04T21:29:39+08:00

    我有一个完整的 oltp 数据库,设计使用标识列进行聚类 + pk。它在插入/查找时工作得非常快,但我看到了一些问题:
    1. 索引填充选项无用,因为插入仅发生在索引的末尾
    2. 更多存储空间。我有几千万条记录的表,1个int本身就占空间。每个带有 pk 标识列的表都必须有另一个用于业务搜索的索引,因此需要更多的存储空间。
    3.可扩展性。这是最糟糕的问题。因为每次插入都会到达索引的末尾,所以每次插入只会强调索引的末尾(分配、用于写入的 io 等)。通过使用业务键作为集群键,您可以在索引上均匀分布插入。这意味着您刚刚消除了一个大热点。您可以轻松地使用更多文件作为索引,每个文件都在一个单独的驱动器上,每个驱动器单独工作。

    我开始将我的表从标识列更改为自然键(对于聚类和 pk 可能是分开的)。现在感觉好多了。

    我会建议以下内容(至少对于 oltp 数据库):
    1. 以正确的顺序将正确的列用作聚类键,以优化最频繁的查询
    2. 使用 pk 对您的表有意义的正确列

    如果聚簇键不简单并且包含字符(char[]、varchar、nvarchar),我认为答案是“视情况而定”,您应该单独分析每种情况。

    我坚持以下原则:优化最常见的查询,同时尽量减少最坏的情况。

    我差点忘了一个例子。我有一些引用自己​​的表。如果该表的主键有标识列,则插入一行可能需要更新,并且一次插入多行即使不是不可能也可能很困难(这取决于表设计)。

    • 3
  4. nvogel
    2011-10-14T20:45:47+08:002011-10-14T20:45:47+08:00

    从性能的角度来看,选择哪个键是“主”键根本没有区别。使用 PRIMARY KEY 和 UNIQUE 约束来强制执行密钥之间没有区别。

    性能取决于索引和其他存储选项的选择和类型,以及键在查询和代码中的使用方式。

    • 2

相关问题

  • 使用 UUID 或 GUID 作为主键有什么缺点?

  • 存储计算值或根据要求重新计算它们更好吗?[复制]

  • 存储与计算聚合值

  • 字符与整数主键

  • 在数据仓库中实现多对多关系有哪些方法?

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    您如何显示在 Oracle 数据库上执行的 SQL?

    • 2 个回答
  • Marko Smith

    如何选择每组的第一行?

    • 6 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    我可以查看在 SQL Server 数据库上运行的历史查询吗?

    • 6 个回答
  • Marko Smith

    如何在 PostgreSQL 中使用 currval() 来获取最后插入的 id?

    • 10 个回答
  • Marko Smith

    如何在 Mac OS X 上运行 psql?

    • 11 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Marko Smith

    将数组参数传递给存储过程

    • 12 个回答
  • Martin Hope
    Manuel Leduc PostgreSQL 多列唯一约束和 NULL 值 2011-12-28 01:10:21 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Stuart Blackler 什么时候应该将主键声明为非聚集的? 2011-11-11 13:31:59 +0800 CST
  • Martin Hope
    pedrosanta 使用 psql 列出数据库权限 2011-08-04 11:01:21 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST
  • Martin Hope
    BrunoLM Guid vs INT - 哪个更好作为主键? 2011-01-05 23:46:34 +0800 CST
  • Martin Hope
    bernd_k 什么时候应该使用唯一约束而不是唯一索引? 2011-01-05 02:32:27 +0800 CST
  • Martin Hope
    Patrick 如何优化大型数据库的 mysqldump? 2011-01-04 13:13:48 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve