我为我的一个客户开发了一个应用程序。他已经有了一个。所以我需要将他的实际数据库(SQL Server)转换为新的数据库(MySQL)。
SQL Server的某些表有超过10.000.000条记录。当我开始开发这个转换器时,我已经开始使用一些带有一些记录的表,所以我找到所有记录并保存到我的新MySQL数据库中。我将向您展示一些代码以便更好地理解(这只是一个例子)
<?php
namespace Converter\Model;
class PostConverter extends AbstractConverter
{
public function convert()
{
// this is the default connection, it is a mysql database (new application)
$em = $this->getEntityManager();
// this return an alternative connection to the sqlserver database (actual application)
$emAlternative = $this->getEntityManagerAlternative();
// instance of Converter\Repository\Post
$repository = $emAlternative->getRepository('Converter\Entity\Post');
$posts = $repository->findAll();
foreach ($posts as $post)
$post = new Post();
$post->setTitle($object->getTitle());
$em->persist($post);
}
$em->flush();
}
}
现在让我们假设Post表有超过10.000.000条记录。我不能只找到所有并迭代它。我会离开RAM。所以我做了类似的事。
存储库类:
<?php
namespace Converter\Repository;
class Posts extends \Doctrine\ORM\EntityRepository
{
public function findPosts($limit, $offset)
{
$qb = $this->createQueryBuilder('Post');
$qb->setMaxResults($limit);
$qb->setFirstResult($offset);
return $qb->getQuery->getResult();
}
}
在这里,我在while循环中只找到了几篇帖子。但它有点慢。我找不到更好的解决方案来改善性能
<?php
namespace Converter\Model;
class PostConverter extends AbstractConverter
{
public function convert()
{
$em = $this->getEntityManager();
$emAlternative = $this->getEntityManagerAlternative();
$repository = $emAlternative->getRepository('Converter\Entity\Post');
$limit = 1000;
while ($object = $repository->findPosts($limit, $offset) {
$post = new Post();
$post->setTitle($object->getTitle());
$em->persist($post);
$offset += $limit;
}
$em->flush();
}
}
我之前从未做过这样的事情。也许我会走错路。如果你们中的一些人能告诉我正确的话,我真的很感激,所以我可以继续这样做。
谢谢大家
我不能把一个转移到另一个。我在这里发布的只是一个例子,在转换中我必须在插入新数据库之前处理几乎所有数据。他的实际应用是在2005年开发的。数据库甚至没有标准化
答案 0 :(得分:5)
我目前正在构建一个类似问题的数据仓库系统。 Doctrine's own documentation正确说明:
ORM工具主要不适合大规模插入,更新或删除。每个RDBMS都有自己的,最有效的方式来处理此类操作,如果下面列出的选项不足以满足您的需要,我们建议您使用适用于这些批量操作的特定RDBMS工具。
我将如何处理它:
LIMIT
和主键&gt;批量查询最后的身份证使用OFFSET
查询通常较慢。gc_collect_cycles()
。如果您的代码被分解为对象,这是一种控制内存的简单方法。答案 1 :(得分:1)
如果源数据库(MSSQL)和目标数据库(MySQL)中的模式完全相似或类似,我将从一个数据库导出记录,然后使用纯数据库工具将它们导入另一个数据库。例如:
您可以使用shell脚本将所有这些粘合在一起并自动完成该过程。
此导出/导入将相当快,因为它发生在数据库层。这也是你可能获得的最快速度。
根据定义,从模型层移动整个数据库的速度会变慢:您将为每一行创建一个模型对象。也就是说,当源和目标模式发生分歧时,使用模型层是一种很好的方法,因为这样您就可以使用编程模型使一个模式适应另一个模式。
在您的具体示例中,如果unset($object)
循环底部while
,您可能会看到性能有所改善,但我怀疑内存是瓶颈。 (I / O是。)
答案 2 :(得分:1)
我之前和之后都尝试过这种方法,使用DBMS本机数据转储和恢复工具总是更快,而不是通过这样的框架处理记录。
我建议使用bcp
(https://msdn.microsoft.com/en-us/library/aa337544.aspx)等实用程序将数据转储出SQL Server,然后使用MySQL LOAD DATA
(http://dev.mysql.com/doc/refman/5.7/en/load-data.html )或mysqlimport
将数据导入MySQL。
如果您需要在将数据加载到MySQL之前重新构建数据,您可以通过在MySQL中设置新的数据结构,然后使用可以搜索的实用程序来操作要导入的数据。替换为sed
。
答案 3 :(得分:1)
首选使用DBMS本机数据转储 并通过恢复工具而不是处理记录 像这样的框架。 以CSV格式导出数据库并导入mysql。