【问题标题】:Looking for Best Practice / Most Efficient Large SQL UPDATE / INSERT寻找最佳实践 / 最高效的大型 SQL 更新 / 插入
【发布时间】:2015-08-31 03:23:07
【问题描述】:

我正在寻找在 SQL 中实现大数据更新/插入的最佳方法。我的特殊情况是使用 MySQL 5.6,但理论上 SQL 的版本并不那么重要。

我正在下载一个大型 CSV 文件,其中填充了我需要转储到 MySQL 表中的数据。我的应用程序解析 CSV 并准备插入数据库。

我需要该表是每次传入的数据 (CSV) 的精确副本,而不是每次都添加到末尾。我正在寻找实现这一目标的最佳方法。

就我目前的 SQL 功能而言,我认为最好每次都简单地截断表并在数据通过时填充它,但我现在不确定这是否比索引列和使用 @987654324 更好@。

我的问题如下:

  • 最好是截断数据然后将数据插入空表,还是更好地找到数据差异并使用INSERT .. ON DUPLICATE KEY 仅更新应用程序发现数据差异的行

  • 在此之后,最好为每行数据格式化单个 SQL UPDATE / INSERT 查询并将它们发送到服务器。或者最好是格式化一个包含所有数据的非常大的查询,或者可能将较大的查询拆分为更易于管理的内容,以免服务器超时。

表中大约有 100k 行正在通过。目前,我在运行任何 INSERT 之前截断表。然后我将这些行分成 10 个不同的集合,并对数据库运行 10 个大型 INSERT 查询。我唯一担心的是我对表锁定知之甚少,并且不确定拆分这些是否真的能取得任何重大意义。

我在这里问这个问题的原因是因为我的监视器中的数据库使用图显示峰值,我认为拥有更稳定的数据流可能会更好,并试图弄清楚如何实现这一点。

我知道这只是磁盘写入,但所有图表看起来或多或少都相同,有很多尖峰且没有一致性。

【问题讨论】:

  • 您好,我建议您使用SQLyog,其中您可以将“结构和数据”或.CSV 格式的“数据”导入表格。建议先导入表结构,再导入数据,导入效率高。您还可以指定一次导入的数据块以避免连接丢失。
  • 感谢马修的建议。我实际上已经使用了 MySQL 工作台,它在将 CSV 导入表时具有相同的功能,但是该过程需要自动并内置到最终用户的程序中:) 一切都很好,下面的迈克尔(标记为答案)给了我我想要的需要。无论如何感谢您的有用建议!

标签: mysql database csv


【解决方案1】:

当您处理较大的csv 文件时,您应该使用LOAD DATA LOCAL INFILE 而不是插入/更新操作。您没有提到在插入之前您正在执行哪些解析操作,其中一些可能仅使用 LOAD DATA LOCAL INFILE 就可以实现。 TRUNCATE语句前的表。

下面是 LOAD DATA LOCAL INFILE 语句的示例,它在加载数据时忽略第一行(标题)并替换价格字段的逗号值,作为示例:

LOAD DATA LOCAL INFILE 'file.csv' 
INTO TABLE table 
CHARACTER SET UTF8 
FIELDS TERMINATED BY '\t'
ENCLOSED BY '\"' 
IGNORE 1 LINES 
(col1,col2,col3,colN, @price) 
SET price = REPLACE(@price,',','.');

正如您所说,您需要 csv 中的所有字段,只需在此处传递列的名称

(col1,col2,col3,colN, @price) 

与它们在 csv 中的顺序相同。这将比您编写的任何插入语句都要快。

要启用LOAD DATA LOCAL INFILE,需要在建立与数据库的连接时设置连接标志(在连接选项中直接设置选项,之后不起作用),例如使用 php PDO:

$dbh = new PDO('mysql:host=' . env('DB_HOST') . ';dbname=' . $database, env('DB_USERNAME'), env('DB_PASSWORD'), 
               [PDO::MYSQL_ATTR_LOCAL_INFILE => 1]);

【讨论】:

  • 太棒了,谢谢迈克尔,我会试一试:)
猜你喜欢
  • 2013-07-01
  • 1970-01-01
  • 2018-01-30
  • 2020-05-08
  • 1970-01-01
  • 1970-01-01
  • 2015-08-21
  • 2019-11-30
  • 1970-01-01
相关资源
最近更新 更多