2014-01-28 7 views
4

Я хочу написать программу, чтобы добавить новый элемент в таблицу. Этот элемент имеет уникальный ключ name и может быть создан одним из 100 потоков, поэтому мне нужно убедиться, что он вставлен только один раз.«Вставить игнорировать» vs «select and insert»

У меня есть две идеи:

  1. Используйте insert ignore

  2. Пиль из базы данных с помощью select затем insert его в таблицу, если не возвращаемой строки.

Какой вариант лучше? Есть ли еще более совершенная идея?

+0

Если вы используете второй вариант, вам придется использовать транзакции. – CBroe

+0

Возможный дубликат [On duplicate key ignore?] (Http://stackoverflow.com/questions/2366813/on-duplicate-key-ignore) –

+0

Если вам нужен идентификатор поля, я бы предложил использовать INSERT/ON DUPLICATE KEY и сбросить поле id (см. здесь - http://stackoverflow.com/questions/778534/mysql-on-duplicate-key-last-insert-id), вызывая mysql, чтобы вернуть id в качестве последнего идентификатора вставки. – Kickstart

ответ

3

SELECT + INSERT - две круглые поездки на сервер, следовательно, медленнее.

INSERT IGNORE - требуется ключ PRIMARY или UNIQUE, чтобы решить, следует ли вводить новый INSERT. Если это сработает для вас, это, наверное, самое лучшее.

REPLACE - DELETE + INSERT. Это редко бывает лучше.

INSERT ... ON KEY UPDATE DUPLICATE - Это позволяет либо INSERT (если ОСНОВНОЙ/UNIQUE ключ (ы) не найден) или UPDATE. Это тот, который использует , если у вас есть вещи, которые необходимо обновить в существующих строках.

+0

Если вам нужен вставленный идентификатор после IODKU, см. Руководство о трюке для получения идентификатора через '... UPDATE id = LAST_INSERT_ID (id) ...'. –

+0

Что делать, если это было внутри хранимой процедуры? Так или иначе, все равно. –

+0

Да, SP спасет кругосветку. Клиент к серверному обращению сильно зависит от физического расстояния. Стоимость инициирования каждого оператора мала, но не равна нулю. –

1

Поздно к вечеринке, но я обдумываю что-то подобное.

Я создал следующую таблицу для отслеживания активных пользователей на лицензии в день:

CREATE TABLE `license_active_users` (
    `license_active_user_id` int(11) NOT NULL AUTO_INCREMENT, 
    `license_id` int(11) NOT NULL, 
    `user_id` int(11) NOT NULL, 
    `date` date NOT NULL, 
    PRIMARY KEY (`license_active_user_id`), 
    UNIQUE KEY `license_id` (`license_id`,`user_id`,`date`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

Другими словами, 1 первичный ключ и 1 уникальный индекс через 3 остальных столбцов.

Затем я вставил 1 миллион уникальных строк в таблицу.

Попытка повторно вставить подмножество (10000 строк) одних и тех же данных были получены следующие результаты:

  • INSERT IGNORE: 38 секунд
  • INSERT ... ON DUPLICATE KEY UPDATE: 40 секунд
  • if (!rowExists("SELECT ..."))INSERT: < 2 секунды

Если эти 10 000 строк еще не присутствуют в таблице:

  • INSERT IGNORE: 34 секунд
  • INSERT ... ON DUPLICATE KEY UPDATE: 41 секунд
  • if (!rowExists("SELECT ..."))INSERT: 21 секунд

Так что вывод должен быть if (!rowExists("SELECT ..."))INSERT является самым быстрым на сегодняшний день - по крайней мере, для этой конкретной конфигурации таблицы ,

недостающий тест if (rowExists("SELECT ...")){UPDATE} else {INSERT}, но я предполагаю, что INSERT ... ON DUPLICATE KEY UPDATE быстрее для этой операции.

Для вашего конкретного случая, однако, я бы пошел с INSERT IGNORE, потому что (насколько мне известно) это атомная операция, и это сэкономит вам массу проблем при работе с потоками.

0

Best: SELECT + INSERT IGNORE.

Потому что это используется SELECT для проверки, что в таблице не нужно блокировать таблицу или строку. Любой замок INSERT необходим. Таким образом, это может снизить производительность на одновременных INSERT.

Смежные вопросы