sqlnvarchar(max)性能和占空间分析与varchar(n)nvarchar(n。。。sql nvarchar(max)性能和占空间分析与varchar(n)/nvarchar(n) 长度性能及所占
空间分析
varchar(n),nvarchar(n) 中的n怎么解释:
nvarchar(n)最多能存n个字符,不区分中英⽂。
varchar(n)最多能存n个字节,⼀个中⽂是两个字节。
所占空间:
nvarchar(n)⼀个字符会占两个字节空间。
varchar(n)中⽂占两字节空间,英⽂占⼀个。
varchar2最大长度n的取值范围:
nvarchar(n) n的范围是:1与4000之间
varchar(n) n的范围是:1与8000之间
n的⼤⼩是否会影响性能:
varchar及nvarchar⾥的长度 n 不会影响空间⼤⼩及性能。除⾮n是max并且内容⼤于4000或8000
设置n更多的是业务需要,如限制⾝份证只能输⼊18位,再多就报错,或者防⽌恶意攻击撑爆硬盘。对空间及性能都没有影响
n设置多⼤⽐较好:
既然对空间及性能都没有影响,那我们只要考虑业务需要就可以了,我分析过微软的数据库,⼤都设置为:256,也会看到
64,128,512,max等,可能是便于记忆吧。
varchar(n),nvarchar(n)存储空间举例解释:
包含 n 个字符的可变长度 Unicode 字符数据。字节的存储⼤⼩是所输⼊字符个数的两倍。
两字段分别有字段值:我和coffee
那么varchar字段占2×2+6=10个字节的存储空间,⽽nvarchar字段占8×2=16个字节的存储空间。
如字段值只是英⽂可选择varchar,⽽字段值存在较多的双字节(中⽂、韩⽂等)字符时⽤nvarchar。
varchar和nvarchar如何选择?
varchar在SQL Server中是采⽤单字节来存储数据的,nvarchar是使⽤Unicode来存储数据的.中⽂字符存储到SQL Server中会保存为两个字节(⼀般采⽤Unicode编码),英⽂字符保存到数据库中,如果字段的类型为varchar,则只会占⽤⼀个字节,⽽如果字段的类型为nvarchar,则会占⽤两个字节。
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
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 次。
--表 '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就会出现乱码(显⽰为??).⽽且正常情况下,
主机都会⽀持中⽂的环境,所以如果使⽤varchar来存储数据,在开发阶段是发现不了的.多数情况下,在布署的时候也不会有问题。
但是!如果布署的主机是英⽂操作系统,并且不⽀持中⽂环境,那问题就出来了.所有的varchar字段在存储中⽂的时候都会变成乱码(显⽰为??).⽽且⼀般情况下你不会知道这是因为你采⽤了错误的数据类型来存储所造成的,你会试着去装中⽂字体,试着去设置操作系统的语⾔环境...这些都不能解决问题,唯⼀能解决问题的是把数据库字段的类型个性为nvarchar(或者nchar).对项⽬管理⽐较熟悉的朋友应该都知道,到布署阶段再来修改数据库是⼀个很恐怖的事情.
使⽤nvarchar的另⼀个⾮常好处就是在判断字符串的时候可以不需要考虑中英⽂两种字符的差别.
当然,使⽤nvarchar存储英⽂字符会增⼤⼀倍的存储空间.但是在存储代价已经很低廉的情况下,优先考虑兼容性会给你带来更多好处的.
所以在Design的时候应该尽量使⽤nvarchar来存储数据.只有在你确保该字段不会保存中⽂的时候,才采⽤varchar来存储
如果 varchar(300) 和 varchar(8000) 都存储相同的字符数,性能上是没有差别的,存储⾏为上也没有不同。因为它们都有相同的存储结构,两个字节的偏移,两个字节的列数(如果表中所有的列都是 varchar 类型)。区别只在于存储容量上。
⼤多数的性能⽐较都集中在 varchar 和 char,varchar 和 varchar(max) 上。还有,⾏外存储(SQL Server 2005 ⽀持的)。
varchar(max) (lob 类型)与 varchar 存储⽅式是不同的。
当 LOB 数据⾜够⼩时,可以考虑将数据直接存储在数据⾏(⾏所在的数据页⾯)中,从⽽可以避免额外的读取 LOB 页⾯,提升访问 LOB 数据的效率(将 LOB 数据直接存储在数据页⾯的阈值由 text in row 选项设置)。
⽽当 LOB 数据⼤于此阈值,或者所在⾏的⼤⼩超过了 8060 字节(单⾏最⼤ SIZE),LOB 数据将会存储在 LOB 页⾯,⽽在数据页⾯中保留⼀个指向 LOB 页⾯的 16 字节的指针。其访问效率当然会将低。
另外还有,恶意⽤户可以利⽤这⼀点“撑爆”你的磁盘。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论