Pregunta

Me pregunto si vale la pena el tiempo del servidor al actualizar un registro para recuperar el registro existente, recorrer los campos buscando cambios y solo colocando los campos modificados en la consulta de actualización. (Estoy usando MySQL & amp; PHP.)

La razón principal para hacerlo es reducir el tamaño de la consulta de actualización para fines de registro de cambios. Normalmente, la consulta puede tener 15 campos, pero en realidad solo se están cambiando 2 campos. Esta consulta también se puede utilizar para iniciar sesión, ya que solo contendrá los campos modificados y, por lo tanto, es más fácil de analizar.

Mi preocupación es el tiempo que lleva recuperar el registro existente.

¿O hay alguna forma de recuperar de MySQL qué campos actualizó?

¿Fue útil?

Solución

Creo que vale la pena cambiarlo, pero probablemente no valga la pena hacer una selección antes de insertarlo.

Solo actualizo los campos que han cambiado, es parte de la operación de mi clase DbEntity que sigue un patrón de registro activo. Hacer esto cuesta un poco más porque tengo el registro actual y los registros originales, simplemente copie cada vez que se carga un registro.

Las razones son brevedad, no realmente rendimiento. También puede verificar la modificación concurrente agregando una cláusula where en el valor anterior de los campos actualizados y arrojando el error apropiado.

En el método de escritura / actualización:

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

En el método de carga

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

Otros consejos

En el nivel más básico, si estoy leyendo su pregunta correctamente, generalmente no desea actualizar a ciegas todo el registro en caso de que otro usuario ya haya actualizado partes de ese registro que en realidad no ha cambiado. Revertiría ciega e innecesariamente sus actualizaciones.

Creo que su algoritmo actual puede conducir a escrituras sucias, si va a leer la actual una vez para actualizar, permita que se realicen actualizaciones en la memoria, luego lea el registro nuevamente para que pueda averiguar qué campos han sido actualizado. ¿Qué sucede si otro usuario actualizó ese registro a sus espaldas, haciendo que su algoritmo crea que usted fue quien actualizó ese campo? Pero principalmente, no debería tener que leer cada registro dos veces para realizar una única actualización.

Si sus datos no suelen generar conflictos, puede beneficiarse al leer sobre el bloqueo optimista, incluso si no elige implementarlo.

Hemos implementado un método aquí mediante el cual agrega una marca de tiempo de actualización o una columna de número de actualización incremental a su tabla. Luego, en su sandbox / memoria, puede realizar un seguimiento de los campos que ha modificado (valor antiguo / valor nuevo), y puede emitir libremente su SQL de actualización para ese registro para esos campos, "ACTUALIZACIÓN ... DONDE ACTUALIZACIÓN = el-original- número " (o WHERE UPDATETS = the-original-timestamp), asegurándose de que su actualización SQL también incremente UPDATENUM o UPDATETS, según corresponda. Si los registros afectados por esa actualización SQL es 0, sabe que otra persona ya ha modificado ese registro en segundo plano y ahora tiene un conflicto. Pero al menos no sobrescribió los cambios de otra persona, y luego puede releer los nuevos datos o hacer que su usuario resuelva el conflicto.

El punto más lento en su aplicación siempre será el acceso a su base de datos, por lo que si puede acelerar eso, es una buena idea. Dicho esto, realmente depende de cuán grande sea su base de datos y registros, y cuán grandes puedan crecer, en cuanto a si vale la pena el esfuerzo de verificar mediante programación si los elementos se han actualizado. Si su base de datos es pequeña y el acceso ya es bastante rápido, puede que no valga la pena. Pero si se puede mejorar la velocidad y le brinda un beneficio adicional para su registro, entonces hágalo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top