【问题标题】:Using MySQL unique index to prevent duplicates, instead of duplicate searching?使用 MySQL 唯一索引来防止重复,而不是重复搜索?
【发布时间】:2017-01-09 13:31:26
【问题描述】:

我有一个大表(500 万行),有一个名为“unique_id”的唯一标识符列

我正在通过 Node.js(node-mysql 绑定)运行 INSERT 查询,并且可能会尝试插入重复项。

两种解决方案是:

1) 将 'unique_id' 设为索引,并在 INSERT 之前检查整个数据库是否有重复记录:

'SELECT unique_id WHERE example = "'+unique_id+'" LIMIT 1'

2) 将 'unique_id' 设为 MySQL 中的唯一索引,并执行 INSERT 检查重复项。显然,任何重复都会导致错误并且不会被插入到表中。

我的直觉是解决方案 2) 更好,因为它可以防止在最坏情况 (500 万 - 1) 行中搜索重复项。

使用解决方案 2) 有什么缺点吗?

【问题讨论】:

    标签: mysql node.js indexing node-mysql


    【解决方案1】:

    为 unique_id 列定义唯一的主索引有很多优点:

    • 语义正确性 - 目前该名称不反映实际情况,因为您可以在名为“unique_id”的列中有重复项,
    • 自动生成唯一 ID - 您可以将此作业委托给数据库并避免 ID 冲突(如果您使用 UUID 而不是整数,这不会成为问题),
    • 速度增益 - 要成为可靠的解决方案 1 需要阻塞事务(在检查重复和插入行之间不应插入新行)。将此委托给 MySQL 会更有效率,
    • 遵循通用模式 - 这正是唯一索引和主索引的设计目的。您的解决方案将易于其他开发人员理解,
    • 代码更少。

    使用第二种解决方案,您可能需要处理插入重复项的尝试(除非您的唯一 ID 是由 MySQL 生成的)。

    自动递增的主索引: https://dev.mysql.com/doc/refman/5.7/en/example-auto-increment.html

    【讨论】:

      【解决方案2】:

      令人惊讶的是,它在性能方面几乎没有什么区别。搜索将使用(并要求)相同的索引。

      然而,性能差异很小,这有利于您的 (2) 解决方案。

      实际上,在 MySQL 中,您可以使用 IGNORE 关键字完全消除错误:

      INSERT IGNORE INTO ... VALUES (1, 2, 3), (4, 5, 6), (7, 8, 9)...;
      

      将始终成功(将跳过插入重复项)。如上所述,这允许在单个语句中插入多个值。

      您可能还对ON DUPLICATE KEY UPDATE 系列技巧感兴趣:-)。

      真正的区别,如 M.M.已经说明,是完整性。使用 UNIQUE 索引约束,您可以确定您的数据;否则,您需要在检查表和插入新元组之间锁定表,以避免其他人插入相同值的风险。


      如果数据的“重复性”需要大量的业务逻辑工作,那么您的 (1) 解决方案可能会占有一席之地,而这不能轻易地转化为 MySQL 约束。在这种情况下,你会

      • 锁定表,
      • 搜索候选重复项(假设您有 20 个),
      • 获取数据并验证它们是否是真正的候选者
      • 如果没有冲突,则插入新元组,
      • 释放锁。

      (可能有充分的理由认为,需要做如此复杂的旋转木马源于数据库设计中的一些错误。理想情况下你应该能够在 MySQL 中做所有事情. 但商业现实有时与理想相去甚远)。

      【讨论】:

        猜你喜欢
        • 2019-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-09
        • 2018-06-19
        • 2012-09-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多