需要MySQL INSERT - SELECT查询具有数百万条记录的表

时间:2009-03-19 16:13:59

标签: php mysql

我正试图向优化90GB +表迈出一步:

旧表

每天桌子抓住约。来自外部源的750,000条记录,并使用新日期将它们添加到表中。根据我的理解,这已经持续了三年。 97%的记录从一天到下一天都没有变化。

新表

我正在尝试浏览旧表(数百万条记录)并消除冗余,这可能会极大地缩小表格大小。

OLD_TABLE

  • 日期
  • RECORD_ID
  • data_field(真的很多字段,但为了示例)

new_table_index

  • 日期
  • index_id的

NEW_TABLE

  • index_id的
  • RECORD_ID
  • data_field中

我们浏览old_table中的每条记录时的逻辑

if(record_id不在new_table中)或(record_id在new_table中,但最新的条目有不同的data_field)

  

将其插入new_table并获取index_id

否则

  

从new_table_index

获取该record_id的最新条目index_id

总是

  

将index_id和date插入new_table_index

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

4 个答案:

答案 0 :(得分:5)

你可以用这个:

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

答案 1 :(得分:1)

首先,我认为不需要创建两个新表。如果你需要一个索引,那就是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创建索引。这样会非常快。

答案 2 :(得分:0)

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

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

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

答案 3 :(得分:0)

我最终使用了PHP和MySQL的混合体(在最初每个方向摆动太远之后):

  • 为以前的所有日期插入INSCL链接(使用INSERT - SELECT)
  • 针对上一天的比较PR,如果更改则插入(使用INSERT - SELECT)
  • INSERT LINK FOR NEWLY UPDATED PRs(使用SELECT - php foreach - UPDATE)
  • 每天添加新PR(使用INSERT - SELECT)
  • 为新PR插入链接(使用INSERT - SELECT)

仍需要使用php foreach循环完善一个,但在大多数情况下,这样做了!谢谢你的帮助!