Как обработать mysql # 1062 - Дублирующая ошибка ввода при создании большой таблицы - PullRequest
2 голосов
/ 20 февраля 2012

Я работаю над таблицей, имеющей около 5 миллионов записей. Я загружаю записи из CSV-файла.

Существует уникальный столбец, url.

При вставке, если url уже есть в таблице, я хочу внести изменения в новое значение url, а затем выполнить вставку.

Пример:

  • попробуйте вставить запись с url из "book". Если "book" уже существует, новая запись должна иметь url "book-1" (тогда "book-2" и т. Д.)

  • результат: значения url "book-1","book-2"... находятся в таблице в дополнение к начальному значению book

Я понял, что есть 2 способа сделать это.

  1. перед вставкой каждой записи: проверьте, существует ли уже значение url; если это произойдет, внесите необходимые изменения в новое значение url и вставьте. Боюсь, что это приведет к плохой производительности.

  2. вставлять записи, не проверяя, существует ли уже значение url. Если значение url уже существует, обработайте «mysql # 1062 - Ошибка повторяющегося ввода» и внесите необходимые изменения в значение url; повторите ввод.

Возможно ли это? Если да, то как?

Ответы [ 2 ]

1 голос
/ 20 февраля 2012

Если это разовая проблема, я бы рекомендовал специальное решение MySQL:

  1. Если ваша таблица не MyISAM, преобразуйте в MyISAM.
  2. Временно создайте столбец целых чисел auto_increment с именем url_suffix.
  3. Временно удалите уникальное ограничение для столбца url.
  4. Создайте индекс из нескольких столбцов (url, url_suffix) и убедитесь, что нет других индексов, использующих url_suffix.
  5. Вставьте все свои строки, разрешив дублирование URL. Вы заметите, что столбец auto_increment url_suffix теперь вводится в URL. Итак, первый конкретный url будет иметь url_suffix из 1, а следующий 2 и т. Д.
  6. Сделайте обновление, подобное следующему, затем удалите временный столбец url_suffix и верните свое уникальное ограничение.

Запрос на обновление всех строк:

UPDATE urls
SET url = if (url_suffix = 1, url, CONCAT(url, '-', url_suffix - 1))

На самом деле, вы можете пропустить шаг 6, оставить поле auto_increment, чтобы вы могли легко добавлять дубликаты URL-адресов в будущем и просто извлекать ваши URL-адреса следующим образом:

SELECT (if (url_suffix = 1, url, CONCAT(url, '-', url_suffix - 1))) AS url
FROM urls

Ваши данные будут выглядеть примерно так:

url     url_suffix
---------------------------
that    1
that    2
this    1
this    2
this    3
those   1
1 голос
/ 20 февраля 2012

У вас есть проблема в том, что простой триггер окажется неэффективным при вставке из-за того, что вы говорите, что они перейдут из «book» в «book-1», «book-2» и т. Д. Самый простой способ сделатьэто будет иметь новый столбец, который содержит числовое значение по умолчанию 0. Это может быть сделано в хранимой процедуре, т.е.

CREATE PROCEDURE `insertURL`(inURL VARCHAR(255))

BEGIN
    DECLARE thisSuffix INT UNSIGNED DEFAULT 0;
    // We have to get this ID first, as MySQL won't let you select from the table you are inserting to
    SELECT COALESCE(MAX(url_suffix)+1,0) INTO thisSuffix FROM urls WHERE url_column = inURL;
    // Now the ID is retrieved, insert
    INSERT INTO urls (
        url_column,
        url_suffix
    ) VALUES (
        inURL,
        thisSuffix
    );
    // And then select the generated URL
    SELECT IF(thisSuffix>0,CONCAT(inURL,'-',thisSuffix),inURL) AS outURL;
END

, которая затем вызывается с использованием

CALL insertURL('book');

Изатем вернет 'book', если суффикс = 0, или 'book-1', если он имеет суффикс больше 0.

В целях тестирования мой дизайн таблицы был

CREATE TABLE `urls` (
`url_column`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL ,
`url_suffix`  tinyint(3) UNSIGNED NOT NULL ,
PRIMARY KEY (`url_column`, `url_suffix`)
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...