Bulk update в MySQL
Ревизия #2
В порыве пятничного отлынивания от работы, совместно с коллегой, родили нечто.
Нечто позволяет одним запросом обновлять неограниченное количество записей. Причем разные столбцы, на разные данные, в зависимости от уникального ключа.
Нечто имеет следующие недостатки:
- требует уникального ключа
- если строки с подходящим ключом нет, то она добавится
- для построения требует знаний о типах полей таблицы
- мускл на него ругается ворнингами
- NULL таким образом вставить невозможно
SQL:
CREATE TABLE `bulk_update` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`int` int(11) NOT NULL DEFAULT '7',
`str` varchar(5) NOT NULL DEFAULT 'def',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
INSERT INTO `bulk_update` (`id`, `int`, `str`)
VALUES (1, 1, 'a'), (2, 2, 'b'), (3, 3, 'c');
INSERT INTO `bulk_update` (`id`, `int`, `str`)
VALUES (1, 22, null), (2, null, 'bb')
ON DUPLICATE KEY UPDATE
`int` = IFNULL(NULLIF(VALUES(`int`), 0), `int`),
`str` = IFNULL(NULLIF(VALUES(`str`), ''), `str`);
SELECT * FROM bulk_update;
+----+-----+-----+
| id | int | str |
+----+-----+-----+
| 1 | 22 | a |
| 2 | 2 | bb |
| 3 | 3 | c |
+----+-----+-----+
Тесты скорости показали следующие результаты:
| Обновляемых записей | По одному (qps) | Кучкой (qps) |
|---|---|---|
| 10 | 2296 | 3620 |
| 100 | 3480 | 11097 |
| 1000 | 3959 | 18804 |
Во время теста параллельно пускались три скрипта, делающие разнообразные селекты к таблице.
Тест, как всегда, прилагается.
В общем штука получилась интересная, но какая-то костылеподобная.
UPD: Теперь работает и для столбцов с NOT NULL и без оного.