DBA 最大的烦恼之一是处理重复数据。无论我们多么努力防范它,重复的东西总是能够找到进入表的方式。这是一个很大的问题,因为它可能影响应用程序视图(每个项目应该是唯一的),偏斜统计信息,并且在严重的情况下,会增加服务器的开销。
在这篇文章中,我们将学习如何识别 MySQL 中的重复数据,以及如何删除它们而不影响宝贵的有效数据。
重复类型
大多数重复记录是这两种不同类型的其中之一:重复含义和非唯一键。在这一篇文章,我们将处理重复含义的记录,而非唯一键将在下一篇文章处理。
当重复不是重复时
重复含义是最常见的重复类型。这情况是两个或多个字段的内容不一样,但它们的含义是一样的。你可以将其视为语义重复。
请看下面的表摘录:
movie_name | media |
--------------------------- | |
ACADEMY DINOSAUR | Theatre |
ACE GOLDFINGER | Television |
ADAPTATION HOLES | Theatre |
AFFAIR PREJUDICE | Theatre |
AFRICAN EGG | TV |
在 media 列中,“Television”和“TV”条目具有相同的含义,但表达方式不同。此问题通常是由使用自由文本输入引起的,使用有限选项的下拉列表是更好的选择。
这种重复类型可能非常难以处理,因为你无法使用 SELECT DISTINCT 语句排除重复项。
有两种方法可以解决这个问题:
- 使用 REPLACE() 选择数据,将不想要的值换成我们想要查看的值:
- 更新实际的表数据。将所有“TV”更新为“TELEVISION”。这是更新语句:
SELECT DISTINCT | movie_name, |
REPLACE(media, "TV", "TELEVISION") as media, | |
FROM films; |
UPDATE films |
SET media = REPLACE(media, "TV", "TELEVISION") |
WHERE media = "TV"; |
下面是我一个月前遇到的真实例子!
不知何故,我们的数据有一些不需要的卷曲撇号。请注意“O'BRIEN”和“O'BRIEN”条目:
first_name | last_name |
--------------------- | |
PENELOPE | GUINESS |
CONAN | O'BRIEN |
ED | CHASE |
JENNIFER | DAVIS |
CONAN | O'BRIEN |
我们可以像上面那样处理这个问题:
- 使用 REPLACE() 选择数据以使用常规单引号交换卷曲撇号,以便我们处理相同的字符:
- 更新实际的表数据。此语句将 last_name 列中的所有撇号更新为常规单引号:
SELECT DISTINCT | first_name, |
REPLACE(last_name, "'", "'") as last_name, | |
FROM actors | WHERE REPLACE(last_name, "'", "'") like "O'BRIEN"; |
UPDATE actors |
SET last_name = REPLACE(last_name, "'", "'") |
WHERE last_name like "%'%"; |
总结
无论是称作重复记录、相同数据、冗余数据,还是重复行,它们都是 DBA 生命中最大的祸根之一。然而,定期清除它们是至关重要的,以免生成错误的统计信息和使数据库用户感到困惑。