SQL Server 2005では、nvarchar(255)のように、長さを明示的に指定するのではなく、すべての文字フィールドをnvarchar(MAX)にすることの欠点はありますか?(データベースレベルでフィールド長を制限できないことは明らかですが)
SQL Server 2005では、nvarchar(255)のように、長さを明示的に指定するのではなく、すべての文字フィールドをnvarchar(MAX)にすることの欠点はありますか?(データベースレベルでフィールド長を制限できないことは明らかですが)
回答:
同じ質問がMSDNフォーラムで質問されました:
元の投稿から(そこに多くの情報があります):
データをVARCHAR(N)列に格納すると、値は物理的に同じ方法で格納されます。ただし、VARCHAR(MAX)列に格納すると、画面の背後でデータはTEXT値として処理されます。そのため、VARCHAR(MAX)値を処理するときに必要な追加処理がいくつかあります。(サイズが8000を超える場合のみ)
VARCHAR(MAX)またはNVARCHAR(MAX)は「大きな値の型」と見なされます。大きな値型は通常「行外」に格納されます。これは、データ行に「大きな値」が格納されている別の場所へのポインターがあることを意味します...
N/VARCHAR(MAX)
「サイズが8000を超えた場合のみ」という追加の処理があるので「いいえ、使っても不都合はありません」と答えました。したがって、必要な場合にのみコストが発生し、データベースの制限が緩和されます。私はこれを間違って読んでいますか?ほとんどの場合、あなたが望むN/VARCHAR(MAX)
よりはむしろN/VARCHAR(1-8000)
…
sp_tableoptions
/ en-us / library / ms173530.aspxなどのより多くの要因に基づいて行からプッシュされます。VARCHAR(255)型も行からプッシュできます。前述の「オーバーヘッド」は、MAXと255でまったく同じになる場合があります。MAX型とTEXT型が異なる場合、MAX型とTEXT型を比較します(操作するAPIが完全に異なる場合、別のストレージなど)。実際の違いについては言及していません。MAXタイプではインデックスもオンライン操作もありません
それは公正な質問であり、彼は明白なものとは別に述べました...
短所は次のとおりです。
パフォーマンスへの影響クエリオプティマイザーはフィールドサイズを使用して、最も効率的な実行計画を決定します
"1.データベースの拡張とページのスペース割り当ては柔軟です。したがって、更新を使用してフィールドに情報を追加する場合、新しいデータが以前に挿入されたものより長い場合、データベースはポインタを作成する必要があります。これにより、データベースファイルは断片化する=インデックスから削除、更新、挿入まで、ほとんどすべてのパフォーマンスが低下する。 " http://sqlblogcasts.com/blogs/simons/archive/2006/02/28/Why-use-anything-but-varchar_2800_max_2900_.aspx
統合への影響-他のシステムがデータベースと統合する方法を知るのが難しい予測できないデータの増加考えられるセキュリティの問題、たとえば、すべてのディスク領域を占有してシステムをクラッシュさせる可能性
ここに良い記事があります:http : //searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1098157,00.html
varchar(max)
。
承認された回答で提供されたリンクに基づいて、次のように表示されます:
に保存されている100文字 nvarchar(MAX)
フィールドにフィールドに格納される100文字と同じです。nvarchar(100)
データはインラインで格納されるため、「行外」でデータを読み書きするオーバーヘッドがありません。だから心配はありません。
サイズが4000より大きい場合、データは自動的に「行外」に格納されますが、これは必要なことです。だからそこにも心配はありません。
しかしながら...
nvarchar(MAX)
列にインデックスを作成することはできません。フルテキストインデックスを使用できますが、列にインデックスを作成してクエリのパフォーマンスを向上させることはできません。私にとって、これは契約を結びます...常にnvarchar(MAX)を使用することは明らかに不利です。結論:
インデックスを作成でき、スペースとアクセス時間を無駄にしない、データベース全体で一種の「ユニバーサルな文字列長」が必要な場合は、を使用できますnvarchar(4000)
。
nvarchar(max)
いつも使用しないのstring
ですか-C#のように?-しかし、ポイント3)(インデックスの問題)が答えを与えています。
nvarchar(4000)
場合によっては、データタイプにデータ内のデータに何らかの意味を持たせたいことがあります。
たとえば、実際には20文字を超えてはならない列があるとします。その列をVARCHAR(MAX)として定義すると、一部の不正なアプリケーションが長い文字列を挿入する可能性があり、それを知らない、またはそれを防ぐ方法がありません。
次にアプリケーションがその文字列を使用するとき、文字列の長さがそれが表すドメインにとって控えめで妥当であるという想定の下で、予測不能で混乱する結果が発生します。
私はいくつかの記事をチェックし、これから有用なテストスクリプトを見つけました:http : //www.sqlservercentral.com/Forums/Topic1480639-1292-1.aspx 次に、NVARCHAR(10)とNVARCHAR(4000)とNVARCHAR(MAX )そして、指定された数値を使用してもMAXを使用すると速度の違いはわかりません。自分でテストできます。これがお役に立てば幸いです。
SET NOCOUNT ON;
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(10)
DECLARE @SomeString NVARCHAR(10),
@StartTime DATETIME;
--=====
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='10', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(4000)
DECLARE @SomeString NVARCHAR(4000),
@StartTime DATETIME;
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='4000', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(MAX)
DECLARE @SomeString NVARCHAR(MAX),
@StartTime DATETIME;
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='MAX', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
最大フィールドまたはテキストフィールドを使用しない理由は、SQL Server Enterprise Editionを使用していても、オンラインインデックスの再構築、つまりREBUILD WITH ONLINE = ONを実行できないためです。
、私が見つけた唯一の問題は、我々は、SQL Server 2005の上の私たちのアプリケーションを開発することで、一つの例では、我々は、私はちょうど学んだSQL Serverの2000をサポートする必要がハードな方法 SQL Server 2000はvarchar型のためにMAXオプション好きではないということかnvarchar。
フィールドが設定された範囲(たとえば、5〜10文字)になることがわかっている場合は、悪い考えです。長さがどうなるかわからない場合のみ、maxを使用すると思います。たとえば、電話番号が特定の文字数を超えることはありません。
テーブルのすべてのフィールドのおおよその長さの要件について不確かであると正直に言えますか?
私はあなたの要点を理解しています-私が確かにvarchar(max)の使用を検討するいくつかのフィールドがあります。
興味深いことに、MSDNドキュメントはそれをかなりうまくまとめています:
列データエントリのサイズが大幅に異なる場合は、varcharを使用します。列データエントリのサイズが大幅に異なり、サイズが8,000バイトを超える可能性がある場合は、varchar(max)を使用します。
データベースの仕事は、企業が使用できるようにデータを格納することです。そのデータを有用なものにすることの一部は、それが有意義であることを保証することです。名に無制限の文字を入力できるようにしても、意味のあるデータが得られるとは限りません。
これらの制約をビジネスレイヤーに組み込むことは良い考えですが、データベースがそのまま残るとは限りません。データルールに違反していないことを保証する唯一の方法は、データベースで可能な限り低いレベルでルールを実施することです。
1つの問題は、SQL Serverの複数のバージョンを操作する必要がある場合、MAXが常に機能するとは限らないことです。そのため、レガシーDBや、複数のバージョンに関連するその他の状況で作業している場合は、十分に注意する必要があります。
1)nvarchar(max)とnvarchar(n)を処理する場合、SQLサーバーはより多くのリソース(割り当てられたメモリとCPU時間)を使用する必要があります。ここで、nはフィールドに固有の数値です。
2)パフォーマンスに関してこれはどういう意味ですか?
SQL Server 2005では、15個のnvarchar(max)列を持つテーブルから13,000行のデータをクエリしました。クエリのタイミングを繰り返してから、列をnvarchar(255)以下に変更しました。
最適化前のクエリの平均は2.0858秒でした。変更後のクエリは、平均1.90秒で戻りました。これは、基本的なselect *クエリに対する約184ミリ秒の改善でした。これは8.8%の改善です。
3)私の結果は、パフォーマンスの違いがあったことを示した他のいくつかの記事と一致しています。データベースとクエリに応じて、改善の割合は異なります。多数の同時ユーザーまたは非常に多くのレコードがない場合は、パフォーマンスの違いは問題になりません。ただし、レコード数と同時ユーザー数が増えるほど、パフォーマンスの違いは大きくなります。
(すべての列の)行のすべてのデータが合理的に8000文字以下になることがない場合は、データ層の設計でこれを強制する必要があります。
データベースエンジンは、ブロブストレージからすべてを除外することで、はるかに効率的です。小さいほど、行を制限できます。ページに詰め込むことができる行が多いほど良いです。より少ないページにアクセスする必要がある場合、データベースのパフォーマンスは向上します。
私のテストでは、選択するときに違いがあることが示されています。
CREATE TABLE t4000 (a NVARCHAR(4000) NULL);
CREATE TABLE tmax (a NVARCHAR(MAX) NULL);
DECLARE @abc4 NVARCHAR(4000) = N'ABC';
INSERT INTO t4000
SELECT TOP 1000000 @abc4
FROM
master.sys.all_columns ac1,
master.sys.all_columns ac2;
DECLARE @abc NVARCHAR(MAX) = N'ABC';
INSERT INTO tmax
SELECT TOP 1000000 @abc
FROM
master.sys.all_columns ac1,
master.sys.all_columns ac2;
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
SELECT * FROM dbo.t4000;
SELECT * FROM dbo.tmax;
興味深いリンク:TEXTを使用できるのに、なぜVARCHARを使用するのですか?
それはPostgreSQLとMySQLに関するものなので、パフォーマンス分析は異なりますが、「明示性」のロジックは依然として成り立ちます。電子メールアドレスを変数に保存した場合、「80文字に制限された文字列」ではなく「文字列」を使用します。
私が見ることができる主な欠点は、あなたがこれを持っているとしましょう:
UIに必要なデータについて最も多くの情報を提供するものはどれですか。
この
CREATE TABLE [dbo].[BusData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[RecordId] [nvarchar](MAX) NULL,
[CompanyName] [nvarchar](MAX) NOT NULL,
[FirstName] [nvarchar](MAX) NOT NULL,
[LastName] [nvarchar](MAX) NOT NULL,
[ADDRESS] [nvarchar](MAX) NOT NULL,
[CITY] [nvarchar](MAX) NOT NULL,
[County] [nvarchar](MAX) NOT NULL,
[STATE] [nvarchar](MAX) NOT NULL,
[ZIP] [nvarchar](MAX) NOT NULL,
[PHONE] [nvarchar](MAX) NOT NULL,
[COUNTRY] [nvarchar](MAX) NOT NULL,
[NPA] [nvarchar](MAX) NULL,
[NXX] [nvarchar](MAX) NULL,
[XXXX] [nvarchar](MAX) NULL,
[CurrentRecord] [nvarchar](MAX) NULL,
[TotalCount] [nvarchar](MAX) NULL,
[Status] [int] NOT NULL,
[ChangeDate] [datetime] NOT NULL
) ON [PRIMARY]
それともこれ?
CREATE TABLE [dbo].[BusData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[RecordId] [nvarchar](50) NULL,
[CompanyName] [nvarchar](50) NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[ADDRESS] [nvarchar](50) NOT NULL,
[CITY] [nvarchar](50) NOT NULL,
[County] [nvarchar](50) NOT NULL,
[STATE] [nvarchar](2) NOT NULL,
[ZIP] [nvarchar](16) NOT NULL,
[PHONE] [nvarchar](18) NOT NULL,
[COUNTRY] [nvarchar](50) NOT NULL,
[NPA] [nvarchar](3) NULL,
[NXX] [nvarchar](3) NULL,
[XXXX] [nvarchar](4) NULL,
[CurrentRecord] [nvarchar](50) NULL,
[TotalCount] [nvarchar](50) NULL,
[Status] [int] NOT NULL,
[ChangeDate] [datetime] NOT NULL
) ON [PRIMARY]
1つの欠点は、予測できない変数を中心に設計することであり、行、ページ、およびエクステントで構成される内部SQL Serverデータ構造を利用する代わりに、おそらく無視することになります。
それは私に考えさせます 、Cでのデータ構造のアラインメントアラインメントを認識することは、一般的には良いこと(TM)と見なされます。同様のアイデア、異なるコンテキスト。
ページとエクステントの MSDNページ
行オーバーフローデータの MSDNページ
最初はこれについて考えましたが、次にもう一度考えました。パフォーマンスには影響がありますが、フィールドの実際のサイズを把握するためのドキュメントとしても役立ちます。そして、そのデータベースがより大きなエコシステムに存在する場合は強制されます。私の意見では、鍵は寛容であることですが、理にかなった範囲内である必要があります。
わかりました、これがビジネスとデータレイヤーロジックの問題についての私の気持ちです。それは、DBがビジネスロジックを共有するシステム間の共有リソースである場合、もちろん、そのようなロジックを適用するのに自然な場所であるように見えますが、それを行う最善の方法ではなく、APIを提供することが最善の方法です。これにより、テストされる相互作用と、ビジネスロジックが属する場所での相互作用、システムの分離、システム内の層の分離が維持されます。ただし、データベースが1つのアプリケーションのみにサービスを提供することになっている場合、アジャイルを考えてみましょう。今、何が本当ですか?今のところデザイン。そのようなアクセスが必要な場合は、そのデータにAPIを提供してください。
もちろん、これは理想的な方法です。既存のシステムを使用している場合は、少なくとも短期的には別の方法で実行する必要がある可能性があります。
これにより、パフォーマンスの問題が発生しますが、データベースが小さい場合は実際の問題が発生することはありません。一度に多くのレコードを検索する場合、各レコードはハードドライブ上のより多くのスペースを占有し、データベースはディスクのより多くのセクターを読み取る必要があります。たとえば、小さなレコードは50をセクターに、大きなレコードは5を収めることができます。大きなレコードを使用して、ディスクから10倍のデータを読み取る必要があります。
nvarchar(max)
列にある場合よりも多くのディスク領域を必要としませんnvarchar(100)
。