DataAdapter.updateBatchSizeを「最適な」値に設定するにはどうすればよいですか?
-
01-10-2019 - |
質問
私はついに挿入バッチを動作させてきましたが、今ではバッチのサイズをいじりましたが、50の値と10000の値のパフォーマンスの違いはわかりません。これは非常に奇妙に思えます。私、しかし、私は舞台裏で何が起こっているのかわからないので、それは通常の行動かもしれません。
私は160K行をテーブルに挿入しており、テストされた値の平均時間は115 +/- 2秒です。バッチをかけないと210秒かかるので、改善に非常に満足しています。ターゲットテーブルは次のとおりです。
CREATE TABLE [dbo].[p_DataIdeas](
[wave] [int] NOT NULL,
[idnumber] [int] NOT NULL,
[ideaID] [int] NOT NULL,
[haveSeen] [bit] NOT NULL CONSTRAINT [DF_p_DataIdeas_haveSeen] DEFAULT ((0)),
CONSTRAINT [PK_p_DataIdeas] PRIMARY KEY CLUSTERED
(
[wave] ASC,
[idnumber] ASC,
[ideaID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
) ON [PRIMARY]
私は読む updateBatchSizeを設定するときに何を探すべきか そして、答えは、単にいくつかの異なる値をテストすることでした。私はそれを理解することができますが、テーブルのデザイン、SQLの質問、挿入されようとしているデータを知っている場合、それを計算したり、少なくとも良い値を推測することはできませんか、少なくとも推測することはできませんか?
誰かが推奨できるベストプラクティスはありますか?
解決
SQLプロファイラーを見たり、電話をかけたりすることで、バッチングの効果を確認できます SqlConnection.RetrieveStatistics()
. 。あなたが見るべきものは、各バッチがDBへの単一の往復に対応することです。
バッチサイズを最適化する方法に関しては、非常に大まかな経験則は、パフォーマンスが約50を超えるバッチサイズで改善を停止する傾向があることです。実際、より大きなバッチが小さなバッチよりもゆっくりと実行される場合があります。私が忙しすぎてテストするには忙しすぎる場合、私は通常、約20のバッチから始めます(テーブルの価値のあるパラメーターを使用していない限り、最大500のバッチは小さなパラメーターよりも速くなります)。ただし、最適な数字は、インサートの合計サイズ(それらはすべてRAMに収まります)、DBログの配置の速さ、ログが独自のドライブ/LUNにあるかどうか(DBログが配置されている)などに依存します(そうでない場合は大きなパフォーマンスコスト)など
達成可能な速度は一般に、最初にラウンドトリップの数、次にトランザクションサイズ、次にログディスク速度(特にシーケンシャルアクセスが可能か、同じスピンドル上の他のファイルとの競合のためにランダムにされているかどうか)、そして最後に制限されます。羊。ただし、すべての要因もある程度関連しています。
挿入物のパフォーマンスを改善する最初のステップは、トランザクションでそれらを実行することです - おそらく1つまたは2つのバッチごとに1つのトランザクション。それを超えて、テーブルの価値のあるパラメーターはおそらく次のステップであり、 INSERT INTO Table SELECT column FROM @TableArgument
.
他のヒント
UpdateBatchSizeを変更すると、ある程度役立ちますが、DataAdapterを使用して多くのレコードを更新する基本的なアプローチは遅くなります。これは、最終的に、各行のDataAdapterによって個別のSQLステートメント(挿入、更新、または削除)が生成されるためです。 updateBatchSizeは、SQL Serverに送信されたときに1つのTSQLバッチで送信される個々のステートメントのうち数のみに影響します。
パフォーマンスの大幅な改善を得るには、SQLServerに1つのステートメントに多くのレコードを挿入/更新/削除することをお勧めします(通常、何らかの結合を使用して)。テーブルの価値のあるパラメーター(Ricknzが言及したように)は、これを行う1つの方法です。別の可能性は、SQLBulkCopyを使用することです(ただし、通常、このためにステージングテーブルを使用する必要があります)。
アクティブなトランザクションがあることを確認してください。これにより、パフォーマンスが大幅に向上します(mysqldataadapterを使用したテストでは約30倍)。