【问题标题】:MySQL Performance INSERT or (partial) UPDATE if exists, what is best?MySQL Performance INSERT 或(部分)UPDATE 如果存在,什么是最好的?
【发布时间】:2021-12-02 17:32:29
【问题描述】:

如果您的 MySQL 数据库中有数十万行经常部分更新,我正在尝试找出“性能明智”的最佳选择。

插入...在重复密钥更新时

这是我目前的方法,我只是插入/更新整行而不检查实际更改的内容。

SELECT FROM ... WHERE ID=? 并让 PHP 检查是否找到了东西

这会是一个更好/更快的解决方案吗?所以我触发了一个 INSERT 语句,如果 ID 存在,我就更新整行。

或者也许我应该进一步检查(如果 ID 存在)并将找到的行与 PHP 中更新的行进行比较,然后只更新实际更改的值?

加载数据语句

到目前为止我从未使用过它,需要熟悉一下,但也许将它与 REPLACE 参数一起使用将是另一种可能加快整个导入速度的方法。

【问题讨论】:

    标签: php mysql performance insert


    【解决方案1】:

    从技术上讲,插入总是会更改索引行,从而导致引擎重新创建索引。但是,如果您的更新更改了索引,则它是一个静音点,因为索引仍将被重新制作。

    这里详细解释:https://stackoverflow.com/a/15412865/11005071

    【讨论】:

    • 索引是 BTree。当插入或更新行时,它们会被修改,而不是重建。将每个索引视为一个表格;在插入或更新表的 BTree 的一行时,需要对部分或全部索引的 BTree 进行类似的插入/更新。
    • 是的,我使用主索引并且在 UPDATE 时我不会覆盖 INDEX Colmun,只有其他 Clolumns 被更新,所以应该没问题。
    【解决方案2】:

    我会说您的第一种方法在效率和性能方面要好得多。使用简单、更短的代码行比编写多行查询更有效。 只要你达到你的预期目的。无论您使用第二种方法还是第一种方法,都不应成为您的主要动力。 您的真正目标应该是可读性、可维护性和效率。

    【讨论】:

    • 谢谢。是的,我当前的解决方案一切正常。只是不确定它是否有效。
    【解决方案3】:

    这样做:

    CREATE TEMPORARY TABLE t ...;
    LOAD DATA ... INTO t ...;
    INSERT INTO real_table
        SELECT ... FROM t
        ON DUPLICATE KEY UPDATE ... ;
    

    每一步都快速高效。 upsert 将根据需要更新现有行(基于唯一键)或添加新行。

    请注意,您有机会在数据到达 real_table 之前对其进行操作。允许您清理数据(如果需要)。 (使用 Replace 加载数据不会提供太多清理机会。)

    • “十万行”——没问题。
    • “部分更新”——它就是这样做的。
    • “检查是否找到了东西”——包括在内。

    我再说一遍:您必须有一个UNIQUE 键才能让进程知道哪些行需要更新而不是插入。

    一个粗略的性能经验法则:批量做某事(如我的建议)是一次做某事的 10 倍(如 Select + check if found)。

    【讨论】:

    • 谢谢,这是一个非常有趣的方法。我会试一试,在我的本地系统上试试这个。
    猜你喜欢
    • 2011-10-14
    • 2012-11-14
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多