Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL如何确定插入是否唯一?_Mysql_Insert_Unique - Fatal编程技术网

MySQL如何确定插入是否唯一?

MySQL如何确定插入是否唯一?,mysql,insert,unique,Mysql,Insert,Unique,我想知道在对任何列定义为唯一的表执行INSERT之前是否运行了隐式SELECT。我在INSERT的文档中找不到任何与此相关的内容 我问了一些其他的问题,似乎没有人能够回答——也许是因为我没有正确地解释自己——这些问题与上述问题有关 如果我理解正确,那么我假设以下是正确的: 案例1: 您有一个包含10亿行的表。每行都有一个唯一的UUID列。如果执行插入,服务器必须执行某种隐式的从表中选择COUNT(*),其中UUID=[new UUID],并确定计数是0还是1。对吗 案例2: 您有一个包含10亿行

我想知道在对任何列定义为唯一的表执行INSERT之前是否运行了隐式SELECT。我在INSERT的文档中找不到任何与此相关的内容

我问了一些其他的问题,似乎没有人能够回答——也许是因为我没有正确地解释自己——这些问题与上述问题有关

如果我理解正确,那么我假设以下是正确的:

案例1: 您有一个包含10亿行的表。每行都有一个唯一的UUID列。如果执行插入,服务器必须执行某种隐式的
从表中选择COUNT(*),其中UUID=[new UUID]
,并确定计数是0还是1。对吗

案例2: 您有一个包含10亿行的表。每行都有一个由日期和UUID组成的复合唯一键。如果执行插入,服务器必须执行某种隐式
操作,从表中选择COUNT(*),其中DATE=[DATE]和UUID=[new UUID]
,并检查计数是0还是1。是吗

我使用隐式这个词是因为在这个过程的某个地方,服务器必须检查这个值。如果不是的话,它将要求物理定律规定两个相同的行不可能存在——据我所知,当涉及到以二进制形式写在计算机磁盘上的某个地方的数字的唯一性时,物理并没有起到很大的作用

让我们假设10亿行在2000个不同的日期中均匀地、顺序地分布。这是否意味着案例2可以更快地执行插入,因为它可以查找分段为日期的UUID?如果不是,那么使用案例1来提高插入速度会更好吗?在这种情况下,为什么

这个问题是理论性的,所以在这种情况下,不要考虑常规的SELECT性能。主键不是UUID+日期索引


作为对评论的回应:在我的例子中,UUID的设计完全是为了避免由于不良连接而出现重复条目。由于您不能为不同的日期创建两个相同的条目(逻辑上它不是一个新条目),因此UUID不需要全局唯一—它只需要对每个日期唯一。这就是为什么我可以允许它成为复合密钥的一部分。

这就是

UNIQUE
索引创建一个约束,使得索引中的所有值都必须是不同的。如果您尝试使用与[另一]现有行匹配的键值添加新行[或更新现有行],则会发生错误

在同一手册的前面一页中,说明

表单
(col1,col2,…)
的列列表创建多列索引。索引键值通过连接给定列的值形成

该约束的实现方式没有文档记录,但它必须以某种方式等同于带有要插入/更新的值的初步
SELECT
。这种检查的成本通常可以忽略不计,因为根据定义,字段是索引的(这种开销变得相关)


索引所覆盖的列数在性能方面没有意义(例如,与表中的行数相比)。它确实会影响索引占用的磁盘空间,但这在您的设计决策中并不重要。

在表中插入大量数据时,请记住,数据最终会物理存储在某个磁盘上。为了从磁盘上读写数据,MySQL(和大多数其他RDBMS)使用了一种称为。如果在表上指定主键或唯一索引,则参与键/索引的列将成为聚集索引键。这意味着数据在磁盘上的物理存储顺序与键列中的值相同

通过使用聚集索引,数据库引擎可以快速确定值是否已经存在,而无需扫描整个表。理论上,如果一个表包含N=1.000.000条记录,引擎平均需要log2(N)=20个操作来检查值是否存在,而不管索引中有多少列参与。对于二级索引,通常使用B-树或哈希表(在web上搜索这些术语,以了解它们如何工作的详细说明)

这个结论是错误的:

“…MySQL无法缓冲足够的数据以保证值为空。” 独特的,因此导致执行大量的 每个插入的读数以确保唯一性”

这是不正确的。检查唯一性实际上不需要任何额外的工作,因为引擎必须找到插入新记录的位置。导致性能下降的原因是UUID的使用。请记住,每当插入新记录时,UUID都是随机生成的。这意味着需要将新记录插入磁盘上的随机物理位置,这会导致现有数据四处移动,以容纳新记录。另一方面,如果索引列是单调递增的值(如自动递增INT),则新记录将始终插入最后一条记录之后,这意味着不需要移动现有数据

在您的情况下,案例1和案例2之间不会有任何性能差异。但由于UUID的随机性,您仍然会遇到麻烦。如果使用自动递增的值而不是UUID,则会更好。此外,由于UUID在本质上总是唯一的,因此使用唯一约束对其进行索引实际上没有多大意义。或者,如果您确实必须使用UUID,请确保表中有一个基于自动递增INT的主键,以确保不会在t上随机插入新记录