varchar(8000)よりもvarchar(500)に利点はありますか?


90

私はこれをMSDNフォーラムとここで読みましたが、まだ明確ではありません。これは正しいと思います。Varchar(max)はテキストデータ型として格納されるため、欠点があります。したがって、フィールドが確実に8000文字未満になるとしましょう。データベーステーブルのBusinessNameフィールドのように。実際には、ビジネス名は常に500文字以内(数字を引っ張って)になります。たまたま私が遭遇するたくさんのvarcharフィールドは、8k文字のカウントに十分収まらないようです。

それで、そのフィールドをvarchar(8000)ではなくvarchar(500)にする必要がありますか?私がSQLについて理解していることから、これら2つの間に違いはありません。だから、人生を楽にするために、すべてのvarcharフィールドをvarchar(8000)として定義したいと思います。それには欠点がありますか?

関連:varcharカラムのサイズ(これが私の質問に答えたとは思わなかった)。


6
名刺に500文字の長さのビジネス名を入力しようとしていると想像してみてください... :)
OMGポニー2010年

2
@OMGポニー:ユーザー名が表示されるたびに私は笑います。さて、あなたは何を言っていましたか?(冗談です)
jcollum 2010年

4
@jcollum:SpaceMan Spiffは常に私の投票を取得します。それは真実ではありません- カルバンとホッブズは何でもしますが、特に雪を彫刻するものはそうです。またはF-14を飛ぶティラノサウルス。しかし、私は余談です...
OMGポニー

回答:


20

処理の観点からは、varchar(8000)とvarchar(500)を使用しても違いはありません。フィールドが保持する必要がある最大長を定義し、varcharをその長さにすることは、「良い習慣」のようなものです。これは、データの検証を支援するために使用できるものです。たとえば、州の略称を2文字にするか、郵便番号を5または9文字にする。これは、データが他のシステムやフィールド長が重要なユーザーインターフェイス(メインフレームのフラットファイルデータセットなど)とやり取りするときに、以前より重要な区別でしたが、最近では、他の何よりも習慣になっていると思います。


3
理にかなっています...当然最大長を持っているもののために。しかし、最大長が明確でない場合はどうしますか?たとえば、会社名。
jcollum 2010年

2
そのようなものについて、サイズが潜在的に何であるかを予測する方法を予測しない場合は、通常、データのタイプに応じてvarchar(8000)またはvarchar(max)を使用します
BBlake

4
これにより、2017年でもパフォーマンスに違いが生じるようです:dba.stackexchange.com/a/162117/1822
a_horse_with_no_name

1
より最近の回答コストがあることを示しています。それは最適化ロジックに影響を与え、マーティン・スミスの回答に加えて、GBNOliverによって言及された合計8Kの行サイズの問題も考慮しています。
ToolmakerSteve 2017年

124

これにより違いが生じる可能性のある1つの例は、After Triggerを使用してテーブルに行バージョン情報を追加することを回避するパフォーマンスの最適化を妨げることです。

これはここのSQL Kiwiでカバーされています

保存されるデータの実際のサイズは重要ではありません。重要なのは潜在的なサイズです。

同様に、2016年以降にメモリ最適化テーブルを使用する場合、行の制限を超える可能性があるがペナルティを伴う可能性のあるLOB列または列幅の組み合わせを使用することが可能になりました。

(最大)列は常に行外に格納されます。その他の列の場合、テーブル定義のデータ行のサイズが8,060バイトを超える可能性がある場合、SQL Serverは最大の可変長列を行外にプッシュします。繰り返しますが、そこに格納するデータの量には依存しません。

これは、メモリの消費とパフォーマンスに大きな悪影響を与える可能性があります

列幅を過度に宣言すると大きな違いが生じる可能性があるもう1つのケースは、テーブルがSSISを使用して処理されるかどうかです。可変長(非BLOB)列に割り当てられたメモリは、実行ツリーの各行に対して固定され、列の宣言された最大長に基づいているため、メモリバッファの非効率的な使用につながる可能性があります(例)。SSISパッケージの開発者はソースよりも小さい列サイズを宣言できますが、この分析は前もって実行してそこで実施するのが最適です。

SQL Serverエンジン自体に戻ると、同様のケースとして、SORT操作に割り当てるメモリ許可を計算するときに、SQL Serverはvarchar(x)列が平均してx/2バイトを消費すると想定します。

ほとんどのvarchar列がそれよりもいっぱいの場合、sort操作がに波及する可能性がありますtempdb

あなたの場合、varchar列が8000バイトとして宣言されているが、実際の内容がクエリよりもはるかに少ない場合、クエリに必要とされないメモリが割り当てられます。これは明らかに非効率であり、メモリ付与の待機につながる可能性があります。

これは、ここからダウンロードできる SQL Workshops Webcast 1のパート2でカバーされているか、以下を参照してください。

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

スクリーンショット

SELECT id,name8000
FROM T
ORDER BY number

スクリーンショット


1
したがって、ほとんどすべての値が3または4文字で、4文字を超えることはできず、「ソート操作がtempdbに溢れる」ことを避けたい場合は、列VARCHAR(8)を宣言し、CHECK制約を使用してその列を強制します幅は4文字を超えることはできません。どう思いますか?
AK

12
@AlexKuznetsov- char(4)いずれにしても、可変列ごとに2バイトのオーバーヘッドがあるので、その状況を宣言します。
マーティン・スミス

9

ベストプラクティス以外(BBlakeの回答)

  • DDLで最大行サイズ(8060)バイトとインデックス幅(900バイト)に関する警告が表示される
  • これらの制限を超えると、DMLは停止します
  • ANSI PADDING ONがデフォルトなので、空白の全負荷を格納してしまう可能性があります

38
ANSI PADDING ONについて明確にするために:nvarcharvarcharタイプを使用する場合、これは挿入時に後続スペースが保持されることを意味するだけでcharあり、やのように、列のサイズに合わせて値にスペースが埋め込まれますnchar
ベンM

9

大規模な列にはいくつかの欠点がありますが、少しわかりにくく、少し遅れて気付く可能性があります。

  • INDEXで使用するすべての列-900バイトを超えてはなりません
  • ORDER BY句のすべての列が8060バイトを超えることはできません。これは一部の列にのみ適用されるため、理解するのが少し難しいです。詳細については、SQL 2008 R2の行サイズ制限を超えているを参照してください)
  • 行の合計サイズが8060バイトを超えると、その行の「ページ溢れ」が発生します。これはパフォーマンスに影響を与える可能性があります(ページはSQLServerのアロケーションユニットであり、8000バイト+オーバーヘッドで固定されています。これを超えることは深刻ではありませんが、それは顕著であり、簡単にできる限り回避するようにしてください)
  • 他の多くの内部データ構造、バッファー、および独自の変数とテーブル変数がすべてこれらのサイズをミラーリングする必要があります。サイズが大きすぎると、過剰なメモリ割り当てがパフォーマンスに影響を与える可能性があります

原則として、列幅は控えめにしてください。問題が発生した場合は、ニーズに合わせて簡単に拡張できます。後でメモリの問題に気付いた場合、後で幅の広い列を縮小することは、データを失うことなく不可能になり、どこから始めればよいかわからなくなります。

ビジネス名の例では、どこに表示するか考えてください。500文字分のスペースは本当にありますか?そうでない場合、それらをそのように保管しても意味がありません。http://en.wikipedia.org/wiki/List_of_companies_of_the_United_Statesにはいくつかの会社名がリストされており、最大は約50文字です。したがって、列の最大値として100を使用します。たぶん80にもっと似ているかもしれません。


2

理想的には、それよりも小さく、適度なサイズ(500は適度なサイズではない)にして、データが大きくなりすぎて有用なエラーが送信されるときにクライアントの検証がキャッチすることを確認します。

varcharは実際には未使用のスペースのためにデータベース内のスペースを予約するつもりはありませんが、SQL Serverのバージョンでは、データベースの行が一部のバイト数よりも広いことを思い出して(正確な数を思い出さないでください)、実際に破棄しています適合しなかったデータはすべて。これらのバイトの特定の数は、SQL Serverの内部用に予約されています。


確かに、これは以前にもずっと大きな懸念でした。でも最近はスペースが本当に安いので、少なくとも私の考えでは、それほど気にする必要はないと思います。
BBlake、2010年

1
@jcollum:あなたの例では、500はビジネス名として適切なサイズではないようです。
Otis

1
@BBlake:ストレージのコストに関係なく、SQL Serverに行サイズの制約がある場合は、どのくらいのストレージでもかまいません。すべてをtextblobに格納できますが、BLOBに対して実行できないSQLオペレーションがvarcharに対して実行できる場合があります。
オーティス、

2
@オーティス:私のポイントはこれです:ビジネス名のサイズに実際の制約はありません。どこかに法律がない限り。したがって、その場合、そのフィールドをvarchar(8000)にして、1日と呼びます。私の考えは次のようになります。本当の制約?varchar(x)。実際の制約はありませんか?varchar(8000)。
jcollum 2010年

24
私はエル・プエブロ・デ・ヌエストラセニョーララレイナデロスアンジェルス・デル・リオ・デ・Porciúnculaを見るまで私は、都市名の良かった30かそこらの文字を考えた
StuartLC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.