4.2 SQL Server數據庫物理結構
SQL Server將所有數據都存儲在文件中。這些文件被分成子結構,SQL Server管理這 些子結構來維護其中所包含數據的完整性、結構和邏輯組織。雖然本書只是提供有關SQL
Server 2008數據庫管理的入門級指導,但是對於新的數據庫管理員而言,了解像數據庫的 物理體系結構這樣的髙級主題還是很重要的。了解SQL Server如何存儲和維護數據有助於 更好地理解數據變更如何影響性能,以及更有效地診斷數據庫問題。
4 .2 .1 物理存儲數據類型
在學習數據的物理存儲之前,了解SQL Server存儲的數據類型非常重要。SQL Server 2008聯機叢書把數據類型分為以下7 個類別:
• 精確數字
• 近似數字
• 日期和時間
• 字符串
• Unicode字符串
• 二進制字符串
• 其他數據類型
雖然從可用性的角度來看數據類型時,這樣的分組很有意義,但與本節討論內容相關
的是數據是如何存儲的。SQL Server數據類型基本上可分為3 種存儲類型:定長數據類型、 變長數據類型和大型對象數據類型。在某些情況下,大型對象數據類型也可作為變長類型,
后面會予以解釋。本節中描述的數據類型僅可以為關聯數據的物理存儲指派表列數據類型。
這並不包括本章后面將講述的cursor和 table數據類型
1 .定長數據類型
定長數據類型的大小是固定的。用來存儲這些數據的內存或磁盤空間的大小不會變
化。下面列出了定長數據類型:
• bit—— bit是一個整型數據類型,支持的值是0 或 1。與其名稱的意義相反,對於8 位或更少的數據,bit數據類型實際上占用一個字節的空間。 • tinyint—— tinyint數據類型 使 用 1 字節的存儲空間來存儲0〜255之間的無符號整 數值。
• smallint-----smallint數據類型使用2 個字節的存儲空間來存儲一個有符號的整數,
其取值范圍為- 32 768〜32 767。
• int—— int數據類型使用4 個字節的存儲空間來存儲一個有符號的整數,其取值范
圍 為 - 2 147 483 648〜 2 147 483 647。
• bigint—— bigint數據類型使用8 個字節的存儲空間來存儲一個有符號的整數,其取
值范圍為- 9 223 372 036 854 775 808—9 223 372 036 854 775 807。
• decimal和 numeric------decimal和 numeric數據類型的功能是一樣的。一般應該采用
decimal數據類型,因為它對存儲的數據的描述性更好。基於使用方式,可以將decimal 數據類型設定為使用不同的固定存儲空間。
當使用decimal數據類型時,也可以指定 要存儲的數據的精度(P)和小數位數(s)。表示方式為deCimal(p,S)。精度和小數位數用 介於0〜38之間的正整數值指定。不過,小數位數值必須小於或等於精度值,而且
只能在指定了精度值的情況下才能指定。存儲空間取決於精度值,如表4-1所示。

smallmoney-----smallmoney 數據類型存儲介於- 214 748.3648〜214 748.3647 之間
的貨幣值。smallmoney數據類型精確到所存儲貨幣單位的萬分之一,占用4 個字
節空間。
• money------money 數據類型存儲介於- 922 337 203 685 477.5808〜922 337 203 685
477.5807之間的貨幣值。它精確到所存儲貨幣單位的萬分之一,占用8 個字節空間。
• real—— real數據類型是浮點型數字,所以它的值是近似的。real支持的值是介於
- 3.40E+38〜 - 1.18E — 38之間的負數、0 以及介於1.18E—38〜3.40E+38之間的
正數。它占用4 個字節的空間。
• float—— float數據類型是浮點型數字,因此其值也是近似值。float支持的值范圍 和所需的存儲空間取決於float的精度。精度表示為float (n),其中n 是用來存儲科 學記數法中尾數的位數。精度值允許介於1〜53之間。1〜24的精度值需要4 個字
節的存儲空間,25〜53的精度值需要8 個字節的存儲空間。對於默認的精度53來
說,float支持的值范圍是一1.79E+308-----2.23E—308的負數、0 以及2.23E—308〜 1.79E+308之間的正數。
• smalldatetime------smalldatetime數據類型用於存儲1900年 1 月 1 日到2079年 6 月
6 日之間的日期。它可以精確到分鍾,占用4 字節的空間。SQL Server在內部將 smalldatetime數據存儲為一對2 字節的整數。第一個2 字節整數用來存儲1900年 1月 1 日以來的日期,另一個2 字節整數是用來存儲零點之后的分鍾數。
• datetime-----datetime數據類型用於存儲1753年 1 月 1 日到9999年 12月 3 1 日之
間的日期和時間。它可以精確到3.33毫秒,占用8 字節的存儲空間。SQL Server 在內部將datetime數據存儲為一對4 字節的整數。第一個4 字節整數用來存儲1753 年 1 月 1 日以來的天數,第二個4 字節整數用來存儲零點之后的毫秒數(舍入到
3.33)O
• datetime2------datetime2數據類 型 是 datetime數據類型的擴展,支持更寬范圍的日
期和更髙的精度。它可用於存儲介於0001年 1 月 1 日至9999年 12月 31之間的
日期和時間,精確到100毫微秒。與 decimal和 numeric數據類型類似的是,它使 用可選精度聲明。秒小數部分的默認精度為7 位,即 100毫微秒。精度等於或小
於 3 時,存儲空間為6 個字節:精度為4 和 5 時為7 個字節;精度為6 和 7 時為8
個字節。
• datetimeoffset------datetimeoffset數據類型用於存儲介於0001年 1 月 1 日至9999年
12月 31之間的日期和時間,且相對於UTC(協調世界時)的時區偏移量范圍為負14
小時到正14小時。和 datetime2數據類型一樣,它精確到100毫微秒,使用可選的 精度聲明。
• date—— date數據類型用於存儲介於0001年 1 月 1 日至9999年 12月 31之間的日
期值、它精確到天,占用3 字節的存儲空間。SQL Server在內部將date數據存儲 為 3 字節的整數,用於存儲自0001年 1月 1 日以來的天數。
• time—— time數據類型用於存儲00:00:00.0000000至 23:59:59.9999999之間的時間
值。它精確到100毫微秒。與 decimal和 numeric數據類型類似,它使用可選精度 聲明。秒小數部分的默認精度為7 位,即 100毫微秒。精度小於3 時,存儲大小
為 3 個字節;精度為3 和 4 時為4 個字節;精度為5、6 和 7 時為5 個字節。
• char------char數據類型用來存儲1〜8000字符之間的定長非Unicode數據,表達式
為 charOi),其中n 是要存儲的字符數。每-個字符都需要1字節的存儲空間。
• nchar------nchar數據類 型 用 來 存 儲 1〜 4000字符之間的 定 長 Unicode數 據 ,
表達式 為
C
har(n),其 中 n 是要存儲的字符數。每一個字符都 需 要 2 字節的存儲空間。如 果必須支持多種語言,則 Unicode類型比較合適。 • binary------binary數據類 型 用 來 存 儲 1〜 8000字節之間的定量的二進制數據,表達 式 為 binary (n ),其 中 n 是要存儲的二進制字節數。
• rowversion 或 timestamp------rowversion 和 timestamp 數 據類型是同義詞,占用 8 字
節的存儲空間。任何情況下都要盡可能地指定rowversion而 不 是 timestamp,因為 rowversion更加准確地反映了數據類型的本質。timestamp數據類型跟時間完全無 關 。它實際上就是 一 個 8 字節的二進制字符串,用來定義表行的版本值。當
rowversion或 timestamp被指定為某表列的數據類型時,每一個對該表執行的插入 和更新操作都會 導 致 SQL Server生成一個新值,並放在合適的字段中。
• uniqueidentifier----- uniqueidentifier數據類型被存儲為一個 16字節的二進制字符串, 用 32個 16進制字符表 示 。SQL Server可 以使用NEWID()函 數生成uniqueidentifier, 或 插 入 現 有 的 uniqueidentifier並 存 儲 在 uniqueidentifier列 中 。
2 .變長數據類型和大型對象數據類型
當數據需要的具體空間數量無法預測時(例如保存一個人的姓的列),就需要使用變長
數據類型。varchar、nvarchar和 varbinary數據類型都屬於變長數據類型。
然而,當為字符串或二進制字符串的長度指定(MAX)選項時,就可以把這些可變數據
類型看作大型對象數據類型。其主要區別是數據的存儲方式。大型對象數據默認存儲在數
據行外部的單獨物理結構中,而變長數據存儲在數據行中。
下面介紹了這些數據類型:
• varchar------varchar數據類 型 用 來 存 儲 1〜 8000字 符 之 間 的 變 長 非 Unicode數 據 , 表達式是varcharOi),其 中 n 是存儲的最大字符數。每個字符都要求1 字節的存儲 空間。varchai•使用的實際存儲空間是n 值 加 上 2 字節。varchar數據類型還支持可
選的(MAX)長度指定。在 使 用 varchar (MAX)時,支持的最大字符量是2 147 483 647, 需要多達2GB的存儲空間。指定了(MAX)選項之后,SQL Server會 把 varchar數據
存儲在數據行中,除非數據黿超過了 8000字節,或者這么做會超過8060字節的
最大行大小。在這些情況下,SQL Server會 把 varchar數據移出行,存儲到一個單 獨的大型對象存儲空間中(參見本章后面的“數據頁” 一節)。
• nvarchar------nvarchar數據 類 型 和 varchar數 據 類 型 是 一 樣 的 ,只 是 它 用 來 存 儲 Unicode數據。每 個 Unicode字符都需要2 字節的存儲空間,這樣其支持的最大字
符 數 就 是 1 073 741 824。
• varbinary------varbinary數 據 類 型 也 和 varchar數據類型類似,只是它用來存儲二進
制數據而不是字符數據。除此之外,(MAX)選項的存儲和使用與上面介紹的一樣。
• text-----text數據類型是一個大型對象數據類型,和 varchar(MAX)數據類型很相似,
因為它也可以用來存儲多達2GB的字符數據。主要的區別在於text數據默認存儲 於數據行外部,而 且 text數據類型不能 作 為 SQL Server函數、存儲過程或觸發器 的參數傳遞。
• ntext—— ntext數據類型和text數據類型是一樣的,只是它用來存儲Unicode數據。 2GB的 Unicode字符數據只支持1 073 741 824個字符。 • image------image數據類型是一個大型對象數據類型,和 varbinary(MAX)數據類型
很相似。它也可以用來存儲多達2GB的二進制數據,但總是存儲在數據行外部的
單獨的大型對象數據頁中。
• XML—— XML數據類型是一個大型對象數據類型,用來以本地格式存儲XML。
每個數據行中可以存儲多達2GB的XML數據。
• sql variant----- 當不知道值的實際數據類型時,可以在對象中使用sql_variant數據 類型。sql_variant數據類型可以用來存儲任何 少 於 8000字節的值。和 sql_variant 類型不兼容的數據類型有text、ntext. image、timestamp、cursor、varchar (MAX) 和 nvarchar (MAX)。
3. CLR數據類型
SQL Server 2008包含3 個不同的基於CLR的數據類型。首先是hierarchyid,它用於管
理表結構中的分層數據。另外兩個是新的空間數據類型,用於表示幾何對象(比如國界、道
路和湖泊等)的物理位置和形狀信息。SQL Server 2008的空間數據類型遵循開放式地理空
間聯盟(OGC,Open Geospatial Consortium)的 Simple Features for SQL 的 1.1.0 版標准。 • hierarchyid------hierarchyid數據類型用於創建帶有分層結構的表或是引用另一位置
的數據的層次結構。所需的存儲空間取決於記錄數和行中的層次結構數。要為一
個有着100 000名雇員(被划分為7 個級別)的組織存儲層次號,需要5 個字節。行
越多並且划分的層次結構越多,所需的存儲空間越多。該數據類型被限制為892
個字節。
• geometry—— 這個類型表示歐幾里得(平面)坐標系中的數據。
• geography-----geography(地理空間)數據類型存儲楠球體(圓球)數據,例 如 GPS諱
度和經度坐標。
4. 行內數據
通過使用large value types out of row表選項,數據庫管理員可以指定將所有的varchar (MAX)、nvarchar (MAX)和 varbinary (MAX)數據都視為大型對象數據,並存儲在行外部的
單獨的大型對象數據頁上。可以將該選項設為ON或者O FF,如下所示:
sp_tableoption * tablename', 'large value types out of row1, *0N1 sp_tableoption 1tablename1, 'large value types out of row', 'OFF'
同樣,如果數據庫管理員想要在行中保存text或 ntext數據,直到它們超過了一個指 定的大小,那么可以指定表選項“text in row”。該選項允許數據庫管理員指定在行中保存 的數據的范圍。所支持的數據范圍是24〜7000字節。通過ON選項值,可設置默認值256
字節。要關閉此選項,則使用OFF:
sp_ tableoption * t a b l e n ^ m e ', 1 text in row'. * n u m b e r o f b y t e s 1
sp_ tableoption * ta b le n a m e * , 'text in row*, •ON,
sp_ tableoption ' ta b le n a m e 1 , * text in row*, •OFF*
4.2.2 FILESTREAM 數據
SQL Server 2008的一個增強功能是在數據庫外部存儲非結構化數據,如文本文檔、圖 像和視頻,但又鏈接至在其中定義列的行。通過將varbinary(MAX)二進制大型對象(BLOB)
數據存儲為文件系統上的文件,而不是存儲在數據庫數據文件中單獨的大型對象數據頁上,
FILESTREAM集成了數據庫引擎與NT文件系統。Transact-SQL語句可插入、更新、査詢
和備份FILESTREAM數據。
為了使用FILESTREAM,數據庫需要一個指派為FILESTREAM存儲區域的文件組。
下列示例演示了如何向AdventureWorks2008數據庫添加FILESTREAM文件組••
USE Master GO
ALTER DATABASE AdventureWorks2008 ADD FILEGROUP MyFilestreamGroup2 CONTAINS FILESTREAM
GO
ALTER DATABASE AdventureWorks2008 ADD FILE (NAME = N 'FileStreamData'
r
FILENAME = N ,D:\SQLData\FileStreamData,) TO FILEGROUP MyFilestreamGroup
GO
在向數據庫添加了新文件組后,可以添加或修改表,以將表的二進制大型對象數據作
為數據庫引擎管理的對象存儲到文件系統中。下列示例演示了如何創建使用FILESTREAM
存儲的表:
USE AdventureWorks2008
GO
CREATE TABLE MyLargeData (DocumentIdentifier uniqueidentifier ROWGUIDCOL NOT NULL UNIQUE ,DocumentFile VARBINARY(MAX) FILESTREAM NULL)
GO
記住,啟用FILESTREAM存儲的表必須有一個非NULL的唯一 ROWGUID列。要向
已有列添加FILESTREAM列,必須確保表有一個ROWGU1D列,否則必須添加一個。
4 .2 .3 其他數據類型
如前所述,SQL Server 2008中有兩種數據類型是表或索引定義的一部分,並不用於在 磁盤上物理存儲數據。這兩種數據類型用於在編程對象中操作數據。
• table一 table數據類型用於將一組數據行存儲在內存中。它主要與表值函數一起 使用,但也可用於任何編程對象來返回一個有組織的結果集—— 這個結果集擁有
實際表的大部分屬性。可以用一組列、一個指定的主鍵、CHECK約束和一個默認
約束來聲明和實例化一個table變量。
• cursor------Transact-SQL可以很好地執行數據集操作 ,但有時必須一次一行地操作
數據。cursor數據類型可以滿足此類要求。一個游標保存一組來自某個查詢的完整 數據行,可對游標進行操作,使其一次返回一行。要想了解有關游標及其用途的
完整討論,可 以 參 閱 Paul Turley和 Dan Wood編 寫 的 《T-SQL編程入門經典(涵蓋
SQL Server 2008 & 2005)》一 書 。
