- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
我想知道在对具有定义为 UNIQUE 的任何列的表执行 INSERT 之前是否运行了隐式 SELECT。我在 INSERT 的文档中找不到任何关于此的信息。
我问了一些似乎没有人能够回答的其他问题——也许是因为我没有正确解释自己——与上述问题有关。
如果我理解正确,那么我认为以下内容是正确的:
案例 1:
您有一个包含 10 亿行的表。每行都有一个唯一的 UUID 列。如果您执行插入,服务器必须执行某种隐式 SELECT COUNT(*) FROM table WHERE UUID = [new uuid]
并确定计数是 0 还是 1。正确吗?
案例 2:
您有一个包含 10 亿行的表。每行都有一个由 DATE 和 UUID 组成的复合唯一键。如果您执行插入,服务器必须执行某种隐式 SELECT COUNT(*) FROM table WHERE DATE = [date] AND UUID = [new uuid]
并检查计数是 0 还是 1。是吗?
我使用隐式这个词是因为在某个时刻,在过程中的某个地方,服务器必须检查该值。如果不是,它将要求物理定律规定不能存在两个相同的行 - 据我所知,当涉及到以二进制形式写下的数字的唯一性时,物理不会发挥重要作用计算机中的磁盘。
让我们假设您的 10 亿行在 2,000 个不同的日期中按顺序均匀分布。这是否意味着案例 2 会更快地执行插入,因为它可以查找分割成日期的 UUID?如果不是,那么将案例 1 用于插入速度会更好 - 在这种情况下,为什么?
这个问题是理论上的,所以在这种情况下不要考虑常规 SELECT 性能。主键不会是 UUID+DATE 索引。
作为对评论的回应:在我的案例中,UUID 仅用于避免由于连接不良而导致重复条目的目的。由于您不能为不同的日期创建两次相同的条目(在逻辑上它没有成为新条目),因此 UUID 不需要全局唯一 - 它只需要每个日期唯一。这就是为什么我可以允许它成为组合键的一部分。
最佳答案
前面的回答有一些缺陷和误解;我不会指出它们,而是从头开始。
仅指 InnoDB...
一个 INDEX(包括 UNIQUE 和 PRIMARY KEY)是一个 BTree。 BTrees 非常有效,可以根据 BTree 排序的键定位一行。 (按键顺序扫描也很有效。)MySQL 中典型 BTree 的“扇出”大约为 100。因此,对于一百万行,BTree 大约有 3 级深(log100(million) );对于一万亿行,它只有两倍深(大约)。因此,即使没有缓存任何内容,只需点击 3 次磁盘即可在百万行索引中找到一个特定行。
我在这里对“索引”与“表”感到松散,因为它们本质上是相同的(至少在 InnoDB 中)。两者都是 BTrees。不同之处在于叶节点中的内容:表 BTree 的叶节点具有所有列。 (我忽略了 InnoDB 中 TEXT/BLOB 的块外存储。)一个 INDEX(除了 PRIMARY KEY)在叶节点中有一个 PRIMARY KEY 的副本。这就是辅助键可以从 INDEX BTree 获取到行的其余列的方式,以及 InnoDB 不必存储所有列的多个副本的方式。
PRIMARY KEY 与数据“聚集”在一起。即一个 BTree 包含所有行的所有列,并且它根据 PRIMARY KEY 规范进行排序。
通过 PRIMARY KEY 定位记录是一种 BTree 搜索。通过 SECONDARY KEY 定位记录是两次 BTree 搜索,一次在次要 INDEX 的 BTree 中为您提供 PRIMARY KEY;然后第二个钻取数据/PK BTree。
PRIMARY KEY(UUID)... 由于 UUID 非常随机,您插入的“下”行将位于“随机”位置。如果表比buffer_pool中缓存的大很多,那么新行需要进入的块很可能不会被缓存。这导致磁盘命中将块拉入缓存(缓冲池),并最终导致另一个磁盘命中将其写回磁盘。
由于 PRIMARY KEY 是 UNIQUE KEY,因此同时发生了其他事情(无 SELECT COUNT(*) 等)。在获取块之后和决定是否给出“重复键”错误或存储行之前,检查 UNIQUEness。另外,如果块是“满的”,那么块将需要“拆分”以便为新行腾出空间。
INDEX(UUID) 或 UNIQUE(UUID)... 该索引有一个 BTree。在 INSERT 上,一些随机定位的块需要被获取、修改、可能拆分并写回磁盘,非常类似于上面的 PK 讨论。如果您有 UNIQUE(UUID),还会检查 UNIQUEness 和可能的错误消息。在任何一种情况下,现在和/或以后都有磁盘 I/O。
AUTO_INCREMENT PK... 如果 PRIMARY KEY 是 auto_increment,则新记录将添加到数据 BTree 中的“最后一个”块。当它变满时(每 100 条左右的记录),(逻辑上)会进行块拆分并将旧块刷新到磁盘。 (实际上,I/O 可能会延迟并在后台完成。)
PRIMARY KEY(id) + UNIQUE(UUID) ... 两个 BTree。在 INSERT 上,两者都有事件。这可能比简单的 PRIMARY KEY(UUID) 更糟糕。把上面的磁盘命中加起来看看我的意思。
“磁盘命中”是大表中的杀手,尤其是 UUID。 “计算磁盘命中数”以了解性能,尤其是在比较两种可能的技术时。
现在为您的秘方... PRIMARY KEY(date, UUID)... 您允许相同的 UUID 在两个不同的日子出现。这可以帮助!回到 PK 的工作原理和检查 UNIQUEness ... 在插入记录时检查“复合”索引(日期,UUID)的唯一性。记录按日期+UUID 排序,因此今天的所有记录都聚集在一起。如果(这可能是一个很大的 IF)一天的数据适合缓冲池(但整个表不适合),那么这就是每天早上发生的事情......插入突然将新记录添加到“结束”由于新的“日期”表。这些插入是在新日期内随机发生的。 buffer_pool 中的块被推送到磁盘,为新块腾出空间。但是,很好,您看到的是流畅、快速的 INSERT。这与您在 PRIMARY KEY(UUID) 中看到的不同,在检查 UNIQUEness 之前,许多行必须等待磁盘读取。今天的所有块都保持缓存状态,您不必等待 I/O。
但是,如果您变得太大以至于无法在缓冲池中容纳一天的数据,事情就会开始放缓,首先是在一天结束时,然后随着 INSERT 频率的增加,它会越来越早地蔓延。
顺便说一下,PARTITION BY RANGE(date) 和 PRIMARY KEY(uuid, date) 有一些相似的特性。 (是的,我故意翻转了 PK 列。)
关于mysql - MySQL 如何确定 INSERT 是否唯一?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28084901/
目前我正在构建相当大的网络系统,我需要强大的 SQL 数据库解决方案。我选择 Mysql 而不是 Postgres,因为一些任务需要只读(MyISAM 引擎)而其他任务需要大量写入(InnoDB)。
我在 mysql 中使用如下命令。当它显示表格数据时,它被格式化为一个非常干净的表格,间距均匀且 |作为列分隔符。 SELECT * FROM TABLE_NAME; 当我从 CLI 运行命令时,如下
我知道这个问题之前已经被问过好几次了,我已经解决了很多问题,但到目前为止没有任何效果。 MySQL 试图将自身安装到的目录 (usr/local/mysql) 肯定有问题。关于我的错误的奇怪之处在于我
以下是我的 SQL 数据结构,我正在尝试如下两个查询: Select Wrk_ID, Wrk_LastName, Skill_Desc from Worker, Skill where
我们有一个本地 mysql 服务器(不在公共(public)域上),并希望将该服务器复制到我们拥有的 google 云 sql 实例。我的问题是:1.这可能吗?2.我们的本地服务器只能在本地网络上访问
我有一个表(test_table),其中一些字段值(例如字段 A、B 和 C)是从外部应用程序插入的,还有一个字段(字段 D),我想从现有表(store_table)插入其值,但在插入前者(A、B 和
我想创建一个 AWS RDS 实例,然后使用 terraform 管理数据库用户。因此,首先,我创建了一个 RDS 实例,然后使用创建的 RDS 实例初始化 mysql 提供程序,以进一步将其用于用户
当用户在我的网站上注册时,他们会在我的一个数据库中创建自己的表格。该表存储用户发布的所有帖子。我还想做的是也为他们生成自己的 MySql 用户——该用户仅有权从他们的表中读取、写入和删除。 创建它应该
我有一个关于 ColdFusion 和 Mysql 的问题。我有两个表:PRODUCT 和 PRODUCT_CAT。我想列出包含一些标记为:IS_EXTRANET=1 的特殊产品的类别。所以我写了这个
我想获取 recipes_id 列的值,以获取包含 ingredient_id 的 2,17 和 26 条目的值。 假设 ingredient_id 2 丢失则不获取记录。 我已经尝试过 IN 运算符
在 Ubuntu 中,我通常安装两者,但 MySQL 的客户端和服务器之间有什么区别。 作为奖励,当一个新语句提到它需要 MySQL 5.x 时,它是指客户端、服务器还是两者兼而有之。例如这个链接ht
我重新访问了我的数据库并注意到我有一些 INT 类型的主键。 这还不够独特,所以我想我会有一个指导。 我来自微软 sql 背景,在 ssms 中你可以 选择类型为“uniqeidentifier”并自
我的系统上有 MySQL,我正在尝试确定它是 Oracle MySQL 还是 MySQL。 Oracle MySQL 有区别吗: http://www.oracle.com/us/products/m
我是在生产 MySQL 中运行的应用程序的新维护者。之前的维护者已经离开,留下的文档很少,而且联系不上了。 我面临的问题是执行以下请求大约需要 10 秒: SELECT COUNT(*) FROM `
我有两个位于不同机器上的 MySQL 数据库。我想自动将数据从一台服务器传输到另一台服务器。比方说,我希望每天早上 4:00 进行数据传输。 可以吗?是否有任何 MySQL 内置功能可以让我们做到这一
有什么方法可以使用 jdbc 查询位于 mysql 根目录之外的目录中的 mysql 表,还是必须将它们移动到 mysql 根目录内的数据库文件夹中?我在 Google 上搜索时没有找到任何东西。 最
我在 mysql 数据库中有两个表。成员和 ClassNumbers。两个表都有一个付费年份字段,都有一个代码字段。我想用代码数字表中的值更新成员表中的付费年份,其中成员中的代码与 ClassNumb
情况:我有 2 台服务器,其中一台当前托管一个实时 WordPress 站点,我希望能够将该站点转移到另一台服务器,以防第一台服务器出现故障。传输源文件很容易;传输数据库是我需要弄清楚如何做的。两台服
Phpmyadmin 有一个功能是“复制数据库到”..有没有mysql查询来写这个函数?类似于将 db A 复制到新的 db B。 最佳答案 首先创建复制数据库: CREATE DATABASE du
我有一个使用 mySQL 作为后端的库存软件。我已经在我的计算机上对其进行了测试,并且运行良好。 当我在计算机上安装我的软件时,我必须执行以下步骤: 安装 mySQL 服务器 将用户名指定为“root
我是一名优秀的程序员,十分优秀!