首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >您是只更新已更改的字段,还是更新所有字段?

问您是只更新已更改的字段,还是更新所有字段?
EN

Stack Overflow用户
提问于 2009-01-19 23:54:48
回答 3查看 7.3K关注 0票数 10

我想知道,在更新记录以检索现有记录、遍历字段、检查更改并仅将更改的字段放入更新查询时,是否值得花费服务器时间?(我使用的是MySQL和PHP。)

这样做的主要原因是为了减少用于更改日志目的的更新查询的大小。通常情况下,查询可能有15个字段,但实际更改的字段只有2个。然后,此查询还可用于日志记录,因为它将只包含已更改的字段,因此更易于解析。

我关心的是检索现有记录所需的时间。

或者,有没有办法从MySQL中检索它更新了哪些字段?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-01-20 00:06:06

我认为这是值得更改的-但可能不值得在insert之前执行select。

我只更新已更改的字段,这是我的DbEntity类操作的一部分,它遵循活动记录模式。这样做的额外成本很低,因为每当加载记录时,我都会保存当前记录和原始记录,并进行-simply复制。

原因是简洁,而不是真正的性能。此外,还可以通过在更新后的字段的旧值上添加where子句来检查并发修改,并抛出相应的错误。

在write/update方法中:

代码语言:javascript
复制
$s1 = "";

foreach ($this->record as $key => $value)
{
    // only update fields that have been changed
    if ($value != $this->orig_record[$key])
    {
        $s1 .= $comma."`$key`='".mysql_real_escape_string($value)."'";
        $comma = ", ";
    }
}

$query = "UPDATE ".$this->table." SET $s1 where {$this->id_field}='".$this->get_keyfield()."'";
$query .= $this->extra_sql_update;
mysql_query($query);

$ar = mysql_affected_rows();
//
// the number of affected rows is actually those changed by the update operation, which will 
// either be zero, or 1. If the query affects more than one row then we have a problem.
if ($ar < 0 || $ar > 1)
{
    cbf_error("cbf_dbentity: {$this->table} :: only one row (not $ar) must be affected by an insert operation. $query",
      E_USER_ERROR);
}
else
{
    $new_id = $this->get_keyfield();

    GlobalEventBus::notify_all(new AuditLogSQL($this->table, "update", $query));

}

$this->orig_record = Array();

foreach ($this->record as $key => $value)
    $this->orig_record[$key] = $value;


//
// sanity check - ensure that what we have just written is actually there.

$this->load($new_id);

foreach ($this->orig_record as $key => $value)
    if (trim($this->record[$key]) != trim($value) 
        && (!$this->record[$key] == "0" && $value=""))
        cbf_error("cbf_dbentity: {$this->table} :: record differs during write after reload: field $key was \"$value\", after write it is now \"".
              $this->record[$key]."\"",E_USER_ERROR);

在load方法中

代码语言:javascript
复制
$this->orig_record = Array();
foreach ($this->record as $key => $value)
    $this->orig_record[$key] = $value;
票数 3
EN

Stack Overflow用户

发布于 2009-01-20 00:37:30

在最基本的层面上,如果我没看错您的问题,您通常不希望盲目地更新整个记录,以防其他用户已经更新了该记录的某些部分,而您实际上并没有更改。您会盲目地、不必要地恢复它们的更新。

我相信你当前的算法可能会导致脏写,如果你打算读取当前更新一次,允许在内存中进行更新,然后再次读取记录,以允许您找出哪些字段已经更新。如果另一个用户在你背后更新了该记录,导致你的算法相信你是更新该字段的人,会发生什么?但最重要的是,您不应该为了执行一次更新而读取每条记录两次。

如果您的数据不经常导致冲突,那么即使您不选择实现乐观锁定,您也可以从阅读有关乐观锁定的文章中受益。

我们在这里实现了一种方法,您可以通过该方法向表中添加一个update-timestamp或一个增量update-number列。然后,在您的沙箱/内存中,您可以跟踪您修改了哪些字段(oldvalue/newvalue),并且您可以自由地为这些字段的记录发出更新SQL,“UPDATENUM= the -original-number”(或者WHERE UPDATE...WHERE=the-original-timestamp),确保您的update SQL也适当地递增UPDATENUM或UPDATETS。如果受该更新SQL影响的记录为0,那么您就知道其他人已经在后台修改了该记录,您现在就有了冲突。但至少您没有覆盖其他人的更改,然后您可以重新读取新数据或让您的用户解决冲突。

票数 2
EN

Stack Overflow用户

发布于 2009-01-20 00:04:47

应用程序中最慢的点总是数据库访问,所以如果能加快速度,这是个好主意。也就是说,这实际上取决于您的数据库和记录有多大,以及它们可能增长到多大,至于是否值得通过编程来检查项目是否已更新。如果您的数据库很小,而且访问速度已经很快,那么可能不值得花时间。但是,如果速度可以提高,并且它为您的日志记录提供了额外的好处,那么就去尝试吧。

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

https://stackoverflow.com/questions/459669

复制
相关文章

相似问题

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