“插入忽略”vs“选择并插入”

时间:2014-01-28 15:10:46

标签: mysql database performance optimization insert

我想写一个程序向表中添加新项。这个项目有一个唯一的键name,它可以由100个线程中的一个创建,所以我需要确保它只插入一次。

我有两个想法:

  1. 使用insert ignore

  2. 如果没有返回的行,则通过select从数据库获取,然后insert将其提取到表。

  3. 哪个选项更好?还有一个更优越的想法吗?

3 个答案:

答案 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的性能。