mysql - 带有索引和约束的 Postgres UUID

标签 mysql postgresql

在 UUID 主键字段上拥有索引和唯一约束有什么好处?看来,如果我有 25M 记录并且必须插入新记录,则必须搜索所有 25M 记录并检查它们是否具有相同的 UUID(带或不带索引)。查找该记录也很麻烦,因为 uuid 无法排序。我错过了什么吗?

最佳答案

是的。

  1. UUID 值可以排序。它们可能不是按照您认为特别理想的顺序排序的。但 UUID 是数据值。它们可以进行比较(它们是否相等、是否小于另一个),因此可以对它们进行排序。

  2. 声明 PRIMARY KEY 可有效创建 UNIQUE 索引。对于某些存储引擎(例如 InnoDB),主键是表的簇键。对于其他存储引擎(例如 MyISAM),表存储为堆,并且 PRIMARY KEY 本质上与声明 NOT NULL 约束并添加 UNIQUE INDEX 相同。

  3. 是的,当向表中插入一行时,存储引擎必须确保不违反 PRIMARY KEY 或 UNIQUE KEY 约束...正在插入的新行上的值不会与已经存在的值重复已存储。

这(理论上)相当于检查所有 25M 行。但由于有可用的索引结构,存储引擎不需要检查所有单独的行。它使用索引。

由于索引是“按顺序”存储的,因此存在大量包含不需要检查的行的 block 。不需要检查它们,因为具有键列的特定值的行不可能存储在这些 block 中。存储引擎非常有效地识别存在或可能存在具有“重复”键值的行的 block 。

<小时/>

跟进

上面的答案主要指的是MySQL(问题中的标签之一)。就 PostgreSQL 而言,我相信这些观点是有效的。

就使用 UUID 值作为表的主键而言,与其他一些选择相比,可能会存在一些性能缺陷。两个主要问题:存储 UUID 所需的空间,以及 UUID 值不是按顺序生成/插入的。

一个UUID是128位,也就是16个字节。但它通常会转换为 36 个字符的“人类可读形式 (?)”。将 UUID 存储为 36 个字符比简单整数占用更多空间。当 CHAR(36) 用作主键时,它不仅存储在主键索引中,而且还作为“行指针”存储在所有辅助索引中。这意味着每个 block 的键更少,这反过来意味着索引中的 block 更多。

另一个问题是,新值不仅插入到索引的后面,而且插入到整个索引中,导致 block split 和碎片。我们不必过度担心所有这些,因为数据库会为我们处理它。但使用 UUID 作为主键可能会导致明显的“性能降低”(与使用升序整数值相比),至少在测试实验室中是这样。

<小时/>

就添加以 PRIMARY KEY 作为前导列的二级索引“有什么好处”而言。一般来说,没有什么好处。

(我不会排除拥有这样的索引可能有益的极端情况。我希望这些极端情况涉及索引组织表中非常长的行,以及一些特定的 SQL 语句,这些语句可能会导致高效使用二级索引。但这种性能优势会带来一定的代价:额外的 block (内存和磁盘 I/O)以及维护二级索引的额外工作。)

关于mysql - 带有索引和约束的 Postgres UUID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36413895/

相关文章:

mysql - IS NOT NULL 查询应该使用什么索引

python - 使用 AWS Elastic Beanstalk 中的requirements.txt 文件安装flask-mysql 应用程序的依赖项时遇到错误

使用 SQLAlchemy + postgresql 更新 Python 数据库

java - Hibernate + PostgreSQL + 网络地址类型(inet、cdir)

ruby-on-rails - 实时博客应用程序的数据库选择

php - 使用 codeigniter 和 postgresql foreach() 将不同表中的 2 个值相乘

Docker 中的 PostgreSQL - pg_hba.conf 允许从主机访问容器

尽管以相反的顺序关闭资源,Java 代码仍未关闭 MySQL 连接

mysql - 如何从一个表中选择 CSV 行并根据键插入到另一个表中?

php - 从表单字段在 php mysql 中每周报告