2

基本的な問題は、データがロードされるにつれて挿入率が低下することです。

  • PK 以外のすべてのインデックスを無効にしました
  • FK 制約を無効にしました。
  • 挿入する前に、LINQ を使用して PK でデータを並べ替えました

しかし、挿入速度は依然として低下しています。

ロード中はユーザー数が制限されます。だからPKを倒すことはできません。

データは PK の順序でロードされますが、そのインデックスはまだフラグメント化されています。

Int、TinyInt、String の複合 PK。

読み込みが 100% のフィル ファクターでインデックスを再構築する前。テーブルには、無効になっている別のインデックスが 1 つあります。

現在、20,00 行がテーブルにロードされているため、PK インデックスには既に 4% の断片化があります。断片化し続け、読み込み速度が低下します。DBCC SHOWCONTIG ('docMVtext', 'PK_docMVtext') で断片化をチェックします。

  • スキャンされたページ.................................................................155
  • スキャンされたエクステント................................................................................. 26
  • エクステント スイッチ.................................................................: 25
  • 平均 エクステントあたりのページ................................................: 6.0
  • スキャン濃度 [ベストカウント:実際のカウント].......: 76.92% [20:26]
  • 論理スキャンの断片化 ................................: 4.52%
  • エクステント スキャン フラグメンテーション ................................: 96.15%
  • 平均 1 ページあたりの空きバイト数.................................................: 54.9
  • 平均 ページ密度 (フル).................................................: 99.32%

Extent Scan Fragmentation が高いので、2 つ目の質問をする必要があるかもしれません。

int tinyint にのみ PK があり、同じ問題に苦しんでいる姉妹テーブル docSVtext があるため、PK の一部としての varchar(600) 値ではないと思います。

バックアップ復元を介して別のデータベースからこのデータベースを作成しました。同じ構成テーブルが必要でしたが、同じデータ テーブルは必要ありませんでした。データ テーブルからデータを削除し、shrinkdb TRUNCATEONLY を実行しました。

挿入値 ()、()、() を使用して値をロードします。

おそらく値 ()、()、() が順序を変更していると考えたため、.NET を行ごとに 1 つの挿入に変更し、PK の順序で挿入されたデータでも PK で断片化が発生しました。

データが PK の順序で挿入されていることを 3 回確認します。

.NET アプリでは、挿入前に LINQ を使用してデータを並べ替えています。デバッグで 40 を確認したところ、すべて適切にソートされていました。

IDEN を使用してミラー テーブルを作成し、同じ 3 つの列を作成しました。そのミラー テーブルで同じ挿入を使用して、挿入順序を検証しました。Iden で並べ替えられたミラー テーブルを選択すると、データは並べ替えられた順序になります。これは、PK でソートされたデータを挿入した二次テストです。

以下はテーブル定義です。(はい、最初の段落で FK 制約がないことを知っています。これは FK 制約を示しています。FK 制約を削除しても、挿入速度は向上しません。)

USE [Gabe2a_ENCORE]
GO

/****** Object:  Table [dbo].[docMVtext]    Script Date: 08/12/2012 20:13:35 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[docMVtext](
    [sID] [int] NOT NULL,
    [fieldID] [tinyint] NOT NULL,
    [value] [varchar](600) NOT NULL,
 CONSTRAINT [PK_docMVtext] PRIMARY KEY CLUSTERED 
(
    [sID] ASC,
    [fieldID] ASC,
    [value] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = ON, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 100) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

ALTER TABLE [dbo].[docMVtext]  WITH CHECK ADD  CONSTRAINT [FK_docMVtext_docFieldDef] FOREIGN KEY([fieldID])
REFERENCES [dbo].[docFieldDef] ([ID])
GO

ALTER TABLE [dbo].[docMVtext] CHECK CONSTRAINT [FK_docMVtext_docFieldDef]
GO

ALTER TABLE [dbo].[docMVtext]  WITH NOCHECK ADD  CONSTRAINT [FK_docMVtext_docSVsys] FOREIGN KEY([sID])
REFERENCES [dbo].[docSVsys] ([sID])
GO

ALTER TABLE [dbo].[docMVtext] CHECK CONSTRAINT [FK_docMVtext_docSVsys]
GO

私を困惑させたのは、この初期ロードの後、テキストを解析してインデックスを作成し、単純な全文検索インデックスを作成したことです。これらのテーブルをロードするために、メモリ内での並べ替えと PK の順序での挿入という同じ戦略を使用し、そこで PK の断片化をゼロにします。PK でこの断片化を取得するための初期ロードの違いがわかりません。

信じられないかもしれませんが、主要なボトルネックは最初のテーブルにありました。

以下の最初のコードは、テーブルに 300,000 行ある 2 番目のコードよりも 10 倍高速です。160 万行で、最初の行は 30 倍高速です。そもそもずさんな @@identity を使用するのは当然のことです。

SQLcmd.CommandText = commandText + ";  SELECT SCOPE_IDENTITY() ";
sID = int.Parse((SQLcmd.ExecuteScalar().ToString()));


SQLcmd.CommandText = commandText;
rowsRet = SQLcmd.ExecuteNonQuery();
if (rowsRet == 1)
{
    commandText = "select @@identity from [docSVsys]";
    SQLcmd.CommandText = commandText;
    sID = int.Parse(SQLcmd.ExecuteScalar().ToString());
}
4

1 に答える 1

1

これは初期化のための一括挿入であるため、テーブルのすべてのインデックスを削除することをお勧めします。これを行うことで、データをできるだけ早くサーバーに取り込みます。その後、データの読み込みが完了したら、PK と非クラスター化インデックスを適用します。Sql サーバーは、特定のページのフィル ファクターに達するたびにデータを再配置するのではなく、一度にすべてのデータを再配置することができます。

于 2012-08-13T14:40:10.850 に答える