【问题标题】:Migration of millions of rows from one mysql table to another as a copy in Laravel 5将数百万行从一个mysql表迁移到另一个作为Laravel 5中的副本
【发布时间】:2017-09-28 20:42:45
【问题描述】:

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

【问题讨论】:

标签: php mysql


【解决方案1】:

问题

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

解决方案

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

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

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

进攻计划

  1. 创建一个新的空表
  2. 添加一个unique 索引,这样我们就可以防止重复记录
  3. 由于名称可能很长,我们将稍微修改表并在 name 列中添加一个 hash - 这将使我们的 unique 索引长度为 20 字节,对于每条记录。
  4. 为避免手动插入唯一键,我们将使用触发器帮助自己
  5. 我们将使用INSERT INTO ... SELECT 语法将数据从一个表移动到另一个表。我们将添加IGNORE 子句来忽略重复记录导致的错误。

代码

创建表

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 终端运行它或创建迁移并通过 DB::raw() 执行它

祝你好运!

【讨论】:

    猜你喜欢
    • 2011-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多