有选择地从CSV读取到MySQL

时间:2015-02-18 03:50:30

标签: mysql csv architecture

这是一个两部分问题。

  • 第一个是我应该使用什么架构来解决以下问题?
  • 第二个是我应该使用什么命令?

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

方法1:我应该解析日志文件的每一行并将其插入数据库吗?
Con:日志条目必须是唯一的,因此我需要首先执行SELECT,检查LogItemID是否存在,然后检查是否存在。这似乎是一个很高的开销活动,在某些时候,这将每小时完成。

方法2:或者我是否使用LOAD DATA INFILE(我甚至可以在PHP中使用它?)并将日志文件加载到临时表中,然后将记录移动到永久表中?
Con:即使在这种方法中,我仍然需要经历SELECT循环,然后INSERT。

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

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

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

2 个答案:

答案 0 :(得分:1)

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

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

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

答案 1 :(得分:1)

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

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

我定义了UNIQUE键(约束),只使用INSERT IGNORE;这比运行单独的SELECT要快得多,并且比REPLACE更快。 (如果您的要求是您不需要更新现有行,您只需要"忽略"新行。

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?)如果我不需要更新,我只会存储这三个。我可以从durationstart_time计算end_time,但保存列可以让我添加索引,并在查找持续时间少于10分钟的查询中获得更好的性能,或者其他。如果没有该列,我将被迫评估表中每一行的表达式,并且在大型集合上会变得昂贵。