将数百万行从一个mysql表迁移到另一个mysql表作为Laravel 5中的副本

时间:2017-09-28 11:28:34

标签: php mysql

我正在开发一个内置laravel 5.3的项目。我有一个名为names的表。我有两列,idu_names。 table names包含4,550,000+行..我之前没有像这样的大数据。现在问题是这个表包含重复的记录。现在我被要求复制它,然后删除这个原始表并再次创建它。在导入之后,copied table进入一个新创建的原始表,并使用PHP的select distinct查询,因此每条记录在原始表中都是唯一的。我知道要用foreach loop执行此操作,但不知道如果记录的数量超过450万,会发生什么。以及memory_limitmax_exicution_time

需要哪些配置

1 个答案:

答案 0 :(得分:1)

问题

根据另一个表的内容创建一个包含唯一记录的表。

解决方案

我们将使用一些查询来迁移数据。

我们不会使用PHP或Laravel对数据做任何事情(因为我们不必)。没有理由让任何数据到达PHP。

直接查询数据库就足够了。如果您愿意,您仍然可以使用Laravel的迁移定义查询。

攻击计划

  1. 创建一个新的空表
  2. 添加unique索引,以便我们可以阻止重复记录
  3. 由于名称可能很长,我们会略微更改表格并添加hash列的name - 这会使我们的unique索引长20个字节,每一条记录。
  4. 为避免手动插入唯一键,我们会使用触发器
  5. 我们将使用INSERT INTO ... SELECT语法将数据从一个表移动到另一个表。我们将添加IGNORE子句以忽略由重复记录引起的错误。
  6. 代码

    创建表

    CREATE TABLE new_names LIKE `names`;
    

    更改表格以添加唯一键

    添加唯一键可防止重复进入。这样您就不必使用DISTINCT查询

    ALTER TABLE new_names ADD unique_id BINARY(20) DEFAULT NULL AFTER id;
    ALTER TABLE new_names ADD unique(unique_id);
    

    创建触发器,为我们更新unique_id

    DELIMITER $$
    
    CREATE
    
        TRIGGER `new_names_before_insert` BEFORE INSERT 
        ON `new_names`
        FOR EACH ROW BEGIN
            SET NEW.unique_id = UNHEX(SHA1(NEW.name));
        END$$
    
    DELIMITER ;
    

    迁移数据

    INSERT IGNORE INTO new_users SELECT * FROM users;
    

    IGNORE表示如果遇到重复,请忽略它并转到下一条记录。

    结论

    没有数据到达PHP,因此PHP不会成为瓶颈,您不必篡改其内存设置。

    由于唯一键,保证了唯一性。您永远不会在该表中有重复记录。

    此迁移将尽可能快,因为一切都发生在数据库服务器上。插入将是原子的(要么所有记录都进入,要么没有),因此它将快速提交到HDD。

    您的任务

    1. 相应地更改表名和列名
    2. 从MySQL termnal运行此命令或创建迁移并通过DB::raw()
    3. 执行此操作 祝你好运!