Вы обновляете только измененные поля или все поля?

StackOverflow https://stackoverflow.com/questions/459669

  •  19-08-2019
  •  | 
  •  

Вопрос

Мне интересно, стоит ли серверное время при обновлении записи для извлечения существующей записи, циклически просматривая поля, проверяя наличие изменений, и помещая только измененные поля в запрос на обновление? (Я использую MySQL & Amp; PHP.)

Основная причина для этого - уменьшить размер запроса на обновление для целей журнала изменений. Обычно запрос может иметь 15 полей, но только 2 поля на самом деле изменяются. Затем этот запрос также можно использовать для ведения журнала, поскольку он будет содержать только измененные поля и, следовательно, его легче будет проанализировать.

Меня беспокоит время, необходимое для извлечения существующей записи.

Или есть способ получить из MySQL какие поля он обновил?

Это было полезно?

Решение

Я думаю, что это стоит изменить, но, вероятно, не стоит делать выбор перед вставкой.

Я обновляю только поля, которые изменились, это часть работы моего класса DbEntity, которая следует шаблону activerecord. Это стоит немного больше, потому что я храню текущую запись и исходные записи, просто копируя их при загрузке записи.

Причины - краткость, а не производительность. Также вы можете проверить наличие одновременных изменений, добавив предложение where к старому значению обновленных полей и выдав соответствующую ошибку.

В методе записи / обновления:

$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);

В методе загрузки

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

Другие советы

На самом базовом уровне, если я правильно читаю ваш вопрос, вы обычно не хотите вслепую обновлять всю запись в случае, если другой пользователь уже обновил части этой записи, которые вы на самом деле не изменили. Вы бы слепо и без необходимости возвращали свои обновления.

Я полагаю, что ваш текущий алгоритм может привести к грязной записи, если вы собираетесь прочитать текущую версию один раз для обновления, разрешить обновления в памяти, а затем снова прочитать запись, чтобы выяснить, какие поля были обновлено. Что произойдет, если другой пользователь обновит эту запись за вашей спиной, заставив ваш алгоритм полагать, что именно вы обновили это поле? Но прежде всего вам не нужно читать каждую запись дважды, чтобы выполнить одно обновление.

Если ваши данные не часто приводят к конфликтам, вы можете извлечь пользу из чтения об оптимистической блокировке, даже если вы не решите ее реализовать.

Мы реализовали здесь один метод, с помощью которого вы добавляете отметку времени обновления или добавочный столбец числа обновлений в таблицу. Затем в своей песочнице / памяти вы можете отслеживать, какие поля вы изменили (oldvalue / newvalue), и вы можете свободно выдавать обновляющий SQL для этой записи для этих полей: & Quot; UPDATE ... WHERE UPDATENUM = & ПЕРВОНАЧАЛЬНО номер Quot; (или WHERE UPDATETS = the-original-timestamp), убедившись, что ваш SQL обновления также увеличивает UPDATENUM или UPDATETS, в зависимости от ситуации. Если записи, затронутые этим обновлением SQL, равны 0, вы знаете, что кто-то уже изменил эту запись в фоновом режиме, и у вас теперь есть конфликт. Но, по крайней мере, вы не перезаписали чужие изменения, и затем вы можете перечитать новые данные или разрешить пользователю разрешить конфликт.

Самым медленным моментом в вашем приложении всегда будет доступ к базе данных, поэтому, если вы можете ускорить его, это & # 8217, хорошая идея. Тем не менее, это действительно зависит от того, насколько велики ваша база данных и записи, и насколько велики они могут вырасти, в зависимости от того, стоит ли она & # 8217; чтобы программно проверить, обновились ли элементы. Если ваша база данных небольшая и доступ к ней уже достаточно быстрый, это может не стоить времени. Но если скорость может быть улучшена, и это дает вам дополнительное преимущество при ведении журнала, тогда сделайте это.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top