将关系检查和可能的不良数据逐行插入大量数据

我已经阅读了许多与此相似的文章和问题,但是已经发现了足够近的东西。

我在10列excel文件中有40,000行。 这里的数据是由纸张手工input的。

在我需要首先检查的文件中有两个主要的数字MO&Order。 由于这些是手工input,他们可能是错的。

我有2张桌子MO表

moID MO Order 3409 87234 23845 3410 84562 21342 etc... (38k rows) 

 printID moID user date printer 5 3409 Brad 01/24 printer1 34 3409 Brad 01/30 printer1 40 3410 Joe 01/31 printer1 etc... (9k ish and growing) 

处理:

我遍历每一行在我的C#应用​​程序,查询获取moID。 然后查询该作业是否已经存在,然后执行Insert。 如果无法findmoID,我查询logging可能的MO和顺序组合,以便稍后修复文件。

LINK QUERYS:

 curMOID = dbReports.MoNumbers.Where(r => r.moNumber == moNum && r.moOrder == orderNum).Select(c => c.id_moNumber).FirstOrDefault(); var printJobs = dbReports.PaperPrints.Where(q => q.id_moNumber == curMOID && q.printDate == printDate && q.rowExcelFile == curRow); if (printJobs.Where(q => q.printSize == null).Count() == 0) 

题:

我的moID查询需要〜250ms(申请时间,直接查询是〜0.075ms)。 与已经存在的和选项列表一样。 所以每一行都需要大约0.5秒才能完成。 在4万行是花5个多小时。 我必须每天与用户做这个。 有没有更好的方法来做到这一点或通过应用程序来加快查询速度。

是的,这是一个痛苦的,非常痛苦的做法。 有一个无痛的方式,更快,不涉及任何编码。

步骤1:将文件导出为CSV

第二步:使用LOAD DATA INFILE
使用它将数据加载到一个虚拟表中

LOAD DATA INFILE语句以非常高的速度从文本文件中读取行到表中

第3步:创build目标表

使它完全像虚拟表,但要确保你有不重复的列上的唯一索引。

你可以用CREATE TABLE LIKE语句来做到这一点

第4步:从温度select最终
是的,语法是

 INSERT IGNORE INTO destination SELECT * FROM tmp_table 

第5步:使用多表删除来清理tmp_table

在那里你有一个无法导入行的表。 而且你用一行代码在一分钟内完成了

除非我错误地将你使用的moID作为唯一键来确定你是否应该插入,所以:

你最好的select是开始批量查询。

取5000个moID并先查询它们,然后删除所有从5000退出的文件,然后执行剩余的批量插入操作。 冲洗并重复。

谢谢@ e4c5。 有我需要去的地方 想给我一个清晰的画面,我做了什么。 这曾经花了5 + HOURS,现在需要5秒。 我仍然使用C#程序来检查文件,创buildcsv并通过LOAD DATA INFILE发送它。

1) 创build一个CSV,每行包含所有表的信息。

  • 使用EPPLUS打开文件。 检查我想要的types的必填字段,如果出现错误,请停止,以便用户修复必填字段。

2) 创build了我想要插入的表的副本

  • 新表被称为StagePrintJob

3) 在我的情况下添加了MO和Order的值。

4) 将舞台表上的moID字段更改为默认值0

5) 使用LOAD DATA INFILE查询

  • 我截断(清除)表,所以我不必每次创build它。 只是重用。

      "TRUNCATE TABLE `" + table + "`; " + string.Format("LOAD DATA LOCAL INFILE '{0}' INTO TABLE `" + table + "` ", csvFullName).Replace(@"\", @"\\") + "FIELDS TERMINATED BY ',' " + "ENCLOSED BY '\"' " + "LINES TERMINATED BY '\\r\\n' " + "ignore 1 lines " + "(@printFix, moClient, moNumber, moOrder, printComment, printPrinter, printStatus, printUser, printIssue, printSolution, printQty, rowExcelFile, excelFile) " + "SET printDate = STR_TO_DATE(@printFix, '%m/%d/%Y'); " + "Call PaperPrintProcedure('" + printFileName + "')"; 
  • SET printDate是一种将我的datestring转换为mySQL可以理解的datestring的方法

  • 我在LOAD DATA LOCAL INFILE上使用了LOCAL,所以我可以在本地PC上使用一个文件,而不必先将它发送到mySQL服务器。

6) 创build一个存储过程(可以只运行命令)。 我做了一个更新查询检查我的价值对我想要的表。

  update StagePrint test inner join MoNumbers mo on test.moNumber = mo.moNumber && test.moOrder = mo.moOrder set test.id_moNumber = mo.id_moNumber; 

7) 我插入到我的实际表中的阶段行,只要它现在有一个MO的ID。

  • 我删除了与我的文件相同的行,因为在excel文件中没有好的ID,所以现在可以使用。

      DELETE FROM `PaperPrint` WHERE `excelFile` = printFileName; insert into PaperPrint(id_moNumber, printQty, printDate, printSize, printUser, printPrinter, printStatus, printIssue, printSolution, printComment, rowExcelFile, excelFile) select id_moNumber, printQty, printDate, printSize, printUser, printPrinter, printStatus, printIssue, printSolution, printComment, rowExcelFile, excelFile from StagePrint where StagePrint.id_moNumber <> 0; 

8) 在StagedTable中查询ID = 0任何logging,并修复或删除它们。