我想写一个程序向表中添加新项。这个项目有一个唯一的键name
,它可以由100个线程中的一个创建,所以我需要确保它只插入一次。
我有两个想法:
使用insert ignore
如果没有返回的行,则通过select
从数据库获取,然后insert
将其提取到表。
哪个选项更好?还有一个更优越的想法吗?
答案 0 :(得分:6)
SELECT + INSERT - 两次往返服务器,因此速度较慢。
INSERT IGNORE - 需要PRIMARY或UNIQUE键来决定是否抛出新的INSERT。如果这适合你,那可能是最好的。
REPLACE - 是DELETE + INSERT。这很少是最好的。
INSERT ... ON DUPLICATE KEY UPDATE - 这使您可以INSERT(如果找不到PRIMARY / UNIQUE键)或 UPDATE。这是使用的那个,如果你需要在现有行中更新的东西。
答案 1 :(得分:2)
晚会,但我正在思考类似的事情。
我创建了下表以每天跟踪许可证上的活跃用户:
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;
换句话说,其余3列中有1个主键和1个唯一索引。
然后我在表格中插入了100万个唯一的行。
尝试重新插入相同数据的子集(10,000行)会产生以下结果:
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
此操作的速度更快。< / p>
但是,对于你的特定情况,我会选择INSERT IGNORE
因为(据我所知)这是一个原子操作,在使用线程时会省去很多麻烦。
答案 2 :(得分:1)
最佳:SELECT + INSERT IGNORE。
因为使用SELECT进行检查,所以不需要锁表或表中的行。 任何INSERT都需要锁定。所以这会降低并发INSERT的性能。