- 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/
我正在使用 Selenium Web 驱动程序 3.0,并且想要从打开的两个对话框(一个在后台,第二个在前台)的 Activity 对话框中单击“确定”按钮。如何从 html 下面的父 div 单击前
actions: [ FlatButton( onPressed: () {
我有一个问题有点超出我的范围(我真的很高兴我是 Beta)涉及重复项(所以 GROUP BY, HAVING, COUNT),通过将解决方案保留在 SQLite 附带的标准函数中而变得更加复杂。我正在
使用DBI是否可以确定SELECT语句的已执行语句句柄是否返回任何行而不从中获取行? IE。就像是: use DBI; ... my $sth = $dbh->prepare("SELECT ..."
是否可以为“确定”和“关闭”按钮指定回调函数? 如果是JQuery Modal,则可以在初始化时使用按钮字典指定回调函数。 Semantic-ui模态是否提供类似的功能?按下确定后,我该如何寻求其他逻
我想阅读警报中的消息。 示例:如果警报显示“错误的电子邮件地址”。怎么读呢?意味着我想将该消息存储在字符串中。 如何在“警报”中单击“确定”...?? 如何使用 Selenium 来做到这一点? 最佳
我有一个删除按钮: 我试图首先查明是否已选择一个网站,如果已选择一个网站,我需要确定是否已选择一个或多个列表项,如果是,则继续删除这些项目。 我的 if 语句不断返回“您必须首先选择您的列表”,即使它
部分出于好奇——我们想知道在我们的应用程序中发生了什么——部分是因为我们需要在我们的代码中找到一些潜在的问题,我喜欢在我们的网络应用程序运行时跟踪一些一般值。这尤其包括某些对象图的分配内存。 我们的应
我将 SweetAlert 与 Symfony 结合使用,我希望用户在完成删除操作之前进行确认。 发生的情况是,当用户单击删除按钮时,SweetAlert 会弹出,然后立即消失,并且该项目被删除。 在
我们有一个应用程序可以生成不包括字母 O 的随机基数 35 [0-9A-Z]。我正在寻找一种解决方案来查找包含任何淫秽英语单词的代码,而无需搜索包含 10,000 个条目的列表每个生成的代码。每秒生成
这是我做的: #include #include int betweenArray(int a, int b){ int *arr,i,range; range = b - a +
我知道如何创建 警报和确认框,但我不知道如何做的是实际单击“确定”。我有一个弹出确认框的页面。 我想使用 Java Script 插件单击“确定”。基本上,我希望我的代码单击页面上的链接,然后在出现提
代码: swal('Your ORDER has been placed Successfully!!!'); window.location="index.php"; 甜蜜警报工
>>> import re >>> s = "These are the words in a sentence" >>> regex = re.compile('are|words') >>> [m
使用确定的理想散列函数给出随机期望线性时间算法两个数组 A[1..n] 和 B[1..n] 是否不相交,即 A 的元素是否也是 B 的元素。 谁能告诉我如何做到这一点,甚至如何开始考虑它? 最佳答案
我在计算机科学课上有这段代码: int input=15; while (input < n ) { input = input *3;} 这段代码有 log3(n/15) 次循环的上限。我们怎样才能
我有一个允许 2 位玩家玩 TicTacToe 的程序。在每个玩家移动之后,它应该在那个点显示棋盘并返回一个名为 Status 的枚举,显示玩家是否应该继续,如果玩家赢了,还是平局。但是,该算法要么返
给定一个 y 值数组,例如 [-3400, -1000, 500, 1200, 3790],我如何确定“好的”Y 轴标签并将它们放置在网格上? ^ ---(6,000)-|---
假设我有一个检查用户登录的 SQL 语句: SELECT * FROM users WHERE username='test@example.com', password='abc123', expi
teradata中有返回表中哪一列被定义为主索引的命令吗?我没有制作一些我正在处理的表,也没有尝试优化我对这些表的连接。谢谢! 最佳答案 有dbc.IndicesV,其中IndexNumber=1表示
我是一名优秀的程序员,十分优秀!