我目前正在进行一个数据迁移--将一个非常大的(至少在我的新手体验中最大的)数据库迁移到另一个结构中。
事实上,我正在尝试将数据从一个非常老的、修改过的SMF数据库迁移到Flarum,作为一个学习步骤。
现在,我为所有帖子中的所有用户提供了SMF特定的用户in,现在我想将这些帖子迁移到Flarum。然而,问题是SMF用户is与Flarum用户is不一样。Flarum数据库中的那些是由AUTO_INCREMENT
属性创建的,因此不是相同的。
因此,为了翻译所有的文章,我使用了这个天真的循环,它正在工作,现在我正在考虑优化它。
while ($topic = $topics->fetch())
{
$posts = $db->query("SELECT * FROM smf_posts WHERE ID_TOPIC = @{$topic->ID_TOPIC}");
$posts->setFetchMode(PDO::FETCH_OBJ);
while ($post = $posts->fetch())
{
$user = $db2->query("SELECT id FROM flarum_users WHERE user_name = @{$post->posterName}");
$user = $user->fetch();
// Now insert the post
}
// Now insert the topic into discussions
}
现在,在我得到的数据集中总共有36,194个主题,这个迁移在我的机器上花费了整整30分钟的时间。
我知道我必须在一个查询中获取大量数据才能使其更快,但我只是没有看到它是如何实现的。我最初想加入这两个表,但它们位于不同的数据库中,更糟糕的是,它们位于不同的服务器中。
我该怎么做?
发布于 2018-04-08 18:13:57
首先,我想评论一下,是否值得优化一个您只需要做一次的任务。是否需要30分钟以上才能进行改进?如果是的话,那就不用费心了。只要在30分钟内运行它,并称之为成功。除非您需要多次运行此迁移。那也许是值得改进的。
在flarum中有多少用户?大概不超过几千人。您可以通过在开始处理主题之前执行一个查询来消除重复的内部查询,并在PHP关联数组中保留用户名到id的映射。
$userQuery = $db2->query("SELECT id, user_name FROM flarum_users");
$userData = $userQuery->fetchAll(PDO::FETCH_OBJ);
$userMap = [];
foreach ($userData as $user) {
$userMap[$user->user_name] = $user->id;
}
// then start processing topics
在循环中,您可以使用$userMap
更快地将用户名更改为id--只是一个关联数组查找,而不是运行另一个SQL查询。
while ($post = $posts->fetch())
{
$userId = $userMap[$post->posterName]; // no SQL query
// insert post
}
通常,这种技术称为环路-不变码运动。如果有在循环中运行的代码,但是无论运行多少次,结果都是相同的,那么为什么要在循环中运行呢?在循环之前执行一次,并将结果保存在某个变量中。
我也同意上面@Ben的评论:确保在smf_posts.ID_TOPIC
的数据库表上有一个索引,以便更快地选择帖子。
https://stackoverflow.com/questions/49719278
复制相似问题