sql nvarchar(max)のパフォーマンスとスペースの分析およびvarchar(n)/ nvarchar(n)の長さのパフォーマンスと占有

sql nvarchar(max)のパフォーマンスとスペースの分析およびvarchar(n)/ nvarchar(n)の長さのパフォーマンスと占有

空間分析
でvarchar(n)およびnvarchar(n)のnを解釈する方法:
  nvarchar(n)は最大n文字を格納でき、中国語と英語を区別しません。
  Varchar(n)は最大nバイトを格納でき、中国語は2バイトです。

占有スペース:
nvarchar(n)1文字が2バイトのスペースを占有します。
   Varchar(n)中国語は2バイトを占め、英語は1バイトを占めます。

nの値の範囲:
nvarchar(n)nの範囲は次のとおりです:1から4000の間
   varchar(n)nの範囲は次のとおりです:1から8000の間

nのサイズはパフォーマンスに影響しますか?
varcharおよびnvarcharの長さnは、スペースのサイズとパフォーマンスに影響しません。nが最大で、コンテンツが4000または8000より大きい場合を除き
  、IDカードを18桁に制限したり、それ以上の場合はエラーを報告したり、悪意のある攻撃によるハードディスクの爆発を防止したりするなど、ビジネスニーズに合わせてnを設定します。スペースやパフォーマンスへの影響なし

nの設定の方が優れています:
スペースとパフォーマンスに影響がないため、ビジネスニーズのみを考慮する必要があります。Microsoftのデータベースを分析しましたが、ほとんどの場合、256、64、128、512、max、等も見られるので便利かもしれません覚えておいてください。

Varchar(n)、nvarchar(n)ストレージスペースの例の説明:
n文字を含む可変長Unicode文字データ。バイトのストレージサイズは、入力された文字数の2倍です。
   2つのフィールドにはそれぞれフィールド値があります:私とコーヒーの場合
   、varcharフィールドは2×2 + 6 = 10バイトのストレージスペースを占有し、nvarcharフィールドは8×2 = 16バイトのストレージスペースを占有します。
   フィールド値が英語のみの場合はvarcharを選択でき、フィールド値の2バイト文字(中国語、韓国語など)が多い場合は、nvarcharを使用します。

varcharとnvarcharを選択する方法は?
Varcharは1バイトを使用してSQLServerにデータを格納し、nvarcharはUnicodeを使用してデータを格納します。SQL Serverに格納されている中国語の文字は2バイト(通常はUnicodeエンコーディング)として格納され、英語の文字はデータベースに格納されます。フィールドタイプがvarcharの場合、1バイトのみを占有し、フィールドタイプがnvarcharの場合、 2バイトを占有します。

SQLは次のとおりです。

-- Subject     : nvarchar(n)及nvarchar(max)中的n及max是否会影响性能
-- Environment : Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (Intel X86) 
--               Apr  2 2010 15:53:02 
--               Copyright (c) Microsoft Corporation
--               Enterprise Evaluation Edition on Windows NT 5.2 <X86></X86> (Build 3790: Service Pack 2)
----------------------------------------------------------------------------------
--首先创建两个表,一个放nvarchar(4000),一个放nvarchar(max)

CREATE TABLE [dbo].[testnvarchar4000] (
id int IDENTITY (1, 1) ,
cnt nvarchar(4000)
) 
GO
CREATE TABLE [dbo].[testnvarcharmax] (
id int IDENTITY (1, 1) ,
cnt nvarchar(max)
)

GO

--然后插入10万条数据,每个cnt里放4000个字符(nvarchar(n)里n的最大值),大约1.6G


BEGIN TRANSACTION
    DECLARE @i INT ;
    SET @i = 0 ;
    while @i<100000
    begin
        insert into [testnvarchar4000] values(LEFT(REPLICATE(cast(@i as nvarchar)+'我是柳永法',1000),4000))
        insert into [testnvarcharmax] values(LEFT(REPLICATE(cast(@i as nvarchar)+'我是柳永法',1000),4000))
        set @i=@i+1
    END
COMMIT


--清空缓存,或重启SQL服务,测试查询速度及lob读取情况(lob是大对象的意思)
--测试testnvarcharmax
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

SET STATISTICS IO ON 
SET STATISTICS TIME ON
SELECT  COUNT(*)
FROM    testnvarcharmax
WHERE   cnt LIKE '%柳永法%'

SET STATISTICS TIME OFF
SET STATISTICS IO OFF

--测试testnvarchar4000
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE

SET STATISTICS IO ON 
SET STATISTICS TIME ON
SELECT  COUNT(*)
FROM    testnvarchar4000
WHERE   cnt LIKE '%柳永法%'

SET STATISTICS TIME OFF
SET STATISTICS IO OFF


--结果:
--(1 行受影响)
--表 'testnvarcharmax'。扫描计数 3,逻辑读取 100000 次,物理读取 8494 次,预读 99908 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
--
-- SQL Server 执行时间:
--   CPU 时间 = 1172 毫秒,占用时间 = 30461 毫秒。


--(1 行受影响)
--表 'testnvarchar4000'。扫描计数 3,逻辑读取 100000 次,物理读取 8523 次,预读 99916 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
--
-- SQL Server 执行时间:
--   CPU 时间 = 968 毫秒,占用时间 = 30038 毫秒。


--从结果可以看出,这两次读取时间基本相同,并且都没有lob读取,以上数据为多次测试结果。

 

--给testnvarcharmax前1000条字段长度+1,来测试是不是超过4000字就会使用lob读取
UPDATE testnvarcharmax SET cnt=cnt+'1' WHERE id <=1000

--结果:

--(1 行受影响)
--表 'testnvarcharmax'。扫描计数 3,逻辑读取 100000 次,物理读取 8292 次,预读 99696 次,lob 逻辑读取 900 次,lob 物理读取 83 次,lob 预读 0 次。
--
-- SQL Server 执行时间:
--   CPU 时间 = 1124 毫秒,占用时间 = 30318 毫秒。

--此结果显示使用了lob读取。但时间相差也不太大。


--字段值加倍,再测试:
UPDATE testnvarcharmax SET cnt=cnt+cnt WHERE id <=1000
--结果:

--(1 行受影响)
--表 'testnvarcharmax'。扫描计数 3,逻辑读取 100000 次,物理读取 8164 次,预读 99521 次,lob 逻辑读取 1000 次,lob 物理读取 101 次,lob 预读 0 次。
--
-- SQL Server 执行时间:
--   CPU 时间 = 1094 毫秒,占用时间 = 31095 毫秒。

通常の状況では、varcharを使用して中国語の文字を格納できますが、オペレーティングシステムが英語のオペレーティングシステムであり、中国語のフォントのサポートが包括的でない場合、中国語の文字がSQL Serverにvarcharとして格納されると文字化けが表示されます(表示されます) as ??)。また、通常の状況では、ホストは中国の環境をサポートするため、varcharを使用してデータを格納する場合、開発段階では検出されません。ほとんどの場合、展開中に問題は発生しません。

だが!デプロイされたホストが英語のオペレーティングシステムであり、中国語の環境をサポートしていない場合、問題が発生します。中国語を保存すると、すべてのvarcharフィールドが文字化けします(??として表示されます)。また、通常の状況では、これが間違ったデータ型を使用して保存されていることが原因であることがわかりません。中国語のフォントをインストールして、オペレーティングシステムのロケールを設定しようとします。これらのどれも問題を解決することはできません。問題を解決できる唯一のことは、データベースフィールドタイプをnvarchar(またはnchar)にパーソナライズすることです。プロジェクト管理に精通している友人は、展開段階でデータベースを変更することはひどいことであることを知っておく必要があります。

nvarcharを使用するもう1つの大きな利点は、文字列を判断するときに中国語と英語の文字の違いを考慮する必要がないことです。
  もちろん、nvarcharを使用して英語の文字を格納すると、ストレージスペースが2倍になります。ただし、ストレージコストがすでに非常に低い場合は、互換性を優先することで、より多くのメリットが得られます。
  
したがって、設計時にnvarcharを使用してデータを格納するようにしてください。フィールドが中国語を保存しないことが確実な場合にのみ、varcharを使用して保存してください

varchar(300)とvarchar(8000)の両方が同じ数の文字を格納する場合、パフォーマンスに違いはなく、ストレージの動作にも違いはありません。それらはすべて同じストレージ構造、2バイトのオフセット、2バイトの列番号を持っているため(テーブル内のすべての列がvarcharタイプの場合)。違いはストレージ容量だけです。
ほとんどのパフォーマンス比較は、varcharとchar、varcharとvarchar(max)に焦点を当てています。また、オフラインストレージ(SQL Server 2005でサポート)。

Varchar(max)(lobタイプ)はvarcharストレージとは異なります。
LOBデータが十分に小さい場合は、データをデータ行(行が配置されているデータページ)に直接格納することを検討できます。これにより、LOBページの追加の読み取りを回避し、LOBデータへのアクセス効率を向上させることができます(ストアデータページに直接あるLOBデータしきい値は、行内のテキストオプションによって設定されます。

LOBデータがこのしきい値を超える場合、または行のサイズが8060バイト(単一行の最大サイズ)を超える場合、LOBデータはLOBページに格納され、LOBページへの16バイトのポインターが格納されます。データページで予約されています。もちろん、そのアクセス効率は低くなります。
さらに、悪意のあるユーザーはこれを使用してディスクを「爆発」させる可能性があります。

おすすめ

転載: blog.csdn.net/qq_37192571/article/details/108886463