2

同じ値でフィールドを更新したい場合。

たとえば、いくつかの列を持つテーブルT:A、B、C

このステートメントを実行する方が良いですか:

UPDATE `T` SET `B` = '0';

またはこれ:

UPDATE `T` SET `B` = '0' WHERE `B` <> '0';

私は最初のものがより速いかもしれないと思います(私がBにインデックスを持っているとしても)?

百万もの行がある場合、この更新を適用するのに時間がかかるのでしょうか、それとも本当に速いのでしょうか。

(私は既存の同様の質問を検索しようとします...しかし、私が使用したキーワードではかなり難しいです..あまりにも多くの異なる質問...私に良い質問を指摘することを躊躇しないでください...)

4

3 に答える 3

2

相対的なパフォーマンスは、の選択性に依存しWHERE B <> 0ます。

  • WHERE全表スキャンを実行する句はありません。

  • Bのインデックスは、全表スキャンを実行しません。

  • 選択性が低いBのインデックス。つまり、インデックスで見つかった行が更新のためにアドレス指定されるため、ヒット数が多いとランダムI/Oの割合が高くなります。ほとんどのシステムでは、これがパフォーマンスのボトルネックになります。選択性が非常に低い場合、全表スキャンの大部分が発生する可能性がありますが、シーケンシャルではなく疑似ランダムです。これは最悪のケースです。これは、クエリプランの生成中に最適化され、全表スキャンに置き換えられる可能性があります。

  • 高い選択性、つまり、ヒット数が少ない場合でもランダムI / Oが作成されますが、必要な場合はごくわずかです。これが最良のケースです。

したがって、更新が必要な行の割合に応じて、全表スキャン(= no WHERE)とターゲットアプローチ(=WHEREインデックス付き)のどちらかを選択する必要があります。

于 2012-08-31T21:32:22.250 に答える
1

パフォーマンスに加えて、実際のコンテキストの違いに注意する必要があります。

最初のオプションではMySQLがすべての行をロックする必要があり、2番目のオプションでは行のロックのみが必要B <> '0'です。InnoDBを使用すると、MySQLは、現在のインデックスがある場合にこれを実行できますB

同時トランザクションがある場合、投稿されたオプションは同じではありません。1つ目は、コミット後のすべての行がであるということを保証しb=0ます。b<>02番目は、コミット後にすべての行が0に設定されることを保証するだけです。ただし、別のトランザクションは、ある行b=0を別の値に同時に変更できます。

したがって、異なる動作を気にしない場合でも、同時トランザクションを実行する場合は、全体的なパフォーマンスを気にする必要があります。最初のオプションの方が高速である可能性がありますが、2番目のオプションの場合とは異なり、このテーブル行にアクセスする他のすべてのトランザクションをブロックします。

于 2012-09-02T11:24:01.550 に答える
1

私見、最初のものはより速くなります...

afaik mysqlは、値がターゲット値ではない列のみを自動的に更新します。したがって、「値」にDOUBLEチェックがあり、行を繰り返し処理します。2番目のアプローチでは、2回繰り返されます。インデックスがない場合は、where-clauseで確認するのはまったく適切ではありません。

于 2012-08-31T21:21:03.960 に答える