【问题标题】:Need MySQL INSERT - SELECT query for tables with millions of records需要 MySQL INSERT - SELECT 查询具有数百万条记录的表
【发布时间】:2009-03-19 16:13:59
【问题描述】:

我正朝着优化 90GB+ 表迈出一步:

旧表

每天桌子抓取大约。来自外部来源的 750,000 条记录,并将它们添加到具有新日期的表中。据我了解,这种情况已经持续了三年。 97% 的记录不会从一天到另一天发生变化。

新建表格

我正在尝试遍历旧表(数百万条记录)并消除冗余,这可能会显着减小表大小。

旧表

  • 日期
  • record_id
  • data_field(确实有很多字段,但为了示例)

new_table_index

  • 日期
  • index_id

新表

  • index_id
  • record_id
  • 数据字段

遍历 old_table 中每条记录的逻辑

if (record_id is not in new_table) or (record_id is in new_table, but the latest entry has a different data_field)

将其插入 new_table 并获取 index_id

其他

从 new_table_index 中获取该 record_id 的最新条目 index_id

总是

将 index_id 和日期插入 new_table_index

对最佳方法有什么想法吗?我对 MySQL 不够先进,无法将所有这些放在一起。当我尝试用 PHP 编写脚本时,它耗尽了 3GB 的内存,然后失败了。其他建议或疑问???非常感谢!

【问题讨论】:

  • 能否请您发布一些 old_table 的示例数据以及您希望在 new_table 和 new_table_index 中获得什么?
  • 一条记录在多个日期的record_id是否一致?
  • 听起来就像我以前为浏览器行星游戏运行搜索引擎的时候。数以千计的行星 = 每次更新都会增加数以千计的新行。

标签: php mysql


【解决方案1】:

你可以用这个:

new_table
    * date
    * record_id (pk)
    * data_field


INSERT INTO new_table (date,record_id,data_field)
    SELECT date, record_id, data_field FROM old_table
        ON DUPLICATE KEY UPDATE date=old_table.data, data_field=old_table.data_field;

记录 id 是主键,同样的插入可以添加到 old_table 的插入下方。

见mySQL

【讨论】:

    【解决方案2】:

    首先,我认为没有必要创建两个新表。如果您需要索引,那么 MySQL 索引的用途就是:只需创建一个新表并为其date 字段设置索引。

    一个简单的脚本应该可以做到(假设 new_table index_id 自动递增):

    INSERT INTO new_table (date, record_id, data_field)
      SELECT
        date,
        record_id,
        data_field
      FROM
        old_table
      GROUP BY
        data_field
    

    在此之前,您可以考虑为所有涉及的 data_field 创建一个索引。这样它会非常快。

    【讨论】:

    • 对不起,让我澄清一下。 new_table_index 的原因是每个日期的每条记录仍然有一个条目(我们的一些查询需要它)。谢谢你的剧本。但是,这并没有真正考虑到我写下的逻辑-对此有何建议???谢谢!
    【解决方案3】:

    您可以在存储 LastModified 时间的表中添加一列。然后是 On Insert 或 On Update 触发器将该值设置为当前时间。您的数据移植过程可以简单地抓取 LastMotified 大于上一个数据端口的记录。

    如果您索引这个新字段,它应该比比较所有数据字段值快很多。

    如果您不需要这些检查的每小时粒度,那么您可以简单地将其设为日期字段类型而不是日期时间。该字段会更小,因此它们中的更多将保留在内存中,并且您的 where 过滤器会更快地发生。

    【讨论】:

    • 聪明的主意。不幸的是,old_table 已经创建并保留了三年的记录。因此,向其中添加 Modified 字段为时已晚。这是一次性转移所有日期到新表的方法。
    【解决方案4】:

    我最终使用了 PHP 和 MySQL 的混合体(在开始每种方式都太过分之后):

    • 为所有前一天 PR 插入前一天的链接(使用 INSERT - SELECT)
    • 比较前一天的 PR,如果更改则插入(使用 INSERT - SELECT)
    • 为新更新的 PR 插入链接(使用 SELECT - php foreach - UPDATE)
    • 每天添加新 PR(使用 INSERT - SELECT)
    • 为新 PR 插入链接(使用 INSERT - SELECT)

    仍然需要使用 php foreach 循环来完善它,但在大多数情况下,这已经成功了!感谢您的所有帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-10-04
      • 1970-01-01
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      • 2017-10-01
      • 1970-01-01
      • 2014-04-05
      相关资源
      最近更新 更多