昨天被一个高手骂了
我的数据库字段,大部分都使用的nvarchar(max)。他说这样很浪费我的空间。。并且查询效率很低。
应该用varchar类型,我知道nvarchar(max)字段实际是可以支持2G。
但是我实际并没有使用它啊,不知道各位有什么观点。
我的数据库字段,大部分都使用的nvarchar(max)。他说这样很浪费我的空间。。并且查询效率很低。
应该用varchar类型,我知道nvarchar(max)字段实际是可以支持2G。
但是我实际并没有使用它啊,不知道各位有什么观点。
0 = varchar(max)、nvarchar(max)、varbinary(max)、xml 和大型 UDT 值直接存储在数据行中(最大限制值为 8000 个字节,只要记录中可以容纳该值)。 如果记录中容纳不下该值,则指针存储在行内,其余内容存储在 LOB 存储空间内的行外。 0 为默认值。
参考:
http://msdn.microsoft.com/zh-cn/library/ms173530.aspx在没有必要用varchar(max)的情况下,还是建议用varchar(n),杀鸡焉用牛刀...
02.-- Subject : nvarchar(n)及nvarchar(max)中的n及max是否会影响性能
03.-- Author : 柳永法(yongfa365) http://www.yongfa365.com/ [email protected]
04.-- CreateDate : 2010-11-22 23:31:04
05.-- Environment : Microsoft SQL Server 2008 R2 (RTM) - 10.50.1600.1 (Intel X86)
06.-- Apr 2 2010 15:53:02
07.-- Copyright (c) Microsoft Corporation
08.-- Enterprise Evaluation Edition on Windows NT 5.2 <X86></X86> (Build 3790: Service Pack 2)
09.----------------------------------------------------------------------------------
10.--首先创建两个表,一个放nvarchar(4000),一个放nvarchar(max)
11.
12.CREATE TABLE [dbo].[testnvarchar4000] (
13.id int IDENTITY (1, 1) ,
14.cnt nvarchar(4000)
15.)
16.GO
17.CREATE TABLE [dbo].[testnvarcharmax] (
18.id int IDENTITY (1, 1) ,
19.cnt nvarchar(max)
20.)
21.
22.GO
23.
24.--然后插入10万条数据,每个cnt里放4000个字符(nvarchar(n)里n的最大值),大约1.6G
25.
26.
27.BEGIN TRANSACTION
28. DECLARE @i INT ;
29. SET @i = 0 ;
30. while @i<100000
31. begin
32. insert into [testnvarchar4000] values(LEFT(REPLICATE(cast(@i as nvarchar)+'我是柳永法',1000),4000))
33. insert into [testnvarcharmax] values(LEFT(REPLICATE(cast(@i as nvarchar)+'我是柳永法',1000),4000))
34. set @i=@i+1
35. END
36.COMMIT
37.
38.
39.--清空缓存,或重启SQL服务,测试查询速度及lob读取情况(lob是大对象的意思)
40.--测试testnvarcharmax
41.DBCC DROPCLEANBUFFERS
42.DBCC FREEPROCCACHE
43.
44.SET STATISTICS IO ON
45.SET STATISTICS TIME ON
46.SELECT COUNT(*)
47.FROM testnvarcharmax
48.WHERE cnt LIKE '%柳永法%'
49.
50.SET STATISTICS TIME OFF
51.SET STATISTICS IO OFF
52.
53.--测试testnvarchar4000
54.DBCC DROPCLEANBUFFERS
55.DBCC FREEPROCCACHE
56.
57.SET STATISTICS IO ON
58.SET STATISTICS TIME ON
59.SELECT COUNT(*)
60.FROM testnvarchar4000
61.WHERE cnt LIKE '%柳永法%'
62.
63.SET STATISTICS TIME OFF
64.SET STATISTICS IO OFF
65.
66.
67.--结果:
68.--(1 行受影响)
69.--表 'testnvarcharmax'。扫描计数 3,逻辑读取 100000 次,物理读取 8494 次,预读 99908 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
70.--
71.-- SQL Server 执行时间:
72.-- CPU 时间 = 1172 毫秒,占用时间 = 30461 毫秒。
73.
74.
75.--(1 行受影响)
76.--表 'testnvarchar4000'。扫描计数 3,逻辑读取 100000 次,物理读取 8523 次,预读 99916 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
77.--
78.-- SQL Server 执行时间:
79.-- CPU 时间 = 968 毫秒,占用时间 = 30038 毫秒。
80.
81.
82.--从结果可以看出,这两次读取时间基本相同,并且都没有lob读取,以上数据为多次测试结果。
83.
84.
85.
86.--给testnvarcharmax前1000条字段长度+1,来测试是不是超过4000字就会使用lob读取
87.UPDATE testnvarcharmax SET cnt=cnt+'1' WHERE id <=1000
88.
89.--结果:
90.
91.--(1 行受影响)
92.--表 'testnvarcharmax'。扫描计数 3,逻辑读取 100000 次,物理读取 8292 次,预读 99696 次,lob 逻辑读取 900 次,lob 物理读取 83 次,lob 预读 0 次。
93.--
94.-- SQL Server 执行时间:
95.-- CPU 时间 = 1124 毫秒,占用时间 = 30318 毫秒。
96.
97.--此结果显示使用了lob读取。但时间相差也不太大。
98.
99.
100.--字段值加倍,再测试:
101.UPDATE testnvarcharmax SET cnt=cnt+cnt WHERE id <=1000
102.--结果:
103.
104.--(1 行受影响)
105.--表 'testnvarcharmax'。扫描计数 3,逻辑读取 100000 次,物理读取 8164 次,预读 99521 次,lob 逻辑读取 1000 次,lob 物理读取 101 次,lob 预读 0 次。
106.--
107.-- SQL Server 执行时间:
108.-- CPU 时间 = 1094 毫秒,占用时间 = 31095 毫秒。
----------------------------------------------------------------------------------
-- Subject : nvarchar(n)及nvarchar(max)中的n及max是否会影响性能
-- Author : 柳永法(yongfa365) http://www.yongfa365.com/ [email protected]
-- CreateDate : 2010-11-22 23:31:04
-- 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 (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 FREEPROCCACHESET 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 FREEPROCCACHESET 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 毫秒。
从以上结果基本上可以证明自己文章头提到的观点,nvarchar(n)或nvarchar(max)中的n及max只是一个符号,不会影响占用空间及性能,除非max存储字符数大于4000,所以我们只要关注实际业务需要就可以了,