3

かなり大きなテーブル (ただし巨大ではありません) を持つ SQL Server があります。

必要がある

a) 1 秒あたり約 1000 レコードを (特定の時間に - ただし、バッチ挿入はできません) をそれらのテーブルの 1 つ、たとえば TABLE_A に挿入し、b) 同時に select * from TABLE_B where id = _SOME_GUID_ID

(a)現在、負荷がかかると500〜600ミリ秒かかり(バッチ処理できないため、挿入ごとに)、(b)約400ミリ秒かかります(インデックスがあります)

これは、私たちが求めているパフォーマンスにはほど遠いものです。これらのテーブル/操作を最適化する方法はありますか?

現在のサーバーには 16 GB の RAM があり、データベースの合計サイズは約 40 GB です。これらのテーブルは、今後数か月で 10 倍になると予想されます。Sql Server で実行できるシャーディングはありますか? MySQL Percona ビルドを使用するとパフォーマンスが向上しますか?

うまくいけば、これは理にかなっています。NHibernate を使用していることを付け加えたいと思いますが、上記のパフォーマンスはデータベースへの挿入に費やされたミリ秒であり、アプリケーションや nh のオーバーヘッドは含まれていません。

ありがとう、ヤニス

4

2 に答える 2

3

いくつかのことが思い浮かびます。主キーとは、GUID または整数です。それが GUID であり、その上にクラスター化されている場合、SQL Server は順番にではなく、さまざまな場所に挿入する必要があります。データベースのサイズ、ログのサイズ、または常に自動拡張されていますか?データベース ファイルのサイジングを参照してください。

プロファイラーを実行して、nhibernate が作成する SQL の種類を確認します。1 秒あたり 1000 回の挿入はもはやそれほど印象的ではありません。ハードウェアもボトルネックになる可能性があります。適切なサイズと構成であることを確認してください。tempdb、ログ、およびデータ ファイルは同じドライブにありますか? その場合は、それらを別のドライブに移動します

別のオプションは、これらの挿入を行う部分を書き直し、単一行の挿入の代わりにそれらをバッチ処理することです

これは、SSMS から実行した例です。166 ミリ秒で 4999 回、40 ミリ秒で 1000 回の挿入を行います。

CREATE TABLE Sometest(id INT PRIMARY KEY, 
SomeCol VARCHAR(200), SomeDate DATETIME,SomeCol2 VARCHAR(200), 
SomeDate2 DATETIME,SomeCol3 VARCHAR(200), 
SomeDate3 DATETIME,SomeCol4 VARCHAR(200), SomeDate4 DATETIME)
GO




DECLARE @start DATETIME = GETDATE()
SET NOCOUNT ON
DECLARE @id INT =1
WHILE @id < 1000
BEGIN
    INSERT Sometest
    SELECT @id ,'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla111111',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla2222',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla3333',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla4444',GETDATE()
SET @id+=1
END




SELECT DATEDIFF(ms,@start,GETDATE())
SELECT COUNT(*) FROM Sometest

全体をトランザクションでラップすると、はるかに高速になります。50000 回の挿入は 800 ミリ秒、5000 回の挿入は 103 ミリ秒、1000 回の挿入は 23 ミリ秒です。

TRUNCATE TABLE Sometest
DECLARE @start DATETIME = GETDATE()
SET NOCOUNT ON
BEGIN tran
DECLARE @id INT =1
WHILE @id < 50000
BEGIN
    INSERT Sometest
    SELECT @id ,'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla111111',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla2222',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla3333',GETDATE(),
    'BlaBlaBlaBlaBlaBlaBlaBlaBlaBla4444',GETDATE()
SET @id+=1
END
commit
SELECT DATEDIFF(ms,@start,GETDATE())
SELECT COUNT(*) FROM Sometest

テーブルのように見えるテーブルを使用してシステムでそのようなものを実行し、問題が何であるかを調査します。おそらく、ファイルのサイズを事前調整したり、ファイルを分離したり、テーブルを最適化したりする必要があります。

于 2013-03-13T15:26:34.843 に答える
0

あなたの Guid はシーケンシャル GUID またはランダム GUID である可能性があり、どちらを知る必要があります。非クラスター化インデックスを一時的に無効にして、挿入の最後にそれらを再構築できます。ただし、その期間中、そのテーブルの選択が (おそらく) 遅くなることを気にしないでください。いくつのコアといくつの一時データベースがありますか? コアごとに 1 つの tempdb (最大 8 コア) を試してみてください。以下で述べたように、挿入をバッチ処理します

于 2013-03-13T15:52:25.593 に答える