500 万行のデータベース テーブルがあります。クラスター化インデックスは自動インクリメント ID 列です。PK は、URL の SHA256 ハッシュである 256 バイトVARCHAR
で生成されたコードです。これは、テーブルの非クラスター化インデックスです。
表は次のとおりです。
CREATE TABLE [dbo].[store_image](
[imageSHAID] [nvarchar](256) NOT NULL,
[imageGUID] [uniqueidentifier] NOT NULL,
[imageURL] [nvarchar](2000) NOT NULL,
[showCount] [bigint] NOT NULL,
[imageURLIndex] AS (CONVERT([nvarchar](450),[imageURL],(0))),
[autoIncID] [bigint] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_imageSHAID] PRIMARY KEY NONCLUSTERED
(
[imageSHAID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
CREATE CLUSTERED INDEX [autoIncPK] ON [dbo].[store_image]
(
[autoIncID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
imageSHAID
" http://blah.com/image1.jpg " などの画像 URL の SHA256 ハッシュで、長さ 256 の varchar にハッシュされます。imageGUID
画像を識別するコード生成された GUID です (後でインデックスとして使用されますが、今のところ、この列をインデックスとして省略しています)imageURL
画像の完全な URL です (最大 2000 文字)showCount
は、画像が表示される回数です。これは、この特定の画像が表示されるたびに増加します。imageURLIndex
は 450 文字に制限された計算列です。これにより、必要に応じて imageURL でテキスト検索を実行できます。インデックス化可能です (ここでも簡潔にするためにインデックスは省略されています)。autoIncID
はクラスター化インデックスであり、データの挿入を高速化する必要があります。
定期的に、一時テーブルからテーブルにマージしstore_image
ます。一時テーブルの構造は次のとおりです (store_image テーブルと非常によく似ています)。
CREATE TABLE [dbo].[store_image_temp](
[imageSHAID] [nvarchar](256) NULL,
[imageURL] [nvarchar](2000) NULL,
[showCount] [bigint] NULL,
) ON [PRIMARY]
GO
マージ プロセスが実行DataTable
されると、次のコードを使用して一時テーブルに a を書き込みます。
using (SqlBulkCopy bulk = new SqlBulkCopy(storeConn, SqlBulkCopyOptions.KeepIdentity | SqlBulkCopyOptions.KeepNulls, null))
{
bulk.DestinationTableName = "[dbo].[store_image_temp]";
bulk.WriteToServer(imageTableUpsetDataTable);
}
次に、merge コマンドを実行して、に基づいて一時テーブルからマージすることによりshowCount
、テーブル内のを更新します。画像が現在テーブルに存在しない場合は、作成します。store_image
imageSHAID
store_image
merge into store_image as Target using [dbo].[store_image_temp] as Source
on Target.imageSHAID=Source.imageSHAID
when matched then update set
Target.showCount=Target.showCount+Source.showCount
when not matched then insert values (Source.imageSHAID,NEWID(), Source.imageURL, Source.showCount);
私は通常、store_image
1 つのマージ プロセスで一時テーブルからテーブルに 2,000 ~ 5,000 行をマージしようとしています。
私はこの DB を SSD (SATA 1 のみが接続されている) で実行していましたが、非常に高速でした (200 ミリ秒未満)。SSD の空き容量がなくなったので、DB を 1 TB 7200 キャッシュ回転ディスクに交換しました。これは、完了時間が 6 ~ 100 秒 (6000 ~ 100000MS) を超えているためです。一括挿入の実行中は、ディスク アクティビティが約 1MB ~ 2MB/秒で、CPU 使用率が低いことがわかります。
これは、この量のデータの典型的な書き込み時間ですか? 少し遅いように思えますが、パフォーマンスが遅い原因は何ですか? 確かimageSHAID
にインデックス化されているので、これよりも速いシーク時間が期待できるでしょうか?
どんな助けでも大歓迎です。
御時間ありがとうございます。