4

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_imageimageSHAIDstore_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_image1 つのマージ プロセスで一時テーブルからテーブルに 2,000 ~ 5,000 行をマージしようとしています。

私はこの DB を SSD (SATA 1 のみが接続されている) で実行していましたが、非常に高速でした (200 ミリ秒未満)。SSD の空き容量がなくなったので、DB を 1 TB 7200 キャッシュ回転ディスクに交換しました。これは、完了時間が 6 ~ 100 秒 (6000 ~ 100000MS) を超えているためです。一括挿入の実行中は、ディスク アクティビティが約 1MB ~ 2MB/秒で、CPU 使用率が低いことがわかります。

これは、この量のデータの典型的な書き込み時間ですか? 少し遅いように思えますが、パフォーマンスが遅い原因は何ですか? 確かimageSHAIDにインデックス化されているので、これよりも速いシーク時間が期待できるでしょうか?

どんな助けでも大歓迎です。

御時間ありがとうございます。

4

1 に答える 1

6

更新のあなたのUPDATE句。これには、クラスター化インデックスでのキー ルックアップが必要です。MERGEshowCount

ただし、クラスター化インデックスも一意でないと宣言されます。これにより、基になる列が一意であっても、オプティマイザーに情報が提供されます。

だから、私はこれらの変更を行います

  • クラスター化された主キーautoIncID
  • 現在の PK をimageSHAIDスタンドアロンの一意のインデックス (制約ではない) にし、 の INCLUDE を追加しshowCountます。一意の制約に INCLUDE を含めることはできません

その他の観察:

  • nvarcharハッシュまたは URL 列は必要ありません。これらはユニコードではありません。
  • ハッシュも固定長であるため、固定長にすることができますchar(64)(SHA2-512 の場合)。
  • 列の長さは、クエリに割り当てるメモリの量を定義します。詳細については、これを参照してください: varchar(8000) よりも varchar(500) に利点はありますか?
于 2013-08-09T09:40:13.933 に答える