Pergunta

Eu estou querendo saber se vale a pena a hora do servidor ao atualizar um registro para recuperar o registro existente, percorrer os campos de verificação de alterações e só colocando os campos alterados na consulta atualização? (Estou usando o MySQL e PHP).

A principal razão para isso é reduzir o tamanho da consulta de actualização para efeitos de registo de mudança. Normalmente, a consulta pode ter 15 campos, mas apenas 2 campos estão realmente sendo alterado. Essa consulta pode igualmente ser usado para o registo, uma vez que irá conter apenas os campos alterados e, portanto, é mais fácil de analisar.

A minha preocupação é o tempo que leva para recuperar o registro existente.

Ou há uma maneira de recuperar a partir do MySQL quais campos lo atualizado?

Foi útil?

Solução

Eu acho que vale a pena mudar -. Mas provavelmente não vale a pena fazer uma escolha antes de inserção

Eu só atualizar os campos que foram alterados, é parte da operação da minha classe DbEntity que segue um padrão activerecord. Custa pouco mais para fazer isso, porque eu mantenha o registro atual e registros originais -Basta copiar sempre que um registro é carregado.

As razões são brevidade - não realmente o desempenho. Além disso, você pode verificar se há modificação concorrente, adicionando uma cláusula onde no valor antigo dos campos atualizados e jogue o erro apropriado.

No método de escrita / atualização:

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

No método de carga

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

Outras dicas

No nível mais básico, se eu estou lendo sua pergunta certa, você geralmente não quer atualizar cegamente todo o registro no caso de outro usuário já actualiza partes desse registro que você não tenha realmente mudado. Você iria cegamente e desnecessariamente reverter as suas alterações.

Eu acredito que o seu algoritmo atual pode levar a gravações sujos, se você estiver indo para ler a corrente de uma vez por atualização, permitir atualizações a serem feitas na memória, em seguida, ler o registro novamente para permitir que você descobrir quais os campos que têm sido Atualizada. O que acontece se outro usuário atualizada que recorde atrás de suas costas, levando o seu algoritmo para acreditar que você foi o único a atualizar esse campo? Mas principalmente, você não deve ter que ler cada registro duas vezes para realizar uma única atualização.

Se os dados não costuma resultar em conflitos, você pode beneficiar de ler sobre o bloqueio otimista, mesmo se você não escolher para implementá-lo.

Nós implementamos um método aqui em que você adicionar um update-timestamp ou uma coluna update-número incremental para a sua mesa. Então em seu sandbox / memória que você pode manter o controle de quais campos você tenha modificado (OldValue / newvalue), e você pode emitir livremente a sua actualização de SQL para esse registro para esses campos, "UPDATE ... ONDE UPDATENUM = o-original-número "(ou ONDE UPDATETS = a-original-timestamp), certificando-se de que a sua actualização de SQL também incrementa o UPDATENUM ou UPDATETS, conforme o caso. Se os registros afetados por esse SQL update é 0 você sabe que alguém já modificou esse registro em segundo plano e agora você tem um conflito. Mas pelo menos você fez não substituir outra pessoa muda, e então você pode reler os novos dados ou ter sua determinação de usuário do conflito.

O ponto mais lento em sua aplicação é sempre vai ser o seu acesso de banco de dados, por isso, se você pode acelerar isso, é uma boa idéia. Dito isso realmente depende o quão grande o seu banco de dados e registros são, e como eles são grandes probabilidades de crescer para, quanto a saber se vale a pena o esforço para programaticamente verificar se os itens foram atualizados. Se seu banco de dados é pequena e acesso já é bastante rápida, pode não valer a pena o tempo. Mas se a velocidade pode ser melhorada, e dá-lhe um benefício adicional para o seu registo, em seguida, ir para ele.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top