INSERT IGNORE генерирует нарушение первичного ключа, используя h2 в режиме mysql - PullRequest
0 голосов
/ 26 июня 2019

Я собираю данные Scopus в базу данных файла h2.В данных содержится более 46 000 000 записей, каждая из которых рассматривается как отдельная, что означает, что сотни ГБ данных повторяются (следовательно, реляционная база данных).Чтобы сократить время вставки всех этих данных, я сначала создаю набор временных таблиц без ограничений, а затем копирую данные в реальные таблицы позже, используя SELECT DISTINCT и GROUP BY для обеспечения уникальности.

Единственное исключение - таблица документов и таблица документов.Благодаря формату данных я могу гарантировать, что каждая запись представляет собой уникальный документ, поэтому я могу просто ВСТАВИТЬ В таблицу документов, а затем объединить только те строки из таблицы ссылочных документов, идентификаторы которых еще не указаны в таблице документов.

Вот соответствующий код:

CREATE TABLE document (docid varchar NOT NULL, title varchar, abstract varchar, docType varchar NULL, ref boolean);

CREATE TABLE refdoc (refid varchar NOT NULL, title varchar);

INSERT INTO document (docid, title, abstract, docType, ref)
VALUES ('2-s2.0-0000098715', 'title', 'abstract', 'ab', 'false');

INSERT INTO refdoc (refid, title)
VALUES ('2-s2.0-0000098715', 'title'),
VALUES ('2-s2.0-33947184743', 'title');

ALTER TABLE document
ADD PRIMARY KEY (docid);

ALTER TABLE document
ADD FOREIGN KEY (docType) REFERENCES doctype(abbrev);

INSERT IGNORE INTO document (docid, title, ref)
SELECT refid, title, 'true' FROM refdoc;

  • Создание таблицы документов
  • Создание таблицы ссылочных документов
  • Вставка записи в документытаблица
  • Вставить две записи в таблицу refdoc, включая дубликат
  • Изменить таблицу документов с помощью первичного ключа
  • Изменить таблицу документов с помощью внешнего ключа
  • Вставить строки из refdoc, которые не конфликтуют с документом

Запрос INSERT IGNORE выдает: org.h2.jdbc.JdbcSQLException: нарушение уникального индекса или первичного ключа: "CONSTRAINT_INDEX_6 ON PUBLIC.DOCUMENT (DOCID)

Я также пытался использовать WHERE NOT EXISTS:

INSERT INTO document (docid, title, ref)
SELECT refid, title, 'true'
FROM refdoc
WHERE NOT EXISTS (
SELECT refid FROM refdoc
INNER JOIN document
ON document.docid = refdoc.refid );

Но может показаться, что попытка присоединиться к таблицеТо, что не проиндексировано, фактически невозможно - ничего, что я пытался с помощью объединений, не сработало.

В качестве последнего средства я могу использовать FileHashMap и просто вывести содержимое таблицы refdoc, а затем создать мега-огромныйPreparedStatement вроде:

INSERT INTO document (docid, title, ref)
SELECT ?, ?, 'true'
WHERE NOT EXISTS (
SELECT docid FROM document
WHERE docid = ? );

Но я бы, очевидно, предпочел бы этого не делать, поскольку это будет длиться вечно.

1 Ответ

0 голосов
/ 27 июня 2019

Наконец-то найдено решение, которое не предполагает построения пакетного оператора из 100 000 000 записей. Проблема заключалась в том, что мне нужно было одновременно обеспечить, чтобы ссылки, которые я вставлял в документ, еще не были в таблице документов, а также чтобы я вставлял только уникальные строки из таблицы refdoc. Все мои решения до этого либо не избегали конфликтов, либо не принуждали к уникальности, либо включали объединения в таблицы, которые не имели индексов.

Вот решение SQL:

CREATE TABLE document (docid varchar NOT NULL, title varchar, abstract varchar, docType varchar NULL);

CREATE TABLE refdoc (refid varchar NOT NULL, title varchar);

INSERT INTO document (docid, title, abstract, docType)
VALUES ('2-s2.0-0000098715', 'title', 'abstract', 'ab');

INSERT INTO refdoc (refid, title)
VALUES ('2-s2.0-0000098715', 'title'),
VALUES ('2-s2.0-33947184743', 'title');

INSERT IGNORE INTO document (docid, title)
SELECT refid, MAX(title)
FROM refdoc
WHERE refid NOT IN (
SELECT docid FROM document )
GROUP BY refid;

ALTER TABLE document
ADD PRIMARY KEY (docid);

ALTER TABLE document
ADD FOREIGN KEY (docType) REFERENCES doctype(abbrev);

Логика теперь:

  • Создать таблицу документов
  • Создать таблицу ссылочных документов
  • Вставить запись в таблицу документов
  • Вставить две записи в таблицу refdoc, включая дубликат
  • Вставить строки из refdoc, которые не конфликтуют с документом и являются уникальными
  • Изменить таблицу документов первичным ключом
  • Изменить таблицу документов с помощью внешнего ключа

Это имеет дополнительный бонус - не индексирует таблицу документов до тех пор, пока вставки не будут завершены.

Мне до сих пор не совсем понятно, почему я получаю нарушение ограничения первичного ключа для таблицы без первичного ключа, но это звучит как что-то, что нужно отправить в h2 github в качестве отчета об ошибке.

...