TL; DR:
插入大量的行的无冲突快得多比(不)重新插入相同的行,BOTH使用INSERT IGNORE
语法。
为什么是这样?我假设插入和“忽略”插入的索引查找成本相同,因为 MySQL 不知道传入的数据是否具有重复/冲突的数据(因此需要被忽略)......因此,索引发生在初始插入和被忽略的插入运行中。
此外,我认为“忽略”行应该是便宜的,因为它不需要任何磁盘写入。
但这绝对不是这种情况。
长版:
在这个问题中,我们使用 AWS 的 Aurora/MySQL 和LOAD DATA FROM S3 FILE
语法来删除任何传输或性能变量。我们加载了一个与下面架构相对应的 4 兆行 CSV 文件,并加载了两次,每次都使用LOAD ... IGNORE
.
请注意,该问题也发生在标准INSERT ... IGNORE
,但使用批量行插入时。LOAD ... IGNORE
这里的用途是将讨论引向测量结果的反直觉性质,而不是“如何执行大量被忽略的插入”。这不是这里的问题,因为已经制定了特定于域的方法。
在被测试的模型中,有一个三层索引:前两个是基数非常低的可枚举分类列,第三个列本质上是“实际”数据。为了简化这个问题,我只是坚持我目前的设置。
假设以下简单模式:
our_table:
id: basic auto-increment bigint, primary key
constkey1: varchar(50) -- this is a constant in the insert
constkey2: varchar(50) -- this is a constant in the insert
datakey: varchar(50) -- this is pulled in …
Run Code Online (Sandbox Code Playgroud) 是涵盖非唯一索引/指数ç在onsistency条款Ç ID?(对于不限制数据的索引的其他属性也是如此)我在 Postgres 中看到了某些性能问题(实际上是好处),这让我想知道它们是否存在。
鉴于索引/索引不是一流的对象(即您不能直接在 Postgres 中访问它们,也不能请求使用它们),我完全看不出为什么需要 Postgres 来支持这一点。我找不到 ACID 的定义说“索引必须完全完成并且在事务完成之前不能被黑客攻击”。
在某些不对插入设置限制的条件下(例如索引不是唯一的),索引本质上可能是“无效的”(即“在我完成重新索引之前不要使用它”),或者标志可以是设置表示“该索引不涵盖以下范围”。
如果 Postgres 使用这个技巧,copy from
操作符可以变得非常迅速(这就是我所看到的),对于事务中的大量插入计数也是如此。
我不只是编造这个...
虽然红移是一个坏榜样,亚马逊黄鼠狼出Ç由捉弄它是如何存储的(唯一)排序键(基本上在红移主索引十岁上下结构)onsistency。在执行vacuum
命令之前,主键只会变得越来越糟糕,您的数据库开始变成一个黑洞:查询进入,但没有结果出来。
显然,内部化的真空方案将防止在大规模进口期间经常发生的 Redshift 愚蠢行为。