恭喜您!在你面前就只剩下幾頁了,然后你就可以完成第1個月的SQL Server性能調優培訓了。今天我將講下頁的一些限制,還有為什么你會喜歡這些限制,同時也會討厭這些限制。
正如你在第2周學到的,數據頁始終是8kb 的大小,而且你只能在上面存儲8060 bytes。你的記錄大小指示你在一個頁里可以存儲多少記錄。當你與像CHAR,INT,DATETIME等定長類型數據類型打交道時,你會發現SQL Server有記錄長度不能超過8060 bytes長度(包含7 bytes 的內部行開銷)的限制。
頁面限制——好的一面當你的表少于8列時,你需要(為每條記錄)增加額外7 bytes 的內部行開銷。對每增加的8列都要增加額外的1 byte, 例如,17列,你需要9 btyes的內部行開銷(7+1+1)。如果你嘗試創建更長的記錄大小,SQL Server會在你執行CREATE TABLE語句時返回一個錯誤信息給你。來看看下面的表定義:
1 CREATE TABLE TooLargeTable12 (3 Column1 CHAR(5000),4 Column2 CHAR(3000),5 Column3 CHAR(54)6 )7 GO
正如你所見,每條記錄需要8061 bytes(5000+3000+54+7 bytes)。因此在這種情況下,當你嘗試去創建這個表時,SQL Server會返回下列的錯誤信息。
當你創建超過8列的表時,你需要把SQL Server需要的8 bytes的行內部開銷也算進去。
1 CREATE TABLE TooLargeTable22 (3 Column1 CHAR(1000) NOT NULL, Column2 CHAR(1000) NOT NULL,4 Column3 CHAR(1000) NOT NULL, Column4 CHAR(1000) NOT NULL,5 Column5 CHAR(1000) NOT NULL, Column6 CHAR(1000) NOT NULL,6 Column7 CHAR(1000) NOT NULL, Column8 CHAR(1000) NOT NULL,7 Column9 CHAR(53) NOT NULL8 )9 GO
因此這里又是一個非法的表定義(8000+53+8 bytes),這里SQL Server會返回一個錯誤信息。
在上一環節我已經向你展示了頁面限制你喜歡的一面,因為當你在創建這樣表的時候,SQL Server會返回你一個錯誤信息。但是頁面限制也有你討厭的一面,因為SQL Server會允許你創建這樣的表,而且有時INSERT語句執行成功,有時卻會失敗……我們來看下。
這里我們面對的問題是與像VARCHAR等變長數據類型。當這些列不能存在它本身頁時,SQL Server會把它們移動到在另外頁面的行偏移位置。這個被稱為 行溢出頁(Row-Overflow page)。SQL Server會在原來的頁面留下24 bytes長的指向行溢出頁的指針。
在于其他列組合時的某些情況下,這個指針會溢出8060 bytes的限制。我們來看下下面的表定義:
1 CREATE TABLE TooLargeTable32 (3 Column1 CHAR(5000),4 Column2 CHAR(3000),5 Column3 CHAR(30),6 Column4 VARCHAR(3000)7 )8 GO
如你所見,這里我使用了VARCHAR(3000)的數據類型。你會看到SQL Server這里會給你一個警告信息。這個警告提示你可以創建這個表,但在執行INSERT/UPDATE語句時可能會失敗……
下面在表里的插入語句會成功:
1 INSERT INTO TooLargeTable3VALUES2 (3 REPLICATE('x', 5000),4 REPLICATE('x', 3000),5 REPLICATE('x', 30),6 REPLICATE('x', 19)7 )8 GO
這里的記錄大小是8056 bytes長(5000+3000+30+19+7 bytes)。在這個情況下,SQL Server會把第4列的數據保存在主數據頁。但是想像下下面的INSERT語句:
1 INSERT INTO TooLargeTable3VALUES2 (3 REPLICATE('x', 5000),4 REPLICATE('x', 3000),5 REPLICATE('x', 30),6 REPLICATE('x', 3000)7 )8 GO
在剛才的INSERT語句,SQL Server會把第4列數據移到行溢出頁(row-overflow page),因為這3000 bytes 不能在主數據頁里放下。這也就意味著SQL Server會在這里留下一個指向不同頁且24bytes 長的指針,在那個位置可以找到數據。但是我們的記錄大小現在是8061 bytes長(5000+3000+30+24+7 bytes)。
Duang,你的記錄長度超過8060 bytes,INSERT語句執行失敗了!
這些就是壞的限制,因為他們在數據庫操作的時候隱藏著,好的一面就是在你定義表架構的時候如上所示可見的。想想看是啥?
小結在你設計你的表結構時,你要非常仔細的想下你的操作。在SQL Server里與頁打交道時你會碰到很多這樣的執行進去后才出現的限制。當然,在SQL Server給你錯誤信息時,你不允許創建這個表,基本上就天下太平了。
當當你收到警告時,基本上每個人會想不都不想下就忽略掉。這始終是個壞的操作,因為你已經看到了,你的INSERT可能在運行時失敗,問題的發生你是可以預見的。我希望你現在已經明白這個性能調優培訓是個很好內幕公開,并且為什么理解數據頁的內部結構是多么重要!
在接下來的培訓我會講解SQL Server中堆表的更多細節,還有為什么它們有時是好的(設計),有時候卻是不好的(設計) 。請繼續關注,并且好好享受剩下的7天!
新聞熱點
疑難解答