4

データベース内の特定のオブジェクトの履歴を追跡するためのテーブルを作成しています。現在、次の列があります。

HistoryId int IDENTITY(1,1) NOT NULL
HistoryDate datetimeoffset(7) NOT NULL 
HistoryTypeId int NOT NULL
HistoryDetails nvarchar(max) NULL

ほとんどの場合、各履歴項目は HistoryTypeId によって一目瞭然であるため、HistoryDe​​tails は Null または非常に小さい値になります。ただし、いくつかの履歴タイプでは、詳細データが大きくなります。すべてのレコードに nvarchar(max) を使用しても問題ありませんか、それとも分割して、64 文字を超える必要がある履歴タイプ用の列を追加する必要がありますか (以下を参照)。大まかな見積もりでは、レコードの 80% ~ 90% は 64 文字を超える詳細情報を必要とせず、テーブルには数百万のレコードが存在することになります。

HistoryId int IDENTITY(1,1) NOT NULL
HistoryDate datetimeoffset(7) NOT NULL 
HistoryTypeId int NOT NULL
HistoryDetails nvarchar(64) NULL
HistoryDetailsMore nvarchar(max) NULL
4

3 に答える 3

5

NVARCHAR(MAX)プレーン インデックスでキーの一部を作成することはできませんB-Tree(インデックスに含まれる列として引き続き使用できます)。

それ以外の場合、列のデータが行サイズのしきい値を超えない限り、ストレージは同じになります。

とにかくこのフィールドにインデックスを付けるつもりはないので、 として作成することをお勧めしますNVARCHAR(MAX)

インデックスを作成したい場合でも (たとえば、 を使用してプレフィックス検索を実行する場合LIKE)、計算NVARCHAR(450)列を作成し、その列にインデックスを作成して、それをクエリに追加して粗いフィルタリングを行うことができます。

詳細については、私のブログのこのエントリを参照してください。

小さな列のみを正確に検索する場合は、計算列を作成し、それにインデックスを付けて、次のようにクエリを実行します。

ALTER TABLE History ADD HistoryDetailsIndex AS SUBSTRING(HistoryDetails, 1, 50)

CREATE INDEX ix_mytable_typeid_details ON History (HistoryTypeId, HistoryDetailsIndex) INCLUDE (HistoryDetails)

SELECT  COUNT(*)
FROM    History
WHERE   HistoryTypeId = 123
        AND HistoryDetailsIndex LIKE 'string_prefix_up_to_50_characters%'
        AND HistoryDetails = 'string_prefix_up_to_50_characters_plus_everything_after_it'

50これにより、最初の文字のみがHistoryDetailsインデックス キー (LIKE条件で検索される) に含まれ、すべてが含まれる列に含まれます。

文字を超える50長さの文字列を検索しないことが絶対に確実な場合は、含まれている列を省略して、これを使用できます。

SELECT  COUNT(*)
FROM    History
WHERE   HistoryTypeId = 123
        AND HistoryDetailsIndex = 'string_prefix_up_to_50_characters'

これにより、インデックスが短くなります。

ただし、文字列を超える長さの文字列を指定すると失敗するため50、長い文字列を検索しないことが絶対に確実な場合に使用してください。

于 2009-09-14T15:32:15.257 に答える
0

nvarchar を使用しているため、SQLServer が小さなケースで可変長をオーバーライドしない限り、可変長レコードのオーバーヘッドをすでに支払っている可能性が高くなります。ただし、nvarchar(64) と nvarchar(max) の間の短いレコードでは、ディスク上のスペースは変更されません。データを収めるのに必要なだけのスペースを確保する必要があります。通常、その数はデータを制約するためにのみ使用されます。制約したくない場合は、まだ支払っていない 2 つの使用の間にペナルティを支払うべきではありません。

于 2009-09-14T15:29:19.630 に答える
0

最初に、varchar(MAX) は最大 2 GB のスペースを格納できることに注意してください。実際にはバックグラウンドで TEXT 値を使用し、その後、varchar(8000) 以下よりも多くの処理を使用します。

varchar(max) に小さなデータを多数格納している場合、8000 を超えない限り、通常の varchar 列として扱われ、その後は varchar(max) のように扱われます。

列にインデックスが付けられていますか、それともインデックスを付けたいですか? その場合は、varchar(max) を避けてください。

より高い値、たとえば varchar(255) を選択して、ユーザーがデータベース設計に適合するように強制し、その逆ではありません。

于 2009-09-14T15:34:53.803 に答える