Вначале целевая таблица пуста, и у нее даже нет проекции для хранения данных. При этом план доступа становится простой вставкой. Фактически, когда вы ОБЪЯСНИТЕ СЛИЯНИЕ с пустой целью и полным источником, вы получите пустой план объяснения.
-- 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
операция.
При усечении target
проекция остается, но пуста. Фактически вы получаете вторую версию EXPLAIN
также тогда, когда целевая таблица усечена, но имеет проекцию.
Вы обнаруживаете особенность Vertica, потому что это платформа для больших данных, оптимизирован для производительности.
- Ограничение таблицы по умолчанию
DISABLED
, и если вы хотите, чтобы оно было включено, вы должны ALTER TABLE ENABLE CONSTRAINT ...
- тем самым замедляя любые манипуляции с массовыми данными - С отключенным ограничением первичного ключа вы можете вставлять дубликаты, но последующие
JOIN
с использованием столбцов первичного ключа целевой таблицы - таблицы OUTER
в объяснении plan - попытается воспользоваться уникальностью при построении плана - и потерпит неудачу, если обнаружит повторяющиеся ключи. И это успешно с пустой внешней целевой таблицей.
Из-за этого происходит сбой вашего MERGE с полной целью, содержащей повторяющиеся ключи.
Вам нужна помощь в удалении дубликатов? Есть несколько сообщений с тегом [Vertica], посвященным этому ...