Поздно к вечеринке, но я обдумываю что-то подобное.
Я создал следующую таблицу для отслеживания активных пользователей на лицензии в день:
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
, потому что (насколько мне известно) это атомная операция, и это сэкономит вам массу проблем при работе с потоками.
Если вы используете второй вариант, вам придется использовать транзакции. – CBroe
Возможный дубликат [On duplicate key ignore?] (Http://stackoverflow.com/questions/2366813/on-duplicate-key-ignore) –
Если вам нужен идентификатор поля, я бы предложил использовать INSERT/ON DUPLICATE KEY и сбросить поле id (см. здесь - http://stackoverflow.com/questions/778534/mysql-on-duplicate-key-last-insert-id), вызывая mysql, чтобы вернуть id в качестве последнего идентификатора вставки. – Kickstart