【问题标题】:Tricky MySQL Batch Design棘手的 MySQL 批处理设计
【发布时间】:2012-02-07 19:07:57
【问题描述】:

我有一个爬虫,它可以访问许多站点并查找即将发生的事件以及另一个实际上应该将它们放入数据库的脚本。目前,插入数据库是我的瓶颈,我需要一种比现在更快的方法来批处理查询。

让这件事变得棘手的是,单个事件包含三个表中的数据,这些表彼此具有键。要插入单个事件,我插入位置或获取该位置已经存在的 id,然后插入实际的事件文本和其他数据,或者如果事件 id 已经存在(有些是每周重复等),最后插入带有位置和事件 ID 的日期。

我不能使用 REPLACE INTO,因为它会孤立具有相同键的旧数据。我在Tricky MySQL Batch Query 中询问了这个问题,但如果 TLDR 的结果是我必须检查哪些键已经存在,预先分配那些不存在的键,然后为每个表进行一次插入(即在 php 中完成大部分工作) .这很好,但问题是,如果一次处理多个批次,它们都可以选择预分配相同的键,然后相互覆盖。无论如何我可以回到这个解决方案吗?这些批次必须能够并行工作。

我现在所拥有的是,我只是在批处理期间关闭索引并分别插入每个事件,但我需要更快的东西。任何想法都会对这个相当棘手的问题有所帮助。 (这些表现在是 InnoDB ......事务可以帮助解决这些问题吗?)

【问题讨论】:

    标签: php mysql performance innodb batch-processing


    【解决方案1】:

    我建议从 Mysql Lock Tables 开始,您可以使用它来防止其他会话在您插入数据时写入表。

    例如,您可能会做类似的事情

    mysql_connect("localhost","root","password");
    mysql_select_db("EventsDB");
    mysql_query("LOCK TABLE events WRITE");
    $firstEntryIndex = mysql_insert_id() + 1;
    /*Do stuff*/
    ...
    mysql_query("UNLOCK TABLES);
    

    上面做了两件事。首先,它锁定表,防止其他会话写入它,直到您完成并运行解锁语句为止。第二件事是 $firstEntryIndex;这是将在任何后续插入查询中使用的第一个键值。

    【讨论】:

    • 嗯,这肯定会解决数据能够相互覆盖的问题,但整个目标是让一切变得更快,因此一次只将其限制为一个进程似乎是一种倒退。
    • 它不会将进程限制为单个实例,只是确保您可以基于单个密钥进行处理,而不会有数据丢失/损坏的风险。无论您使用哪种方法,都不太可能在不影响效率的情况下提供锁表的预处理和安全性方面的灵活性。
    猜你喜欢
    • 2012-02-12
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 2016-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多