sql中NVARCHAR(MAX) 性能和占空間分析 varchar(n),nvarchar(n) 長度性能及所占空間分析


varchar(n),nvarchar(n) 中的n怎么解釋:
  nvarchar(n)最多能存n個字符,不區分中英文。
  varchar(n)最多能存n個字節,一個中文是兩個字節。

所占空間:

  nvarchar(n)一個字符會占兩個字節空間。
  varchar(n)中文占兩字節空間,英文占一個。

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,則會占用兩個字節.

 代碼如下 復制代碼

----------------------------------------------------------------------------------
-- 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就會出現亂碼(顯示為??).而且正常情況下,主機都會支持中文的環境,所以如果使用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 字節的指針。其訪問效率當然會將低。
另外還有,惡意用戶可以利用這一點“撐爆”你的磁盤。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM