在加载到数据库或使用数据库之前规范化数据?

Normalize data before loading to database or use database?

我有一些数据想添加到现有的 mysql 数据库中。新数据可能有条目,这些条目已经保存在数据库中。由于我的某些专栏是唯一的,因此我得到了预期的 ER_DUP_ENTRY 错误。

批量插入

假设我想使用以下语句在 table mytablenames 列中保存“A”、“B”和“C”,而“A”是已经保存在那里了。

insert into mytable (names) values ("A"), ("B"), ("C");

有没有办法直接用bulk insert保存“B”和“C”而忽略“A”?或者我是否必须为每个新行构建一个 insert 语句?这就引出了另一个问题:

标准化数据

我是否应该确保在 实际 insert 声明之前 不上传重复的条目?在我的例子中,我需要 select 来自数据库的数据,消除重复项,然后执行上面看到的 insert。还是应该由数据库完成的任务?

如果您有阻止导入的 UNIQUE 约束,您有几种方法可以解决这个问题:

INSERT IGNORE INTO mytable ...

如果任何单独的行违反了 UNIQUE 约束,它们将被跳过。插入其他行。

REPLACE INTO mytable ...

如果有任何行违反了 UNIQUE 约束,则删除现有行,然后插入新行。请记住这样做的副作用,例如,如果您有外键在引用已删除行的删除时级联。或者如果 INSERT 生成一个新的自增 id。

INSERT INTO mytable ... ON DUPLICATE KEY UPDATE ...

更大的灵活性。这不会删除原始行,但允许您根据具体情况为您选择的任何列设置新值。另请参阅我对 "INSERT IGNORE" vs "INSERT ... ON DUPLICATE KEY UPDATE"

的回答

如果您想使用 mysqlimport 或 SQL 等效语句 LOAD DATA INFILE 的批量加载,有一些选项与 INSERT IGNORE 或 REPLACE 解决方案相匹配,但与 INSERT 不匹配...关于重复密钥更新解决方案。

阅读文档了解更多信息:

在某些情况下,我喜欢这样做:

  1. LOAD DATA 进入临时 table
  2. 清理数据
  3. 根据需要进行标准化。 (每列需要规范化 2 SQLs -- details
  4. 扩充摘要 table(s) (INSERT .. ON DUPLICATE KEY .. SELECT x, y, count(*), sum(z), .. GROUP BY x,y)
  5. 将干净的数据从临时 table 复制到实际 table(s) ("Fact" table)。 (INSERT [IGNORE] .. SELECT [DISTINCT] .. 或带 SELECT 的 IODKU。)

关于规范化的更多信息:

  • 我在任何交易之外进行。这样做更好的原因有很多。
  • 在最坏的情况下(由于其他失败),我偶尔会在规范化中抛出一个未使用的条目 table。没什么大不了的。
  • 不燃烧 AUTO_INCREMENT 个 ID(边缘情况除外)。
  • 非常快。

因为REPLACEDELETE加上INSERT所以几乎可以保证比IODKU差。但是,当行存在时,两者都会刻录 ID。

如果可能的话,不要"loop"逐行;而是找到 SQL 语句来一次处理它们。

根据具体情况,在第 2 步(如果有很多重复项)或第 5 步(重复项不常见)中删除重复项。