SQL varchar列の長さのベストプラクティス[終了]


288

新しいSQLテーブルをセットアップするたび、またはvarchar既存のテーブルに新しい列を追加するたびに、1つのことを考えていlengthます。

したがって、たとえば、というnameタイプの列があるとしますvarchar。したがって、長さを選択する必要があります。20文字を超える名前は考えられませんが、あなたは決してわかりません。ただし、20を使用する代わりに、常に次の2 ^ nの数値に切り上げます。この場合、長さとして32を選択します。コンピュータサイエンティストの観点から見ると、2 ^ nという数値evenは他の数値よりも私に見えるため、その下のアーキテクチャがこれらの数値を他の数値よりもわずかに処理できると想定しているだけです。

一方、たとえば、MSSQLサーバーは、varchar列の作成を選択すると、デフォルトの長さの値を50に設定します。それについて考えさせられます。なぜ50?それは単なる乱数ですか、それとも平均列長に基づいていますか?

また、SQLサーバーの実装(MySQL、MSSQL、Postgresなど)によって、列の長さが異なる場合もあります。

回答:


238

ようになります任意の「最適化」ありのないDBMS私が知っているVARCHARとの2^n長さはとのより良いものより行うmax2のべき乗でない長さを。

SQL Serverの初期のバージョンでは、実際にVARCHARは長さが255のと、最大長がそれよりも長い場合の扱いが異なっていたと思います。これがまだ当てはまるかどうかはわかりません。

ほとんどすべてのDBMSで、必要な実際のストレージは、max定義した長さではなく、そこに入れる文字数によってのみ決定されます。だから、ビューのストレージポイント(およびおそらくパフォーマンスの一つとしても)から、それはあなたのように列を宣言するかどうかを任意の違いはありませんVARCHAR(100)VARCHAR(500)

あなたは、表示されるはずmaxのために提供長さVARCHARの制約(またはビジネスルール)の一種として、列ではなく、技術的/物理的なものを。

PostgreSQLの場合、最適な設定はtext、長さ制限なしで使用しCHECK CONSTRAINT、文字数をビジネスで必要なものに制限することです。

その要件が変更された場合、チェック制約の変更はテーブルの変更よりもはるかに高速です(テーブルを再作成する必要がないため)。

Oracleや他の人にも同じことが当てはまります-OracleではそうでVARCHAR(4000)textありません。

VARCHAR(max)たとえばVARCHAR(500)SQL Server との間で物理的なストレージの違いがあるかどうかはわかりません。ただしvarchar(max)、と比較して使用するとパフォーマンスに影響があるようvarchar(8000)です。

このリンクを参照してください(コメントとしてErwin Brandstetterにより投稿)。

2013-09-22を編集

bigownのコメントについて:

9.2以前のPostgresバージョン(最初の回答を書いたときには利用できませんでした)では、列定義を変更するとテーブル全体書き換えられました。たとえば、こちらを参照してください。9.2以降、これは当てはまりません。簡単なテストでは、120万行のテーブルの列サイズを増やすのに0.5秒しかかからないことが確認されました。

Oracleにとっても、大きなテーブルのvarchar列を変更するのにかかる時間から判断すると、これは正しいようです。しかし、そのための参照は見つかりませんでした。

MySQL 場合、ALTER TABLEマニュアルにはほとんどの場合、元のテーブルの一時コピーを作成する」と記載されています。そして、私自身のテストALTER TABLEでは、120万行のテーブルで(Postgresを使用した私のテストと同じ)列のサイズを増やすのに1.5分かかりました。ただし、MySQL では、「回避策」を使用してチェック制約を使用し、列の文字数を制限することできません

SQL Serverの場合、これに関する明確なステートメントは見つかりませんでしたが、varchar列のサイズを増やすための実行時間(上記の120万行のテーブル)は、書き換えが行われていないことを示してます。

2017-01-24を編集

SQL Serverについて(少なくとも部分的に)間違っていたようです。a または列の宣言された長さがパフォーマンスに大きな違いをもたらすことを示す、Aaron Bertrandからのこの回答を参照してください。nvarcharvarchar


34
実際には、VARCHAR(255)とVARCHAR(500)の間には、そのような列の中に1文字を入れても違いがあります。行の最後に追加される値は、格納されたデータの実際の長さが何であるかを格納する整数になります。VARCHAR(255)の場合は1バイト整数になります。VARCHAR(500)の場合は2バイトになります。これは小さな違いですが、注意する必要があります。パフォーマンスにどのような影響を与える可能性があるのか​​、手元にあるデータはありませんが、データが小さすぎて調査する価値がないと思います。
NB

1
@NB:SQL Serverの「マジック」255値について私が言及していたものです。説明をありがとう。
a_horse_with_no_name

4
@NBどのRDBMSを参照していますか?SQLサーバー?性能に影響があります。[N] VARCHAR(max)のパフォーマンスは[N] VARCHAR(n)よりもわずかに遅くなります。最近このサイトを紹介されました。私が知っている限り、同じことはPostgreSQLにも当てはまりません。
Erwin Brandstetter、2011年

@ErwinBrandstetter:リンクをありがとう。以下のように見えるがvarchar(max)、おそらくより、OracleのようなものですCLOB
a_horse_with_no_name

1
varcharの長さを変更しても、テーブルは書き換えられません。CHECK CONSTRAINTとまったく同じように、テーブル全体に対して制約の長さをチェックするだけです。長さを増やす場合、何もする必要はありません。次の挿入または更新だけで、より長い長さが受け入れられます。長さを減らし、すべての行が新しい小さな制約を通過した場合、Pgは次の挿入または更新で新しい長さのみを書き込むことを許可する以外に、それ以上のアクションを実行しません。
Maniero 2013

69

VARCHAR(255)そしてVARCHAR(2)取る正確にディスク上の領域の同じ量を!したがって、それを制限する唯一の理由は、それを小さくする特定の必要性がある場合です。それ以外の場合は、すべて255にします。

具体的には、並べ替えを行う場合、列が大きくなるとより多くのスペースが必要になるため、パフォーマンスが低下する場合は、列を心配してサイズを小さくする必要があります。ただし、そのテーブルから行を1つだけ選択する場合は、それらをすべて255にするだけで問題ありません。

参照:MySQLの最適なvarcharサイズは何ですか?


7
全部作ってみませんVARCHAR(MAX)か?データベースをモデル化する際の考慮事項はスペースだけではありません。モデリングするドメインは、データ型とサイズを決定する必要があります。
Oded

6
@Oded VARCHAR(MAX)varchar(255)or と同じではありません-varchar varchar(65535)maxはtextデータ型のタイプです。そして、あなたの要点-彼が「彼がモデリングしていたドメイン」が何であるかを知っているなら、彼はこの質問をしません。明らかに、彼は自分のデータがどれくらいの大きさになるかわからないので、フルサイズにしても何も害がないことを確信しています。
アリエル

4
@Ariel:考慮すべきインデックスにも問題と制限があります。(a,b,c,d)4つの列がすべての場合は、インデックスを作成できませんVARCHAR(255)
ypercubeᵀᴹ

@ypercubeそうです、列にインデックスが必要な場合は、サイズにもっと注意する必要があります。しかし、ほとんどの列はインデックスを必要としないので、ほとんどの場合、それを心配する必要はありません。
アリエル

正確な値がわかっている場合は、charを使用することをお勧めします。一方、それはまだであれば、私はvarchar型を使用predicitveし、それが動的なメモリ割り当てであるとして、あなたが取られるサイズの心配はありませんので、255を保つ
ファリスRayhan

54

新しいSQLテーブルをセットアップするときはいつでも、2 ^ nの方が同じように感じます...しかし、ここで答えをまとめると、varchar(2 ^ n)を定義するだけで、ストレージスペースに大きな影響はありません。またはvarchar(MAX)。

とはいえ、varchar()の上限を高く設定した場合でも、ストレージとパフォーマンスへの潜在的な影響を予測する必要があります。たとえば、フルテキストインデックスを使用して製品の説明を保持するvarchar(MAX)列を作成するとします。説明の99%が500文字しかない場合に、突然、その説明をウィキペディアの記事に置き換える誰かを見つけると、予期しない大きなストレージとパフォーマンスのヒットに気付く場合があります。

ビルカーウィンからのもう1つの考慮事項

パフォーマンスへの影響が1つ考えられます。MySQLでは、一時テーブルとMEMORYテーブルがVARCHAR列を固定長の列として格納し、最大長までパディングされます。必要な最大サイズよりもはるかに大きいVARCHAR列を設計すると、必要以上のメモリが消費されます。これは、キャッシュ効率、ソート速度などに影響します。

基本的に、妥当なビジネス上の制約と、少し大きいサイズでのエラーを考え出します。@onedayが指摘したように、英国の姓は通常1〜35文字です。これをvarchar(64)にすると決めたとしても、何も傷つけることはありません... 666文字までと言われているこの男の姓を保存している場合を除きます。その場合、おそらくvarchar(1028)のほうが理にかなっています。

参考になる場合は、varchar 2 ^ 5から2 ^ 10を入力すると、次のようになります。

varchar(32)     Lorem ipsum dolor sit amet amet.

varchar(64)     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie

varchar(128)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas

varchar(256)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt

varchar(512)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie

varchar(1024)   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie
                dapibus leo lobortis eleifend. Vivamus vitae diam turpis. Vivamu
                nec tristique magna, vel tincidunt diam. Maecenas elementum semi
                quam. In ut est porttitor, sagittis nulla id, fermentum turpist.
                Curabitur pretium nibh a imperdiet cursus. Sed at vulputate este
                proin fermentum pretium justo, ac malesuada eros et Pellentesque
                vulputate hendrerit molestie. Aenean imperdiet a enim at finibus
                fusce ut ullamcorper risus, a cursus massa. Nunc non dapibus vel
                Lorem ipsum dolor sit amet, consectetur Praesent ut ultrices sit

31

最良の値は、基になるドメインで定義されているデータに適した値です。

一部のドメインでVARCHAR(10)は、Name属性に適切ですが、他のドメインVARCHAR(255)では最適です。


15

a_horse_with_no_nameの回答に追加すると、興味のある次の項目が見つかるかもしれません...

列をVARCHAR(100)として宣言しても、VACHAR(500)として宣言しても、違いはありません。

-- try to create a table with max varchar length
drop table if exists foo;
create table foo(name varchar(65535) not null)engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length - 2 bytes for the length
drop table if exists foo;
create table foo(name varchar(65533) not null)engine=innodb;

Executed Successfully

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65533))engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65532))engine=innodb;

Executed Successfully

長さバイトとnull許容バイトを忘れないでください。

name varchar(100) not null 1バイト(長さ)+最大100文字(latin1)

name varchar(500) not null 2バイト(長さ)+最大500文字(latin1)

name varchar(65533) not null 2バイト(長さ)+最大65533文字(latin1)

name varchar(65532) 2バイト(長さ)+最大65532文字(latin1)+ 1つのnullバイト

お役に立てれば :)


MySQLを使用していて、MSSQLに関する質問です
Bogdan Mart

6

常にビジネスドメインの専門家に確認してください。それがあなたなら、業界標準を探してください。例えば、問題のドメインは、自然人の姓(名字)であれば、英国のビジネスのために私はに行きたい人の情報のために英国Govtalkデータ標準カタログや家族の名前は1から35文字の間になることを発見します。


3

私は最近これをチェックしていませんが、以前はOracleで、JDBCドライバーがクエリの実行中にメモリのチャンクを予約して、返される結果セットを保持することを知っていました。メモリチャンクのサイズは、列の定義とフェッチサイズによって異なります。したがって、varchar2列の長さは予約されるメモリの量に影響します。私たちは常にvarchar2(4000)(当時の最大値)を使用しており、ガベージコレクションは現在よりもはるかに効率が悪いため、これは私にとって数年前に深刻なパフォーマンスの問題を引き起こしました。


-2

ある意味であなたは正しいですが、2 ^ 8文字よりも小さいものは1バイトのデータとして登録されます。

同じ量のスペースを消費するので、VARCHAR <255の何かを残す基本文字を考慮する場合。

特に過剰な入力を削減したくない場合を除き、255は適切なベースライン定義です。


" ただし、2 ^ 8文字よりも小さいものは1バイトのデータとして登録されます "-間違っています。データベースには、VARCHARタイプで指定された数の文字のみが格納されます。列を宣言するときに、「登録」、予約、または初期化されるスペースはありません。
a_horse_with_no_name
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.