对大多数表使用MySQL 5.6和InnoDB存储引擎。InnoDB缓冲池大小为15 GB,Innodb DB +索引约为10 GB。服务器具有32GB RAM,并且正在运行Cent OS 7 x64。
我有一张大表,其中包含大约一千万条记录。
我每24小时从远程服务器获取一个更新的转储文件。该文件为csv格式。我无法控制该格式。该文件约为750 MB。我尝试将数据逐行插入MyISAM表中,这花了35分钟。
我只需要从文件中取出10-12行中的每行3个值,然后在数据库中更新它。
实现这样的最佳方法是什么?
我需要每天这样做。
当前Flow是这样的:
- mysqli_begin_transaction
- 逐行读取转储文件
- 逐行更新每个记录。
- mysqli_commit
以上操作大约需要30-40分钟才能完成,在执行此操作的同时,还有其他更新正在进行中
超过了锁定等待超时;尝试重新启动事务
更新1
使用加载新表中的数据LOAD DATA LOCAL INFILE
。在MyISAM中,花38.93 sec
了7分钟5.21秒,而在InnoDB中,花了7分钟。然后我做了:
UPDATE table1 t1, table2 t2
SET
t1.field1 = t2.field1,
t1.field2 = t2.field2,
t1.field3 = t2.field3
WHERE t1.field10 = t2.field10
Query OK, 434914 rows affected (22 hours 14 min 47.55 sec)
更新2
与连接查询相同的更新
UPDATE table1 a JOIN table2 b
ON a.field1 = b.field1
SET
a.field2 = b.field2,
a.field3 = b.field3,
a.field4 = b.field4
(14 hours 56 min 46.85 sec)
评论中问题的澄清:
- 该文件将更新表中约6%的行,但有时可能多达25%。
- 在要更新的字段上有索引。表上有12个索引,其中8个索引包含更新字段。
- 它不是必要做的更新在一个事务中。这可能需要一些时间,但不能超过24小时。我希望在1小时内完成它而不锁定整个表,因为稍后我必须更新依赖于此表的sphinx索引。只要数据库可用于其他任务,步骤是否花费更长的时间都没有关系。
- 我可以在预处理步骤中修改csv格式。唯一重要的是快速更新且没有锁定。
- 表2是MyISAM。它是使用加载数据infile从csv文件中新创建的表。MYI文件大小为452 MB。表2在field1列上建立索引。
- MyISAM表的MYD为663MB。
更新3:
这是有关这两个表的更多详细信息。
CREATE TABLE `content` (
`hash` char(40) CHARACTER SET ascii NOT NULL DEFAULT '',
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`og_name` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`keywords` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
`files_count` smallint(5) unsigned NOT NULL DEFAULT '0',
`more_files` smallint(5) unsigned NOT NULL DEFAULT '0',
`files` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
`category` smallint(3) unsigned NOT NULL DEFAULT '600',
`size` bigint(19) unsigned NOT NULL DEFAULT '0',
`downloaders` int(11) NOT NULL DEFAULT '0',
`completed` int(11) NOT NULL DEFAULT '0',
`uploaders` int(11) NOT NULL DEFAULT '0',
`creation_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`upload_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`last_updated` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`vote_up` int(11) unsigned NOT NULL DEFAULT '0',
`vote_down` int(11) unsigned NOT NULL DEFAULT '0',
`comments_count` int(11) NOT NULL DEFAULT '0',
`imdb` int(8) unsigned NOT NULL DEFAULT '0',
`video_sample` tinyint(1) NOT NULL DEFAULT '0',
`video_quality` tinyint(2) NOT NULL DEFAULT '0',
`audio_lang` varchar(127) CHARACTER SET ascii NOT NULL DEFAULT '',
`subtitle_lang` varchar(127) CHARACTER SET ascii NOT NULL DEFAULT '',
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
`uploader` int(11) unsigned NOT NULL DEFAULT '0',
`anonymous` tinyint(1) NOT NULL DEFAULT '0',
`enabled` tinyint(1) unsigned NOT NULL DEFAULT '0',
`tfile_size` int(11) unsigned NOT NULL DEFAULT '0',
`scrape_source` tinyint(1) unsigned NOT NULL DEFAULT '0',
`record_num` int(11) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`record_num`),
UNIQUE KEY `hash` (`hash`),
KEY `uploaders` (`uploaders`),
KEY `tfile_size` (`tfile_size`),
KEY `enabled_category_upload_date_verified_` (`enabled`,`category`,`upload_date`,`verified`),
KEY `enabled_upload_date_verified_` (`enabled`,`upload_date`,`verified`),
KEY `enabled_category_verified_` (`enabled`,`category`,`verified`),
KEY `enabled_verified_` (`enabled`,`verified`),
KEY `enabled_uploader_` (`enabled`,`uploader`),
KEY `anonymous_uploader_` (`anonymous`,`uploader`),
KEY `enabled_uploaders_upload_date_` (`enabled`,`uploaders`,`upload_date`),
KEY `enabled_verified_category` (`enabled`,`verified`,`category`),
KEY `verified_enabled_category` (`verified`,`enabled`,`category`)
) ENGINE=InnoDB AUTO_INCREMENT=7551163 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=FIXED
CREATE TABLE `content_csv_dump_temp` (
`hash` char(40) CHARACTER SET ascii NOT NULL DEFAULT '',
`title` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`category_id` int(11) unsigned NOT NULL DEFAULT '0',
`uploaders` int(11) unsigned NOT NULL DEFAULT '0',
`downloaders` int(11) unsigned NOT NULL DEFAULT '0',
`verified` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`hash`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
这是更新查询,它content
使用来自content_csv_dump_temp
UPDATE content a JOIN content_csv_dump_temp b
ON a.hash = b.hash
SET
a.uploaders = b.uploaders,
a.downloaders = b.downloaders,
a.verified = b.verified
更新4:
以上所有测试都是在测试机上进行的,但是现在我在生产机上进行了相同的测试,查询速度非常快。
mysql> UPDATE content_test a JOIN content_csv_dump_temp b
-> ON a.hash = b.hash
-> SET
-> a.uploaders = b.uploaders,
-> a.downloaders = b.downloaders,
-> a.verified = b.verified;
Query OK, 2673528 rows affected (7 min 50.42 sec)
Rows matched: 7044818 Changed: 2673528 Warnings: 0
我为我的错误道歉。最好使用连接而不是每个记录更新。现在,我正在尝试使用rick_james建议的索引来改进mpre,一旦完成基准测试,它将更新。
UPDATEs
。请确切告诉我们从csv数据更新表的简单语句是什么样的。 然后,我们可能可以帮助您设计出满足您要求的技术。
update
,请检查更新的问题。,谢谢
INDEX(field2, field3, field4)
(任何顺序)吗?请给我们看看SHOW CREATE TABLE
。