3

そのため、私はいくつかの調査を行っておりINSERT、サーバー上のテーブルに一意のクライアント名を挿入するステートメントを作成する必要があります。ただし、データベースのデフォルトの標準にはすでに数千のクライアントが含まれているため、新しいクライアントを挿入するときは、システムに追加する前に、それらがすでに存在するかどうかを確認する必要があります。

私の質問は、これを行うための最良/最速の方法は何でしょうか?クライアントテーブル(ASC順)で単純なselectクエリを実行し、結果に対してバイナリ検索などを実行する方がよいでしょうか。それとも、以下のようなSQLクエリを実行するだけでよいでしょうか。

IF NOT EXISTS (SELECT 1 FROM clients AS c WHERE c.clientname = ?)
BEGIN
  INSERT INTO clients (clientname, address, ...)
  VALUES (?, ?, ...)
END

これは遅い声明ですか?提出ごとに数百回挿入を実行しなければならない場合があります。

4

2 に答える 2

3

特定の列を一意にする場合は、UNIQUE制約を作成することをお勧めします。

ALTER TABLE clients ADD UNIQUE KEY (clientname);

次に、INSERTを実行しようとすると、一致する行がない場合は成功し、重複している場合は失敗します。SELECTは必要ありません。

于 2013-02-11T23:23:15.147 に答える
2

ディスク操作の観点からクエリでSQLのコストを計算することはそれほど珍しいことではありません(通常、ブロックの読み取り/書き込み(通常は8 KB)がコストの単位です)。(メモリ内-DBはこの考え方について何かを変える必要があります)。

数百、場合によっては数千のアイテムがあり、各アイテムが... 20バイトと言うと、データベース全体がディスク上の1つのブロック(400アイテム/ブロック)に収まる可能性があります。たぶんそれはさらに2、3ブロック必要ですが、万歳:それは無視できる少数です。このような小さなデータベースでは、データベースはおそらくデータベースのメモリキャッシュ内でくつろぎ、書き込みアクセスに対してのみ料金を支払う必要があります。データベースが大きくなるにつれて、インデックスがある場合、必要なブロックアクセスの数を指数関数的に減らすことができます。

アイテムがデータベースにすでに存在する場合、ソリューションとBillのソリューションの両方で書き込みアクセスが発生しないため、どちらも同じように高速である必要があります。

興味深い部分は次のとおりです。

提出ごとに数百回挿入を実行しなければならない場合があります。

つまり、同じブロックをディスクに何百回も書き込む可能性があります。これを1つのステップで実行できれば、より高速になります。ただし、この動作を可能にするSQL関数を認識していないため、これは確かに問題です。MySQLのINSERTは、単一のステートメントでいくつかの値を指定する方法を提供します。これはかなりのプラスになるかもしれませんが(MySQLがこの状況をどのように処理するかはわかりません)、MySQLに固有であり、移植性はありません。

処理を高速化するもう1つの方法は、変更したブロックがディスクに書き込まれるまで待たないことです。これは、通知なしにデータを失うリスクがありますが、パフォーマンスを大幅に向上させる可能性があります。繰り返しますが、これは使用するDBMSに固有です。たとえば、MySQLをInnoDBで使用する場合innodb_flush_log_at_trx_commit=0は、my.iniでオプションを設定して、この動作をアーカイブできます。

クライアントテーブル(ASC順)で単純なselectクエリを実行し、結果に対してバイナリ検索などを実行する方がよいでしょうか。

これにより、DBMSからクライアント(ネットワークプロトコルを介して通信する別のマシン上にある可能性があります)に大量のデータが不必要にコピーされます。これは小さなDBでも問題ありませんが、拡張性は高くありません。1回の操作でデータをディスクに保存するのに役立つ場合にのみ役立つ場合があります。

于 2013-02-11T23:55:07.107 に答える