2008-09-19 70 views
10

表1: 一切都包括厨房水槽。日期格式错误(年份最后,因此无法在该列上排序),以VARCHAR形式存储的数字,“街道”列中的完整地址,名字列中的名字和姓氏,姓氏列中的城市,地址不完整,行根据多年来发生变化的一些规则,将数据从一个字段移动到另一个字段,更新前面的行,重复记录,不完整的记录,垃圾记录......你的名字......哦,当然不是TIMESTAMP或PRIMARY KEY栏目在眼前。最终的MySQL遗留数据库噩梦

表2: 正常化的任何希望都在打开婴儿时出现在窗外。 对于表1中的每个条目和行更新,我们都有一行。所以像明天没有(800MB的价值)和像Phone1 Phone2 Phone3 Phone4这些列的复制品... Phone15(他们不叫电话,我用这个插图)foriegn的关键是......好好猜测。根据表1中的行的数据类型,有三种候选者:

表3: 它可能会变得更糟。哦,是的。 “外键是虚线,点,数字和字母的VARCHAR列组合!如果没有提供匹配(通常不会),那么类似产品代码的第二列应该是。与他们内部的数据无关,并且强制性的Phone1 Phone2 Phone3 Phone4 ... Phone15。从表1重复列,而不是TIMESTAMP或PRIMARY KEY列在望。

表4:被描述为工作在任何时刻都有可能发生变化,这与其他人相比是相似的。

在接近1米的行上,这是一个大混乱。幸运的是,这不是我的大混乱。不幸的是,我不得不把它从一个复合记录每个“客户”。

最初,我设计了Table1的四步翻译,添加了PRIMARY KEY并将所有日期转换为可排序格式。然后再执行几步查询来返回已过滤的数据,直到我有了Table1才能使用它从其他表中拉出来形成组合。经过几个星期的工作,我用一些技巧将这个过程变成了一步。所以现在我可以将我的应用程序指向混乱,并提出一个很好的合成数据清理表。幸运的是,我只需要其中一个电话号码用于我的目的,因此我的表正常化不是问题。

但是,这是真正的任务开始的地方,因为每天有数百名员工以您不想要的方式添加/更新/删除此数据库,并且每天晚上我都必须检索新的行。

由于任何表中的现有行都可以更改,并且由于没有TIMESTAMP ON UPDATE列,所以我将不得不使用日志来了解发生了什么。当然,这假定有一个二进制日志,但没有!

引入这个概念就像铅气球一样。我可能告诉他们,他们的孩子将不得不接受实验手术。他们并不是高科技......如果你没有收集到......

这种情况有点微妙,因为他们有我的公司非常需要的一些有价值的信息。我被一家大公司的高级管理人员(你知道他们是怎么做的)发送了“实现它”。

我想不出任何其他方式来处理夜间更新,而不是用另一个应用程序解析bin日志文件,以找出他们在白天对数据库做了什么,然后相应地组合我的表。我真的只需要看看他们的桌子1就可以知道该怎么办我的桌子了。其他表格只提供一些字段来清除记录。 (使用MASTER SLAVE不会有帮助,因为我将有一个副本的混乱。)

另一种方法是为其table1的每一行创建一个唯一的散列并构建一个散列表。然后,我每天晚上都会查看整个数据库,看看哈希是否匹配。如果他们不这样做,我会阅读该记录,并检查它是否存在于我的数据库中,如果存在,那么我会在数据库中更新它,如果它不是它的新记录,我会插入它。这是丑陋的,并不快,但解析二进制日志文件也不是很好。

我已经写了这个,以帮助弄清楚问题。经常告诉别人有助于澄清问题,使解决方案更加明显。在这种情况下,我只是头痛得厉害!

您的想法将不胜感激。

回答

1

日志文件(二进制日志)是我的第一个想法。如果你知道他们做了什么,你会不寒而栗。对于每一行,日志中会有很多条目添加和更改。它只是巨大的! 现在我决定了哈希方法。随着一些聪明的文件内存分页,这是相当快的。

1

难道你不能使用现有的代码访问这个数据库,并适应您的需求吗?当然,代码必须是可怕的,但它可能可能为你处理数据库结构,不是吗?你可以专心于完成你的工作,而不是当时考古学家。

0

您可能可以使用maatkit的mk-table-sync工具来同步临时数据库(毕竟,您的数据库只有非常小的数据库)。这将“复制混乱”

然后,您可以编写一些内容,在同步之后,执行各种查询以生成一组更清晰的表格,然后您可以报告。

我想这可以在没有性能问题的情况下每天完成。

这样做可以避免影响原始数据库。

我可以看到的唯一问题是如果某些表没有主键。

+0

*我可以看到的唯一问题是,如果有些表没有主键。* - 他们不会... 今天他们告诉我他们很少“更新/删除记录”。 ..无论这意味着什么。在与另一位数据库开发人员交谈时,似乎最好的(唯一)方法是正确执行此操作,即对每一行进行散列并将散列存储在表中。然后,每天晚上重新阅读整个数据库,为每一行做一个散列,然后做一个简单的比较。我只是无法看到它的方式。试图破译二进制日志文件只会充满危险。 – 2008-09-20 01:55:22

2

我不是MySQL的人,所以这是从左场出来。

但我认为日志文件可能是答案。谢谢你,你真的只需要知道日志中的两件事情。

您需要record/rowid,并且您需要该操作。

在大多数数据库中,我假定MySQL,每行都有一个隐式列,比如rowid或recordid,或者其他。这是数据库使用的内部行号。这是您的“免费”主键。

接下来,您需要操作。值得注意的是它是否是对行的插入,更新或删除操作。

按时间顺序合并所有这些信息,然后遍历它。

对于每个插入/更新,您从原始数据库中选择行,然后在目标数据库中插入/更新该行。如果是删除,则删除该行。

你不关心字段值,它们并不重要。做整行。

你希望不应该“解析”二进制日志文件,MySQL已经必须有例程来做到这一点,你只需要找到并找出如何使用它们(甚至可能有一些方便的“转储日志”你可以使用的工具)。

这可以让您保持系统非常简单,它应该仅取决于您在一天中的实际活动,而不是总数据库大小。最后,你可以通过使它变得“更聪明”来优化它。例如,也许他们插入一行,然后更新它,然后删除它。你会知道你可以完全忽略你的重播中的那一行。

显然这需要一些奥术知识才能真正阅读日志文件,但其余的应该是直截了当的。我想认为日志文件也是时间戳的,所以你可以知道在“从今天开始”的行上工作,或者你想要的任何日期范围。