java - 大型数据插入 (> 4,000,000) 的 SQL INSERT 性能
问题描述
我在向表中插入大量数据时遇到了问题。
我有一个 xml 文件中的数据,大小从40 MB 到 3 GB。解析数据最多需要 3 分钟。将数据插入到一个 700 MB 文件的表中大约需要 30 分钟。太长了,数据总量200GB左右,插入数据库需要一个月的时间。
如何优化插入?
重要提示:记录中的数据可能重复。我在复制时使用 UPDATE ON DUPLICATE KEY。
我试过的:
使用 Hibernate 并分批插入 1000\5000\10000 条记录。
生成本机 sql 并插入。(生成每个插入需要不到一秒钟的时间)。
使用 MySQL 中的 LOAD XML
创建一个临时表,将数据加载到其中,然后将其插入到主表中
不幸的是,所有这些方法都太慢了。
数据库中的表:
CREATE TABLE as_apartments_params (
id int NOT NULL,
objectid int NOT NULL,
changeid int DEFAULT NULL,
changeidend int NOT NULL,
typeid int NOT NULL,
value varchar(8000) DEFAULT NULL,
updatedate date NOT NULL,
startdate date NOT NULL,
enddate date NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_0900_ai_ci;
XML 文件:
<?xml version="1.0" encoding="utf-8"?><PARAMS>
<PARAM ID="719546591" OBJECTID="40537945" CHANGEID="192698204" CHANGEIDEND="0" TYPEID="8" VALUE="83:00:050002:426" UPDATEDATE="2021-04-29" STARTDATE="2021-04-29" ENDDATE="2079-06-06" />
<PARAM ID="719547975" OBJECTID="40539484" CHANGEID="192698457" CHANGEIDEND="0" TYPEID="8" VALUE="83:00:050002:477" UPDATEDATE="2021-04-29" STARTDATE="2021-04-29" ENDDATE="2079-06-06" />
<PARAM ID="719548916" OBJECTID="40530716" CHANGEID="192698634" CHANGEIDEND="0" TYPEID="8" VALUE="83:00:050002:438" UPDATEDATE="2021-04-29" STARTDATE="2021-04-29" ENDDATE="2079-06-06" />
<PARAM ID="719548922" OBJECTID="40535413" CHANGEID="192698640" CHANGEIDEND="0" TYPEID="8" VALUE="83:00:050002:430" UPDATEDATE="2021-04-29" STARTDATE="2021-04-29" ENDDATE="2079-06-06" />
</PARAMS>
解决方案
INSERT IGNORE
id
将根据任何唯一键(在您的情况下)跳过任何重复的行。
当你批量处理它们时,它们是什么INSERT
样子的?希望它在一个单一的有数千行INSERT
:
INSERT INTO t (...) VALUES (...), (...), ... ;
该技术可能是第二快的。
最快的方法是使用 500 万行的 CSV 文件和LOAD DATA
. 但这可能是最快的,因为您需要将数据转换为文件以写入以供读取。
或者,也许,最快的将是
LOAD XML LOCAL INFILE 'filename'
REPLACE
INTO TABLE ...
etc.
请参阅https://dev.mysql.com/doc/refman/8.0/en/load-xml.html 这将消除您解析 XML 的需要。(我没用过LOAD XML
,所以不知道速度有多快,也不知道你的XML标签能不能接受。如果需要,XSLT也许可以转换XML。)
你每天都运行这个负载吗?它会“取代”整个桌子吗?如果是这样,请执行以下操作:
CREATE TABLE new_t LIKE t;
load the data by whatever means
RENAME TABLE t TO old_t,
new_t TO t;
DROP TABLE old_t;
t
无论负载需要多长时间,停机时间几乎为零。
重复
XML中的重复项吗?如果它在 XML 中,“更好”的数据会排在最后吗? INSERT IGNORE
会照顾它。
还是介于新数据和旧数据之间?您是说每天要添加大约 4 999 900 行吗?请详细说明; 我不明白你的意思。
推荐阅读
- linux - 用户线程和内核线程如何与 linux 堆栈一起工作?
- react-native - 将本机设置动画值反应到动画
- php - 每次单击按钮时生成新的 id
- java - Using SharedPreferences with for loop
- c++ - C ++ 3D数组中的Valgrind错误
- bash - 使用 fmt 后执行变量替换
- javascript - How to add new column for each array with js
- angular - 创建嵌套组件 Angular 6
- ruby-on-rails - Rails 在开发中不通过 Mandrillapp 发送邮件(提供节点名或服务名)
- javascript - How can I get the same id (slides) as array through javascript without using **jquery**, **querySelectorAll()** Method or **querySelector()** Method?