数百万のファイルを含むFILESTREAM
コンテナがあり、それが現在発生しているパフォーマンスの問題(大量のタイムアウト)の原因であると考えています。
このブログFILESTREAM
のベストプラクティスによると、各コンテナは300,000を超えるファイルに到達しないようにする必要があります。
ここで受け入れられた回答 によると、テーブルを新しいFILESTREAM
の場所に再作成することを除いて、これを達成する方法はありません。
テーブルの構造は次のとおりです。
CREATE TABLE [dbo].[Documents](
[ContentPath] [uniqueidentifier] ROWGUIDCOL NOT NULL,
[FileContent] [varbinary](max) FILESTREAM NULL,
CONSTRAINT [UQ_IX_Documents_ContentPath] UNIQUE NONCLUSTERED
(
[ContentPath] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 90) ON [PRIMARY]
) ON [PRIMARY] FILESTREAM_ON [FSFileGroup_1]
私たちはSQL Server 2012を使用しています。残念ながらEnterpriseではありません(最近、ファイルグループごとに複数のコンテナーをサポートすることを認識しました)。
更新を記録することはありませんが、書き込みの数は多く、おそらく読み取りの数と同じです。パターンは次のとおりです。一度に1つだけ、ContentPathで読み取り、特定のコンテナーまたは順序で書き込みを行いません。
私にとっては、テーブルを論理的に分割することをお勧めします。そのため、すべてのセクションが独自のフォルダーにあり、300k以下のファイル(=レコード)を持ちます。
SQL Serverでは、論理テーブルの分割は通常、パーティション分割で行われます(これはエンタープライズ機能です)。パーティション分割は基本的に、テーブルのセクション(パーティション)を物理ストレージ(ファイルグループ)にマップします。さまざまなパーティションを異なるファイルグループに割り当てることができます。 FILESTREAM
は基本的にファイルグループのプロパティです。
これはあなたのソリューションの背骨を構成します:
これが FILESTREAM
列でテーブルを分割する方法 です。
主な利点:テーブル全体ではなく、パーティションごとにFILESTREAM
データを一度に管理できます。
あなたは必要になるでしょう:
パーティションのサイズを追跡できる、または少なくともパーティション間のランダムな書き込みを許可しないID
_[Id] [uniqueidentifier] ROWGUIDCOL NOT NULL DEFAULT (newsequentialid())
_
最後のパーティションの空き容量を確認するメンテナンスジョブ、事前に新しいファイルグループとパーティションを作成する、パーティションごとにインデックスを再構築するなど。
Insert
オペレーションに対応するには、パーティションが300k未満になるため、インデックスは一度に1つのパーティションを再構築します。
この設計は、ほとんどの場合、最後に挿入が発生する読み取り専用テーブル用です。まだ行っていない場合は、書き込みと更新、およびそれらに対するパーティション分割の影響を考慮してください。
テーブルをパーティション分割するには、インデックスを作成する必要があります。主に2つの方法があります。
テーブル全体のインデックスを再構築します。テーブルのx2〜x3倍のスペースが必要です。多くの理由により、大きなテーブルには適していません。
すでにパーティション分割されている新しいテーブルにデータを移行します。
これに対する私の好ましい方法:
DELETE... OUTPUT DELETED ... INTO <intermediary table>
_を使用してデータを挿入します。新しく挿入された行は、理想的には最後のパーティションに配置する必要があります。ただし、NEWSEQUENTIOALID()
関数には注意点があります。
GUIDこれは、任意の値よりも大きいGUID Windowsの起動以降、指定されたコンピューター上でこの関数によって以前に生成されました。Windowsの再起動後、GUIDは低い範囲から再開できますが、それでもグローバルに一意です。
つまり、サーバーの最初の再起動まで、新しい書き込みは最後のパーティションにのみ行われます。そして、これは最終的に起こります。新しい行がテーブルの中央に挿入されます。しかし、今パーティションがあることを覚えていますか?一度に1つのパーティションのみが影響を受けます。それでも、ある時点で30万行を超えることになります。
ここでの主なオプションは、パーティションを分割することです。既存のパーティションは2つに分割され、右側の部分が新しいパーティションを形成します。新しいパーティションは新しいファイルグループに移動する必要があります。これはメタデータのみの操作ではありません:ファイルは物理的に別のパーティションにコピーされます。
回避策は、同じPSで行を移動(行を削除して中間テーブルに挿入)することです。パーティションを分割して行を戻します。ただし、いずれにしてもデータの移動が必要です。同じPSに中間テーブルがある場合、分割にはデータの移動が含まれます。そうでない場合、データをもう一度メインテーブルに戻す必要があります。
複数のFILESTRAMコンテナーは、エンタープライズバージョンの機能です。コンテナは、FILESTREAM
コンテナでは「フォルダ」と呼ばれることがよくあります。実際には、FILESTREAM
タイプのファイルグループ内のデータベースファイルです。
NTFSフォルダーごとに300k未満のファイルを保持するのに役立ちますが、これらのフォルダー全体で保存されたファイルを明示的に管理することは非常に困難です。
記事 ファイルグループ内のファイル間でのデータの再調整 2011からPaul Randallがファイルグループ内のファイルの使用に関するヒントを提供します。
[SQL Server]は、ファイルグループ内の他のファイルとの相対的な空き容量に応じて、ファイルからデータを割り当てることを目的とするプロポーショナルフィルと呼ばれるアルゴリズムも使用します。
...
つまり、ほとんどが完全なデータファイルを持つファイルグループに新しいデータファイルを追加する場合、比例的な塗りつぶしの重み付けは、新しいファイルが、古いファイルと同じレベルに達するまで割り当てが行われるファイルになるようになります。ファイル。本質的に、新しいファイルは割り当てホットスポットになります。
SQL Serverは、他のファイルと同じ%ageレベルになるまで、新しく追加されたファイルを最初に埋めます。
パーティショニングのより簡単な代替手段のように見えるかもしれませんが、そうではありません:
同時に、複数のFILESTREAMコンテナーをパーティション分割ソリューションにブレンドして、フォルダーをより小さく高速にすることができます。
SEには、パーティション化も複数のFILESTREAM
コンテナーもありません。つまり、テーブルごとに1つのパーティションと1つのコンテナーしか持てません。
1つのオプションは、_UNION ALL
_ビューを上部に持つ複数のテーブルを持つことです。
UNION ALL
_するビューを作成します。 ヒント:すべてのテーブルのスキャンを回避するために、その特定のテーブルに属するIDのWHERE
句を追加します。オプティマイザーが特定のテーブルが存在しないテーブルを除外するのに役立ちます。_ Select * from Table1 where ID between 1 and 100
UNION ALL
Select * from Table2 where ID between 101 and 10000
UNION ALL
Select * from Table3 where ID between 10001 and 100000000
_
GUID from _0000-...-0000
_ to _FFFF-...-FFFF
_)のすべての可能な値をカバーしていることを確認してください-このビューは更新可能であるため、次のコマンドを使用して関連するテーブルにデータを挿入できます ビューによるデータの変更 。-すべてのデータを既存のテーブルから新しいテーブルに物理的にコピーする必要があります。これは、マスタービューを介して実行できます。
追伸SQL Serverは、まずRDMSです。 VARBINARY(MAX)
などの大量の非構造化データを管理する機能は、アドオンで比較的新しいものです。したがって、考慮する必要がある他の制限があります。
テーブルあたりの最大パーティション数:15 000最大ファイルグループORデータベースあたりのファイル数:32 767コンテナあたりの最大ファイル数:300 000(=この例ではファイルグループ、=複数のコンテナの場合はデータベースファイル)ファイルグループごと)
トランザクションログのサイズは、1つのトランザクションの制限と、トランザクションが完了するまでの時間です。合理的な時間内にロールバックするには、個々の操作を管理可能かつ可能な状態に保つ必要があります。