7

私は Web アプリを開発しており、現在 SQL Server 2008 を使用しています。しかし、パフォーマンスを向上させるために、別のデータベース (simpledb) に移行することを検討しています。

1 時間ごとに最大 10000 行を 1 つの特定のテーブルに挿入するバックグラウンド プロセスがあります。そのテーブルは、Web アプリケーションでデータを表示するためにも読み取られます。バックグラウンド プロセスが実行されると、データベース接続がタイムアウトするため、Web アプリは使用できなくなります。

その結果、パフォーマンスを向上させるために amazon の simpledb に移行することを考えています。Amazon の SimpleDB はこのユース ケースに最適化されていますか? そうでない場合、使用できる別の解決策はありますか?

4

4 に答える 4

20

問題は、使用している分離レベルです。変更しない限り、SQL Server (および他の多くのデータベース) は、コミットされていない読み取りをブロックするモードで動作します。代わりにMVCCを使用するようにSQL Serverを変更したい(Oracleのデフォルト。MySQLとSQL Serverの両方にもあります)。問題は解決します。

SET TRANSACTION ISOLATION LEVEL (Transact-SQL)から:

コミットされた読み取り

ステートメントは、他のトランザクションによって変更されたがコミットされていないデータを読み取ることができないことを指定します。これにより、ダーティ リードが防止されます。データは、現在のトランザクション内の個々のステートメント間で他のトランザクションによって変更される可能性があり、その結果、反復不可能な読み取りまたはファントム データが発生します。このオプションは、SQL Server のデフォルトです。

READ COMMITTED の動作は、READ_COMMITTED_SNAPSHOT データベース オプションの設定によって異なります。

  • READ_COMMITTED_SNAPSHOT が OFF (既定) に設定されている場合、データベース エンジンは共有ロックを使用して、現在のトランザクションが読み取り操作を実行している間、他のトランザクションが行を変更できないようにします。共有ロックは、他のトランザクションが完了するまで、ステートメントが他のトランザクションによって変更された行を読み取ることもブロックします。 共有ロックのタイプによって、いつ解放されるかが決まります。行ロックは、次の行が処理される前に解放されます。次のページが読み取られるとページ ロックが解放され、ステートメントが終了するとテーブル ロックが解放されます。
  • READ_COMMITTED_SNAPSHOT が ON に設定されている場合、データベース エンジンは行のバージョン管理を使用して、ステートメントの開始時に存在していたデータのトランザクション的に一貫性のあるスナップショットを各ステートメントに提示します。ロックは、他のトランザクションによる更新からデータを保護するために使用されません。

READ_COMMITTED_SNAPSHOT データベース オプションが ON の場合、READ COMMITTEDLOCK テーブル ヒントを使用して、READ COMMITTED 分離レベルで実行されているトランザクション内の個々のステートメントの行のバージョン管理ではなく、共有ロックを要求できます。

(強調追加)

データベース構成を変更して、READ_COMMITTED_SNAPSHOT を ON にします。

また、トランザクションを可能な限り短命に保ち、バックグラウンド プロセスでトランザクションをコミットしていることを確認してください (つまり、1 時間に 10,000 の挿入を実行しています)。コミットしないと、selects が永久にブロックされるためです (既定の設定)。

于 2009-09-13T03:22:28.650 に答える
5

他の人が言ったように、データベースに書き込むデータの量は問題ではありません。SQL Server は、それよりもはるかに多くのデータを簡単に処理できます。個人的には、問題なく 1 時間あたり数十万から数百万の行を処理するテーブルがあり、人々は一日中速度を落とさずに行を読んでいます。

  1. 読み取りステートメントの分離レベルを変更するか、WITH (NOLOCK) ヒントを使用して、ダーティー読み取りを行うことを確認する必要がある場合があります。

  2. .NET で一括アップロード オブジェクトを使用して、データをデータベースにロードする方法を検討する必要があります。テスト中に表示されるパフォーマンスに応じて、1000 ~ 5000 のバッチを使用します。最高のパフォーマンスを得るには、数を調整する必要があります。テーブルにデータを一括挿入すると、行ごとにレコードを挿入するよりもパフォーマンスが大幅に向上します。1 回のトランザクションでアップロード全体を実行しないようにしてください。バッチごとに 1 つのトランザクションを実行する必要があります。

  3. データベースに書き込みを行っているときのディスク IO はどのように見えますか。

  4. データベースにどの復旧モデルを設定していますか? データベースの FULL リカバリは、SIMPLE リカバリ モードを使用するよりも多くの IO を必要とします。FULL リカバリは、それに伴うポイント イン タイム リストアが実際に必要な場合にのみ使用してください。

于 2009-09-13T04:11:49.117 に答える
2

1 秒あたり 3 回未満の挿入では、各挿入操作で挿入されるデータの量が驚異的でない限り、どの DBMS にも効果がありません。同様に、1秒あたり10回の読み取りは、言及していない複雑な要因がない限り、有能なDBMSに過度のストレスをかける可能性はほとんどありません(「読み取りは、期間後に数十億のレコードを蓄積するDBMS全体の集計の集計です」など)の ... まあ、最初の 10 億レコードで 100,000 時間、つまり約 4,000 日、つまり約 10 年です)。

于 2009-09-13T03:21:24.977 に答える
0

Joel の回答のフォローアップでは、インデックスの PAD_INDEX と FILLFACTOR に適切な値を設定する必要があるかもしれません。これらのオプションを指定していない場合、挿入によってインデックスで多くの再ページ付けが行われる可能性があり、書き込み時間が大幅に遅くなります。

于 2009-09-14T04:35:41.333 に答える