あなただけ変更されたフィールドまたはすべてのフィールドを更新しますか?
-
19-08-2019 - |
質問
私はそれが既存のレコードを取得するレコードを更新するサーバーの時間価値がある場合は、フィールドをループは、変更のチェックのみ更新クエリで変更されたフィールドを入れて思ったんだけど? (私は、MySQL&PHPを使用しています。)
これを行うための主な理由は、変更ログのために、更新クエリのサイズを小さくすることです。通常、クエリは15個のフィールドを持っているかもしれませんが、唯一の2つのフィールドは、実際に変更されています。このクエリは、その後も、それだけで変更されたフィールドを含み、したがって、解析が容易になりますよう、ロギングのために使用することができます。
私の関心は、それが既存のレコードを取得するのにかかる時間です。
それともそれが更新さをフィールドのMySQLから取得する方法は何ですか?
解決
私はそれが変化する価値があると思う - しかし、挿入する前に選択をして、おそらく価値がない
。私は変更されているフィールドを更新し、それはActiveRecordのパターンを次の私のDbEntityクラスの動作の一部です。それは私が現在のレコードとオリジナルのレコードのレコードがロードされるたびに-simplyコピーを保持しているため、これを行うために少し余分なコストがかかります。
本当にパフォーマンス -理由は簡潔です。また、あなたは更新されたフィールドの古い値に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;
他のヒント
最も基本的なレベルでは、あなたは一般的に盲目的に別のユーザーが既にあなたが実際に変更されていませんでした、そのレコードの部分を更新した場合には、レコード全体を更新する必要はありません。あなたは盲目的と不彼らの更新を元に戻します。
私はあなたの現在のアルゴリズムは、あなたがされたフィールドを把握することを可能にするために、再度レコードを読み、その後、あなたが更新のために一度電流を読むつもりなら、更新がメモリ内で行うことを可能にする、汚れの書き込みにつながる可能性が信じています更新しました。背中の後ろのレコードは、のあなたのことを信じるようにあなたのアルゴリズムをリードし、そのフィールドを更新するために、1だった別のユーザーが更新された場合に何が起こるかということ?しかし主に、あなたは、単一の更新を実行するために二回すべてのレコードを読み取るために必要はありません。
あなたのデータは、多くの場合、競合が発生しない場合は、、あなたはそれを実装することを選択しない場合でも、楽観的ロックについて読んでから利益を得ることができます。
あなたがあなたのテーブルに更新タイムスタンプまたは増分更新番号の列を追加することにより、ここでは一つの方法を実装しました。 「、UPDATE ... WHERE UPDATENUM =-元番号を次に、あなたのサンドボックス/メモリ内にあなたが(OLDVALUE / NEWVALUE)変更したフィールドをを追跡することができ、あなたは自由にそれらのフィールドのために、そのレコードのために、あなたの更新SQLを発行することができます」(またはWHERE UPDATETS = - オリジナル・タイムスタンプ)、必ずお使いの更新SQLはまた、必要に応じて、UPDATENUMまたはUPDATETSをインクリメントすることを作ります。記録の影響を受けたその更新SQLでは0であるならば、あなたは他の誰かがすでにバックグラウンドでそのレコードを変更したことを知っているとあなたは今の競合を持っています。しかし、少なくとも、あなたが誰か他の人の変更を上書きしていない、とあなたは、新しいデータを再読み込みしたり、ユーザーが競合を解決することができます。
アプリケーション内の最も遅い点は、常にあなたのデータベースへのアクセスであることを行っているので、あなたはそれをスピードアップすることができれば、それは良い考えです。それはそれが本当にどのように大きなデータベース依存しており、記録があり、そしてどのように大きな彼らはそれがプログラムの項目が更新されているかどうかを確認するための努力の価値があるかどうかについて、に成長する可能性があると述べました。 データベースが小さく、アクセスはすでにかなり速い場合、それは時間の価値ではないかもしれません。速度を向上させることができる、そしてそれはあなたのロギングのための付加的な利益を与えた場合でも、それのために行く。