sql - vertica中的“在连接中检测到重复的合并键”
问题描述
我正在尝试使用 MERGE 将聚合数据插入到表集合中。对于每个表,有些字段可以为空,有些则不能。在 fieldA 和 FieldB 上声明了两个主键。当我运行 MERGE 语句时,我收到“在连接中检测到重复的 MERGE 键”错误。谁能帮我解决这个问题。
注意:当我截断目标表时,如果对临时表中的 fieldC 或 FieldD 进行任何更新操作,然后运行合并查询,它工作正常。但是下次当临时表中的 fieldC 或 fieldD 发生任何更新操作然后运行合并查询时,它会给出此错误。
示例伪语法:
CREATE TABLE target (
fieldA varchar,
fieldB varchar,
fieldC varchar null,
fieldD int not null,
FieldE int,
Constraint target_pk primary key(fieldA, fieldB));
CREATE TABLE temp (
fieldA varchar,
fieldB varchar,
fieldC varchar null,
fieldD int not null,
fieldE int,
Constraint temp_pk primary key(fieldA, fieldB));
MERGE INTO target trg
USING temp tmp ON (
trg.FieldA = tmp.FieldA
AND trg.FieldB = tmp.FieldB)
WHEN MATCHED THEN UPDATE
SET fieldC = tmp.fieldC ,
fieldD= tmp.fieldD,
fieldE=temp.fieldE
WHEN NOT MATCHED THEN INSERT (
FieldA ,
FieldB ,
FieldC ,
fieldD,
fieldE)
VALUES (
tmp.FieldA ,
tmp.FieldB ,
tmp.FieldC ,
tmp.fieldD,
tmp.fieldE);
解决方案
一开始,目标表是空的,甚至没有包含数据的投影。这样,访问计划就变成了一个简单的插入。事实上,当你用一个空的目标和一个完整的源来解释 MERGE 时,你得到一个空的解释计划。
-- here's a scenario - improved a bit -
-- never, if you can avoid it, use a VARCHAR with no length info
DROP TABLE IF EXISTS target;
DROP TABLE IF EXISTS temp;
CREATE TABLE target (
fieldA VARCHAR(8) NOT NULL,
fieldB VARCHAR(8) NOT NULL,
fieldC VARCHAR(8) NULL,
fieldD INT NOT NULL,
FieldE INT,
CONSTRAINT target_pk PRIMARY KEY(fieldA, fieldB)
);
CREATE TABLE temp LIKE target INCLUDING PROJECTIONS;
INSERT INTO temp
SELECT '1','1','A',1,1
UNION ALL SELECT '1','1','A',1,1 -- note that this is a duplicate of the row above
UNION ALL SELECT '1','2','B',1,2
UNION ALL SELECT '1','3','C',1,3
UNION ALL SELECT '1','4','D',1,4
UNION ALL SELECT '1','5','E',1,5
;
COMMIT;
用空表解释:
EXPLAIN
MERGE INTO target trg
USING temp tmp
ON trg.FieldA = tmp.FieldA
AND trg.FieldB = tmp.FieldB
WHEN MATCHED THEN UPDATE SET
fieldC = tmp.fieldC ,
fieldD = tmp.fieldD,
fieldE = tmp.fieldE
WHEN NOT MATCHED THEN INSERT (
FieldA ,
FieldB ,
FieldC ,
fieldD,
fieldE
) VALUES (
tmp.FieldA ,
tmp.FieldB ,
tmp.FieldC ,
tmp.fieldD,
tmp.fieldE
);
-- out Access Path:
-- out
-- out
-- out ------------------------------
-- empty.
现在,我执行第一个 MERGE 和 COMMIT:
MERGE INTO target trg
USING temp tmp
ON trg.FieldA = tmp.FieldA
AND trg.FieldB = tmp.FieldB
WHEN MATCHED THEN UPDATE SET
fieldC = tmp.fieldC ,
fieldD = tmp.fieldD,
fieldE = tmp.fieldE
WHEN NOT MATCHED THEN INSERT (
FieldA ,
FieldB ,
FieldC ,
fieldD,
fieldE
) VALUES (
tmp.FieldA ,
tmp.FieldB ,
tmp.FieldC ,
tmp.fieldD,
tmp.fieldE
);
COMMIT;
-- out OUTPUT
-- out --------
-- out 6
-- out (1 row)
-- out
-- out Time: First fetch (1 row): 142.089 ms. All rows formatted: 142.152 ms
-- out Time: First fetch (0 rows): 5.042 ms. All rows formatted: 5.059 ms
我再次解释了 MERGE:
-- out Access Path:
-- out +-DML MERGE [Cost: 0, Rows: 0]
-- out | Target Projection: dbadmin.target_super
-- out | Target Prep:
-- out | +---> JOIN MERGEJOIN(inputs presorted) [RightOuter] [Cost: 7K, Rows: 10K (NO STATISTICS)] (PATH ID: 1)
-- out | | Join Cond: (target.fieldA = VAL(2)) AND (target.fieldB = VAL(2))
-- out | | +-- Outer -> STORAGE ACCESS for <No Alias> [Cost: 4K, Rows: 10K (NO STATISTICS)] (PATH ID: 2)
-- out | | | Projection: dbadmin.target_super
-- out | | | Materialize: target.fieldA, target.fieldB, target.fieldC, target.fieldD, target.FieldE, target.epoch
-- out | | | Runtime Filters: (SIP1(MergeJoin): target.fieldA), (SIP2(MergeJoin): target.fieldB), (SIP3(MergeJoin): target.fieldA, target.fieldB)
-- out | | +-- Inner -> SELECT [Cost: 3K, Rows: 10K (NO STATISTICS)] (PATH ID: 3)
-- out | | | +---> STORAGE ACCESS for tmp [Cost: 3K, Rows: 10K (NO STATISTICS)] (PATH ID: 4)
-- out | | | | Projection: dbadmin.temp_super
-- out | | | | Materialize: tmp.fieldA, tmp.fieldB, tmp.fieldC, tmp.fieldD, tmp.FieldE
现在您看到有一个DML MERGE
操作,它从一个操作中读取JOIN MERGEJOIN
。
当您 truncatetarget
时,投影仍然存在,但为空。事实上,EXPLAIN
当目标表被截断时,你也会得到第二个版本,但确实有一个投影。
您遇到了 Vertica 的一个特点,因为它是一个大数据平台,针对性能进行了优化。
- 默认情况下,对表的约束是
DISABLED
,如果您希望启用它,则必须ALTER TABLE ENABLE CONSTRAINT ...
- 这样做会大大减慢任何海量数据操作的速度。 - 使用禁用的主键约束,您可以插入重复项 - 但随后
JOIN
使用目标表的主键列 -OUTER
解释计划中的表 - 将尝试利用构建计划的唯一性 - 如果遇到则失败重复键。它以一个空的外部目标表成功。
因此,您与包含重复键的完整目标的 MERGE 失败。
您在删除重复项方面需要帮助吗?有一堆带有 [Vertica] 标签的帖子处理这个......
推荐阅读
- php - 如何使用基于数据库行的 N 个表单填充 Smyfony CollectionType
- c# - 如何为现有的数据库提供者注入/拦截 DbConnection 实例?
- javascript - 如何将依赖项传递给 Vue 组件?
- angular - 从打字稿中的集合中提取值给出错误
- amazon-web-services - 从多个账户到中央账户的 AWS 可信咨询报告
- php - 将特定数据绑定到 url
- r - 如何计算包含特定单词的值?
- discord - youtube-dl 的 Discord.py Bot 问题
- r - 如何使用 geom_sf 从坐标中绘制具有多个孔的多边形?
- arrays - Angular:从数组中的 1 个对象创建 2 个对象