【问题标题】:Best Method For Quick Uploading of MYSQL Data with Normalization?使用规范化快速上传 MYSQL 数据的最佳方法?
【发布时间】:2020-07-28 20:18:33
【问题描述】:

这是我的情况。我得到了这样一个虚构的原始 csv 数据集,平均包含大约 100 万行。我会经常每 2 周获得一次这个数据集。

PROJECT, MD5SUM_VALUE, USAGE_NAME
A,132412341324asdf,Apple
B,13404892340asdf9,Banana
...

我有 mysql 表

PROJECT_TABLE (id, value),
MD5SUM_VALUE (id, value)
USAGE_NAME (id, name)
RECORD_TABLE (id, project_id, MD5SUM_id, USAGE_id)

我一直在使用脚本将 PROJECT 的值(使用 INSERT IGNORE)快速文件加载到 PROJECT_TABLE 中,并为 MD5SUM_VALUE 和 USAGE_NAME 使用类似的策略。

就目前而言,我已经了解了

  • USAGE_NAME 表的 17,115,235 个唯一行条目
  • MD5SUM_VALUE 表的 3,001,675 个唯一行条目
  • PROJECT 表的 200 个唯一行条目
  • RECORD_TABLE 表超过 59m 行

我上传 RECORD_TABLE 的速度似乎很慢。我需要进行查询以识别 id(project_id、MD5SUM_id、USAGE_id)并为每个原始 csv 文件执行 100 万次以上。

有没有更好的上传数据的方法?似乎没有办法快速上传这个数据部分?我应该采用不同的结构吗?

【问题讨论】:

  • 你能用LOAD DATA INFILE吗?
  • 我已经为填充 USAGE_NAME、MD5SUM_VALUE、PROJECT 表执行此操作。如何为 RECORD_TABLE 做到这一点?
  • 是的,没有脚本是不可能的,因为它必须找到 ID。
  • 通常的优化方法是INSERT INTO ... VALUES (...), (...), (...), ...。将数百行收集到一个查询中。

标签: mysql


【解决方案1】:

我会创建一个临时表并使用它来生成/查找 ID,然后插入到您的记录表中​​。假设您在 project_table、md5sum_table 和 usage_name 上有自动增量 id,并且在非 id 列上有唯一键:

create temporary table record_table_load (
    project varchar(255),
    project_id int,
    md5sum_value varchar(32),
    md5sum_id int,
    usage_name varchar(255),
    usage_id int
);
load data local infile 'foo.csv'
into table record_table_load
fields terminated by ',' enclosed by '"'
lines terminated by '\n'
ignore 1 lines
(project, md5sum_value, usage_name);
insert ignore into project_table (value) select distinct project from record_table_load;
insert ignore into md5sum_table (value) select distinct md5sum_value from record_table_load;
insert ignore into usage_name (name) select distinct usage_name from record_table_load;
update record_table_load join project_table on project_table.value=record_table_load.project set record_table_load.project_id=project_table.id;
update record_table_load join md5sum_table on md5sum_table.value=record_table_load.md5sum_value set record_table_load.md5sum_id=md5sum_table.id;
update record_table_load join usage_name on usage_name.name=record_table_load.usage_name set record_table_load.usage_id=usage_name.id;
insert into record_table (project_id, md5sum_id, usage_id) select project_id, md5sum_id, usage_id from record_table_load;
drop temporary table record_table_load;

如果您想避免使用 insert ignore 或者您对这些值没有唯一约束,请进行查找,然后插入任何未找到的值,然后再进行一次查找。

【讨论】:

  • @Gordon 这个答案对你有帮助吗?你试过了吗?
猜你喜欢
  • 1970-01-01
  • 2017-03-04
  • 2018-04-03
  • 2010-11-09
  • 2020-05-31
  • 1970-01-01
  • 1970-01-01
  • 2012-03-08
  • 2021-03-14
相关资源
最近更新 更多