我有一个案例,我需要每隔几分钟就将一个外部现有表与网站表同步。
我以前用一个简单的foreach来循环遍历每条记录,随着表的增长,它变得越来越慢,现在大约20.000条记录需要很长时间。
我想确保它创建一个新的记录或更新一个现有的。这是我得到的,但它似乎没有更新现有的行。
$no_of_data = RemoteUser::count(); // 20.000 (example)
$webUserData = array();
for ($i = 0; $i < $no_of_data; $i++) {
// I check the external user so i can match it.
$externalUser = RemoteUser::where('UserID', $i)
->first();
if($externalUser) {
$webUserData[$i]['username'] = $externalUser->username;
$webUserData[$i]['user_id'] = $externalUser->UserID;
}
}
$chunk_data = array_chunk($webUserData, 1000);
if (isset($chunk_data) && !empty($chunk_data)) {
foreach ($chunk_data as $chunk_data_val) {
\DB::table('WebUser')->updateOrInsert($chunk_data_val);
}
}
我是否遗漏了什么,或者这是错误的方法?
先谢了
1条答案
按热度按时间6yt4nkrj1#
在我看来,这将是一个理想的场景,使用触发器,而不是外部的方法。
如果您复制的数据不需要外部解释器的干预,并且数据保留在数据库的进程中(这意味着源知道数据,因为它是从同一个源提取的),则可以使用SQL或数据库支持的任何SQL扩展。
我没有您的表的模式,所以我只使用我可以从您的问题中提取的信息,将其缩小到简单的
user_id
和username
。我们需要改变这种情况,不再询问每个条目是否发生了更新或该行是否是新条目,而是让条目本身通知我们更新或插入。
我假设您使用的是MySQL,如果不是,SQL触发器在所有已知的支持SQL的数据库中都非常相似。
触发器结构具有如下简单布局:
其中
AFTER_UPDATE
是本例中要捕获的事件。因此,对于更新事件,我们希望知道已更改的数据
AFTER
,它已被更新,因此我们将使用AFTER UPDATE
触发器。因此,表的
AFTER UPDATE
将remote_user
称为原始表,将web_user
称为副本表,将user_id
和username
用作字段,如下所示变量
NEW
和OLD
在触发器中可用,其中NEW
拥有更新后的数据,OLD
拥有更新前的数据。对于已经插入的新用户,我们有相同的过程,我们只需要在
web_user
中创建条目。希望这能让你对如何使用SQL触发器有一个清晰的概念。有很多信息可以找到,指南,教程,你能想到的。SQL可能是一种由长胡子的老人创造的古老无聊的语言,但是了解它的特性会给你一个很大的优势,用简单的方法解决复杂的问题。