我的mysql群集:INSERT INTO `sometable` (SELECT ...);
我有一个复杂的SQL查询,它使用以下语法将大约36k行插入到表中:
CREATE TABLE `sometable` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(11) unsigned DEFAULT NULL,
`a` varchar(255) DEFAULT NULL,
`b` smallint(6) unsigned DEFAULT NULL,
`c` smallint(6) unsigned DEFAULT NULL,
`d` smallint(6) unsigned DEFAULT NULL,
`e` smallint(6) unsigned DEFAULT NULL,
`f` varchar(255) DEFAULT '',
`country_id` int(10) unsigned DEFAULT NULL,
`city_id` int(10) unsigned DEFAULT NULL,
`g` smallint(6) unsigned DEFAULT NULL,
`h` smallint(6) unsigned DEFAULT NULL,
`i` smallint(6) unsigned DEFAULT NULL,
`j` smallint(6) unsigned DEFAULT NULL,
`k` smallint(6) unsigned DEFAULT NULL,
`l` varchar(3) DEFAULT NULL,
`m` varchar(3) DEFAULT NULL,
`n` text,
`o` varchar(255) DEFAULT NULL,
`p` varchar(32) DEFAULT NULL,
`q` varchar(32) DEFAULT NULL,
`r` varchar(32) DEFAULT NULL,
`s` time DEFAULT NULL,
`t` time DEFAULT NULL,
`u` text,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `country_id` (`country_id`),
KEY `city_id` (`city_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
选择有点复杂但不慢(0.0023s)但插入需要大约40-50s。我在插入行时没有使用该表。
我的问题是:
由于
更新
表架构:
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
UPDATE2:
当我尝试运行查询时,在某些情况下会出现错误:
mytable
我的解决方案:
如果有兴趣的人,这是我的最终解决方案: gist
主要问题是,当我填充mytable
时,其他查询被卡住,群集出现了严重的性能问题。在这个解决方案中,我创建了一个临时表,并在“脏读”模式下用数据填充它,然后我将这些数据以块的形式复制到await _signInManager.RefreshSignInAsync(user);
,这样它需要更多的时间,但没有性能问题而且没有卡住查询。
答案 0 :(得分:1)
一个value
操作,每隔64纳秒返回一行描述的行,速度非常快。这就是2.3毫秒内36千里的成功率。您的SELECT
查询时间似乎不会将结果集传输到MySQL客户端。无论如何,使用该性能作为INSERT操作的比较会使您的期望值过高。
您可以在开始操作之前尝试发出此命令。它将允许您的SELECT
操作继续使用SELECT
的源表上的应用程序流量进行较少的争用。见https://dev.mysql.com/doc/refman/5.7/en/set-transaction.html
SELECT
您可以尝试一个包含临时表的两步过程。这样做的好处是不必在SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
操作的同时更新some_table
中的所有索引。该操作将如下所示。
SELECT
您应该了解InnoDB将您的一批插入作为单个事务发布到您的表中。如果你能够以一次处理大约500行而不是36K的方式执行此操作,那么您将拥有更多的事务,但它们会更小。这通常是获得更高吞吐量的一种方式。
答案 1 :(得分:1)
如果一切都失败了,这可能是一个可行的解决方案。首先,请参阅http://mysql.rjweb.org/doc.php/deletebig#deleting_in_chunks
INSERT ... SELECT ...
。此技术可能(或可能不会)花费超过40-50秒,但至少不会超时或死锁。
通常,避免运行任何持续时间超过几秒的事务。这个链接在如何“分块”冗长(和重复)操作以避免长事务方面有点泛泛。