有选择地从 CSV 读取到 MySQL

Selectively reading from CSV to MySQL

这是一个由两部分组成的问题。

我有一些日志文件要读入数据库。日志文件包含不必要的字段(因为它们可以从其他字段计算)。

方法一:我是否应该解析日志文件的每一行并将其插入数据库?
Con: 日志条目必须是唯一的,所以我需要先做一个 SELECT,检查 LogItemID 是否存在,如果不存在,然后插入。这似乎是一个很高的开销 activity,并且在某些时候这将按小时进行。

方法 2: 或者我使用 LOAD DATA INFILE(我什至可以在 PHP 中使用它吗?)并将日志文件加载到临时 table,然后将记录移动到永久 table?
Con: 即使在这种方法中,我仍然必须经历 SELECT 的循环,然后插入。

方法三:或者有更好的方法吗?是否有命令将记录从一个 table 批量复制到另一个具有选定字段的记录?只要 LogItemID 设置为 UNIQUE , REPLACE INTO .... ON DUPLICATE UPDATE 工作(如果该项目存在,我不想更新,只是忽略)?无论哪种方式,我都需要扔掉无关的字段。这些方法中哪种更好?不仅更容易,而且从编写良好的可扩展代码的角度来看?

P.S。不相关,但这里的架构问题的一部分是...... 如果我有 StartTime、EndTime 和 Interval (EndTime-StartTime),我应该保留哪个 - 前两个还是间隔?为什么?

编辑:澄清为什么我不想存储所有三个字段 - 问题当然是规范化,因此不是好的做法。出于审计原因,也许我会存储它们。也许在另一个table? TIA

您可以使用 perl 解析出您要加载的 csv 字段的子集,然后使用命令 'uniq' 删除重复项,然后使用 LOAD DATA INFILE 加载结果。

通常将数据加载到临时table,然后遍历比提前预处理数据慢。至于 LogItemID,如果将其设置为唯一,则在加载后续匹配行时插入应该会失败。

在决定存储 StartTime+Interval(通常称为 Duration)或 StartTime 和 EndTime 时,这实际上取决于您计划如何使用生成的数据库 table。如果您存储持续时间并不断计算结束时间,那么只存储 start/end 可能会更好。如果您认为持续时间将被常用,请存储它。根据您可能决定只存储所有三个的数据库有多大,多一个字段可能不会增加太多开销。

LOAD DATA INFILE 比 运行 单个插入要快得多。

您可以加​​载到一个单独的临时 table,然后 运行 一个 INSERT ... SELECT 从临时 table 加载到您的实际商店。但不清楚为什么需要这样做。对于 "skip" CSV 中的某些字段,只需将它们分配给虚拟用户定义变量。无需将这些字段加载到临时 table。

我会定义一个 UNIQUE 键(约束)并只使用 INSERT IGNORE;这将比 运行 一个单独的 SELECT 快很多,而且比 REPLACE 快得多。 (如果您的要求是您不需要更新现有行,那么您只想 "ignore" 新行。

LOAD DATA INFILE 'my.csv'
IGNORE
INTO TABLE mytable
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY '\n'
( mycol
, @dummy2
, @dummy3
, @mm_dd_yyyy
, somecol 
)
SET mydatecol = STR_TO_DATE(@mm_dd_yyyy,'%m-%d-%Y')

如果您有 startendduration,请继续并存储所有三个。那里有冗余,主要问题是性能和更新异常。 (如果你更新 end,你是否也应该更新 duration?)如果我不需要更新,我会存储所有三个。我可以从 start_timeend_time 计算 duration,但是存储列将允许我添加索引,并在查找持续时间小于 10 分钟或其他任何时间的查询时获得更好的性能.如果没有该列,我将不得不为 table 中的每一行计算一个表达式,这在大型集上会变得很昂贵。