"插入忽略"vs"选择并插入"

use*_*050 9 mysql database optimization performance insert

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

我有两个想法:

  1. 使用 insert ignore

  2. 如果没有返回的行,则从数据库中获取它select然后insert再到表.

哪个选项更好?有更优越的想法吗?

Ric*_*mes 6

SELECT + INSERT - 两次往返服务器,因此速度较慢.

INSERT IGNORE - 需要PRIMARY或UNIQUE键来决定是否抛出新的INSERT.如果这适合你,那可能是最好的.

REPLACE - 是DELETE + INSERT.这很少是最好的.

INSERT ... ON DUPLICATE KEY UPDATE - 这使您可以INSERT(如果未找到PRIMARY/UNIQUE键) UPDATE.如果您需要在现有行中更新所需的内容,可以使用此选项.


Woo*_*ome 6

晚会晚了,但我正在考虑类似的事情。

我创建了下表来每天跟踪许可证上的活动用户:

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;
Run Code Online (Sandbox Code Playgroud)

换句话说,其余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此操作更快。

但是,对于您的特殊情况,我会选择使用它,INSERT IGNORE因为(据我所知)这是一个原子操作,在使用线程时可以为您节省很多麻烦。