首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将数据库内容从一个非常糟糕的结构迁移到一个非常逻辑的结构的最佳实践?

将数据库内容从一个非常糟糕的结构迁移到一个非常逻辑的结构的最佳实践?
EN

Stack Overflow用户
提问于 2011-08-07 14:44:01
回答 5查看 4.5K关注 0票数 17

TL博士:在一个结构非常糟糕的数据库之间迁移大量数据的最佳方法是什么(大量重复列、没有相互关系和重复的数据),迁移到另一个高度组织性和关系性结构?-很抱歉长时间阅读!

我最近做了一项非常复杂的工作。它正在改写整个公司的基于网络的IT平台。恐怕我不能给出太多的细节,因为我们不能让老开发商知道(他是唯一一个知道如何做像发票生成这样的重要事情的人,并且要求越来越多的钱)。

主要的问题是,整个web平台(所有员工和所有客户都使用)是由一个技术水平低于业余水平的人编写的。它由大约300个单独的代码文件组成。没有模板库-所有这些都是硬编码到每个文件中。没有逻辑的数据库结构--实际上是在他走的时候编造出来的。没有保安-太令人震惊了。无论如何,我们将在三个月的时间内重写整个平台。

然而,老板说,在直播的第一天早上,任何地方都不能丢失客户数据。整个数据库内容必须直接复制。目前数据库的结构非常糟糕,几乎不可能使用,但本周我们将(尝试!)编写一些脚本,将其迁移到我们新的、高度关系的结构中,这更符合逻辑。问题是,做这件事的最好方法是什么?

地址就是一个例子。在旧数据库中,大约有12个表使用了地址(总共44个表.)。在我们的系统中,我们有一个addresses表,它将被其他表(例如address_id)交叉引用,以保持事物的清洁。主要的问题是,在他的大约一半的表中,地址存储为line1line2towncity等,这很好,但在另一半中,他只有一个address字段来存储整个东西!

第二个例子是日期--在一些表中,他有秒开始的日期,而在另一些表中,则是MySQL NOW() dates,而在另一些表中,他实际上将其存储在每行6列中-- yearmonthdayhourminutesecond .

要解决这个问题,有什么好办法呢?我们应该看看ours?

  • From 我们的表,并计算出我们需要从哪里提取--他的E 227E 128数据从我们的角度来看,还是应该反向看E 229E 130他的E 231/code>E 132表,并计算出他的数据需要进入到哪个位置才能进入编程的观点,我们应该如何解决这个问题呢?很多数据都需要动态格式化(例如日期),因此我们正在考虑一次只提取一行数据,对其进行正确的格式化,然后将其重新插入脚本中的正确位置。
  • Speed和查询效率对我们来说不是问题,因为我们只需要在本地机器上运行一次(测试后)。当SQL转储时,他的数据库目前是800 of,但是很多这些都是他无用的测试数据,或者完全没有必要。

对解决这个问题的最佳方法有什么想法吗?作为参考,我们的系统将用PHP重新编写,所以任何基于PHP的建议都会很好。该数据库目前(而且仍将是)在MySQL中。

EN

回答 5

Stack Overflow用户

发布于 2011-08-07 16:42:39

这里没有解决办法。没有魔法。只是很努力的工作。

你有了你的新模型,唯一的方法就是把每个表分别地、逻辑地、纸面上、白板上等转换成新的模型。

您需要处理的不仅仅是简单的格式化问题。您还需要处理数据复制问题。如果您有12个有地址的表,但只有一个客户端,哪个地址获胜?

仅凭这个决定就可以简化许多处理(例如,您可以忽略其他地址,而不是从主客户端记录链接的一个有福地址)。

这就引出了最后的问题。在转换过程中“不丢失任何数据”。

这很可能是从第一天开始的,这取决于“不丢失任何数据”意味着什么。例如,如果您正在丢弃地址,就会有数据丢失。当然,每个组件“都有一个地址”,但不一定是以前的地址。以前他们可能都是一样的,但也可能不是。会很乱的。

一旦您完成了映射和其他过程,在大多数语言中编写它们都是非常简单的。脚本语言在这方面工作得很好。您可以将每个表按“原样”大容量加载到一个新的DB中,并编写存储过程来执行转换。不管你熟悉什么。您的转换可能是几个步骤,而这些代码中的大部分可能只是为了方便转换而“一次性”转换。

这将是乏味的。这些东西一直都是。细节太多了。所有的原因,这是一个可怕的制度是为什么转换将是可怕的。如果你没有花足够的时间来完成它,那就不要感到惊讶。

最后,如果您有大量的数据,您可能有一些时间限制来处理,如果您不能在业务关闭时间(周末,晚上什么)。如果你是在更新数据的过程中这样做的话,那将是另一个水壶。如果可能的话,我强烈建议不要这么做。

票数 10
EN

Stack Overflow用户

发布于 2011-08-07 16:41:28

最近,我做了几次更大的迁移,在此期间,我逐渐为自己开发了一些实用的最佳实践。这并不是什么突破性的东西,但你可能会发现其中一些很有帮助:

一般提示

在开始工作之前,请确保了解现有的数据模型和对新版本系统的需求。

  • 尽可能地设计新的数据库模式,并尽量避免因需要迁移旧内容而给自己造成压力。
  • 使用一个具有可靠ORM的框架。开发新版本不仅更容易,而且迁移也更容易。

迁移

处理数据迁移的代码将在一段时间内成为项目的一部分,因此将其指定为包/文件夹(即legacy)是一个好主意。在这个包中,保存与遗留系统相关的转换脚本和其他文件。过了一段时间,您将能够通过简单的rm -rf legacy来摆脱它。

脚本应该以小的步骤完成转换。最好是多次遍历一个表,并保持这些步骤的小、简单和可调试,而不是有一个大脚本来完成所有事情,尽管速度更快。

这也是一个好主意,在它自己的事务中运行每一个步骤,只有在它成功完成之后才提交,这样当一个步骤失败时,您就不需要重新运行整个迁移了。

应该可以使用命令行中的一个命令来运行整个迁移过程以及特定步骤或步骤组,因为在达到最终版本之前,您将多次运行它,因此越自动化越好。

主脚本(即legacy/bin/full-migration)应该执行整个过程(即获取遗留产品DB的新副本,(重新)在其中创建新的DB和表,运行整个迁移),并且它应该与在生产服务器中部署新版本后(只有不同的配置)中的最终运行过程完全相同。它将允许您在开发环境中对其进行彻底的测试。

由于转换可能需要很长时间,所以记录每个操作(普通的print action + object_id应该做的)是有益的。通常,有几个行有一些意外的差异,它们会导致脚本崩溃或导致引用完整性错误。在这种情况下,很好地了解了它是哪个对象,这样您就可以立即转到DB,检查数据,相应地更新脚本,然后再次运行失败的步骤。

事实证明,对我非常有用的一件事是使用ORM为遗留数据库表定义模型类。我在Django中做了几次这样的工作,它支持多个数据库连接和每个模型的路由,因此我能够编写大致类似于以下(Python)的脚本:

代码语言:javascript
复制
from legacy import models as old
from catalog import models as new

# Loop through all products from the legacy DB
for old_product in old.Product.objects.all():  
    # Create an instance of the new product model class
    new_product = new.Product() 
    # Copy and modify attributes as needed
    new_product.name = old_product.product_name.strip()
    # ...
    # Save it to the new database
    new_product.save()

此外,新模式的限制性越强,就越好(即。(在可能的情况下不为空,外键检查等)因为它将帮助您了解关于旧模式的假设是错误的,并防止错误的数据进入新系统(InnoDB作为MySQL的后端是个好主意)。

其他良好做法是在可能的情况下保留新数据库中的旧主键。如果迁移后在新数据中看到了一些奇怪的东西,您可以返回并通过遗留系统中的ID查找该项。

票数 6
EN

Stack Overflow用户

发布于 2011-08-07 15:29:51

重写的第一步是充分理解当前的数据结构和运行在其上的代码。可能有一些数据看起来是多余的,但是由于一些奇怪的原因,代码要求它这样做。设计不好吗?也许吧--但一定要确保您完全理解编写或访问数据的每一段代码,这样您就可以确定哪些代码可以删除,哪些必须重构,哪些必须按原样保留。

工具可以帮助过程自动化--但是如果不深入掌握当前系统,它们可以将您自动化到一个角落。

我将设计新的数据结构,编写脚本将旧结构转换为新结构,然后测试功能。如果出现问题,请更改新结构和/或导入脚本,然后再次运行数据传输例程,并重复整个过程,直到确保没有任何数据或功能丢失。此时,安排一个关闭旧系统的日期,进行数据迁移,然后打开新系统。

当然,这一切中缺少的是对用户进行新的/改进的系统的培训。这是至关重要的!不要把它排除在你的计划之外,否则最好的新的、闪亮的、改进的系统会因为用户的不高兴而沉没。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6973452

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档