sql vertica中的“join中检测到重复的合并键”

lhcgjxsq  于 2021-07-24  发布在  Java
关注(0)|答案(1)|浏览(505)

我尝试使用merge将聚合数据向上插入到表集合中。对于每个表,有些字段可为空,有些字段不可为空。fielda和fieldb上声明了两个主键。当我运行merge语句时,我收到一个“join中检测到重复的合并键”错误。有人能帮我解决这个问题吗。
注意:当我截短目标表时,如果我在temp表中的fieldc或fieldd上执行任何更新操作,然后运行merge query,它的工作正常。但下一次在临时表中的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);
eit6fx6z

eit6fx6z1#

一开始,目标表是空的,它甚至没有包含数据的投影。这样,访问计划就变成了一个简单的插入。事实上,当你用一个空的目标和一个完整的源来解释合并时,你会得到一个空的解释计划。

-- 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 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

我再解释一下合并:

-- 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 操作。
当你截断 target ,投影仍保留,但为空。事实上你得到了第二个版本的 EXPLAIN 当目标表被截断,但确实有投影时也是如此。
你发现了vertica的一个特点,那是因为它是一个性能优化的大数据平台。
默认情况下,表上的约束是 DISABLED ,如果要启用它,则必须 ALTER TABLE ENABLE CONSTRAINT ... -这样就大大降低了海量数据的处理速度。
在禁用主键约束的情况下,可以插入重复项,但后续的 JOIN 使用目标表的主键列 OUTER explain计划中的表-将尝试利用构建计划中的唯一性-如果遇到重复的键,它将失败。它成功的外部、目标、表为空。
因此,与包含重复键的完整目标的合并失败。
删除重复项时需要帮助吗?有一堆贴有[vertica]标签的帖子在处理这个问题。。。

相关问题