anthonyvipond / deduper-laravel
删除数据库表中的重复记录并重新映射其他表的外键
Requires
- anthonyvipond/simple-pdo: dev-master
- illuminate/database: ~4.2
- symfony/console: ~2.0
- symfony/process: 2.5.*
This package is not auto-updated.
Last update: 2022-02-01 12:42:08 UTC
README
目的
-
从数据库中删除重复记录,并在其他表中重新映射外键
-
您可以使用一个或多个列轻松定义行的唯一性
-
它在大表(10M+行)上也能很好地工作。
-
设计用于直接在生产表上运行
安装
建议通过 composer 进行。
编辑 composer.json 并添加
{
"require": {
"anthonyvipond/deduper": "dev-master"
}
}
安装依赖项
composer install
将 config/database.php.sample 复制到 config/database.php 并填写它
现在您应该能够从命令行(dlr文件存储位置)使用程序
php dlr
目的
###删除重复项的表####
假设您有以下 people 表
| id | name |
|---|---|
| 2 | Mary |
| 3 | Joseph |
| 5 | Mary |
| 6 | mary |
| 7 | Joseph |
php dlr dedupe tableName columnName
即。
php dlr dedupe people name
您的原始表不会被触及,您将得到这个表 people_uniques
| id | name |
|---|---|
| 2 | Mary |
| 3 | Joseph |
您还会得到这个表 people_removes
| id | name | new_id |
|---|---|---|
| 5 | Mary | null |
| 6 | Joseph | null |
| 7 | Joseph | null |
但是,如果您有一个表,其唯一性是通过三个列定义的怎么办?没问题。
| id | firstname | lastname | birthday |
|---|---|---|---|
| 2 | Mary | Smith | 1991-01-01 |
| 3 | Joseph | Parker | 1984-02-02 |
| 5 | Mary | Kate | 1981-08-08 |
| 6 | mary | kate | 2001-03-03 |
| 7 | Joseph | Parker | 1984-02-02 |
在第二个参数中使用 : 分隔列
php dlr dedupe people firstname:lastname:birthday
您将得到一个新的表 people_uniques
| id | firstname | lastname | birthday |
|---|---|---|---|
| 2 | Mary | Smith | 1991-01-01 |
| 3 | Joseph | Parker | 1984-02-02 |
| 5 | Mary | Kate | 1981-08-08 |
| 6 | mary | kate | 2001-03-03 |
以及另一个表 people_removes
| id | firstname | lastname | birthday | new_id |
|---|---|---|---|---|
| 7 | Joseph | Parker | 1984-02-02 | null |
您可以在不同的列上继续删除重复项。
您的 uniques 表将变小,而您的 removes 表将变大。
再次看看我们表格的最后阶段。
让我们根据新的规则继续删除重复项...
php dlr dedupe tableName firstname:lastname
现在 people_uniques 看起来是这样的
| id | firstname | lastname | birthday |
|---|---|---|---|
| 2 | Mary | Smith | 1991-01-01 |
| 3 | Joseph | Parker | 1984-02-02 |
| 5 | Mary | Kate | 1981-08-08 |
而 people_removes 看起来是这样的
| id | firstname | lastname | birthday | new_id |
|---|---|---|---|---|
| 7 | Joseph | Parker | 1984-02-02 | null |
| 6 | mary | kate | 2001-03-03 | null |
###链接####
下一步是将新ID添加到 removes 表中
php dlr link uniquesTable removesTable col1:col2:col3
即。
php dlr link people_uniques people_removes firstname:lastname:birthday
在执行链接时,您应该传入与您在删除时相同的列
如果您多次运行了删除命令,使用了不同的组合,您希望从最不具体到最具体地执行链接
即。
php dlr link people_uniques people_removes lastname:placeOfBirth
php dlr link people_uniques people_removes firstname:lastname:birthday
这样,更具体、质量更高的分组将覆盖质量较低的分组
如果您在多个规则上多次运行了 dedupe 命令,您可能会在运行 link 命令后留下少量未链接的记录
您可以通过传递 --fillerMode 选项用ID填充剩余的 new_id
检查每次运行后有多少 new_id 未重新映射
SELECT count(1) FROM table_removes WHERE new_id IS NULL;
即。
php dlr link people_uniques people_removes firstname:lastname --fillerMode=true
###重新映射####
运行 dedupe 后,您将拥有 table_uniques 和 table_removes,以及您的原始表。
重新映射要正常工作,需要存在 removes 表。
它不会被写入,但需要被读取。
假设您有以下 teams 表
| id | team |
|---|---|
| 2 | Knicks |
| 3 | Knicks |
| 4 | Lakers |
| 5 | Knicks |
以及需要重新映射的 champions 表
| id | team_id |
|---|---|
| 2 | 3 |
| 3 | 2 |
| 4 | 5 |
| 5 | 2 |
并且还有teams_uniques表(记住,你已经去重了)
| id | team |
|---|---|
| 2 | Knicks |
| 4 | Lakers |
还有这个用于重映射的teams_removes表
| id | team | new_id |
|---|---|---|
| 3 | Knicks | 2 |
| 5 | Knicks | 2 |
你现在可以重映射指向teams.id的外键
php dlr remap remapTable removesTable foreignKey
即。
php dlr remap champions teams_removes team_id
champions表现在看起来是这样的
| id | team_id |
|---|---|
| 2 | 2 |
| 3 | 2 |
| 4 | 2 |
| 5 | 2 |
在运行remap命令之前,你应该备份重映射表。
如果第一次重映射没有完成,只需再次运行。这不会造成任何伤害。
###替换新表###
回到people表的例子...
完成所有指向people.id的外键的重映射
现在,进行最后的致命一击!
RENAME TABLE table TO table_bak; RENAME TABLE table_uniques TO table; DROP TABLE table_bak -- optional
恭喜!你已经去重并重映射了你的表。
贡献指南
- 发布一个问题!
- 分支并拉取。
备注
- 暂时来说,你的原始表必须有一个
id列 - 仅适用于MySQL,但我愿意增加更多支持