想說一下動手做實驗的重要性
前言
有時候一個人會有很多想法,或者當你看到别人的文章的時候你會有想法,又或者想驗證一下别人的觀點
這時候就需要自己動手做實驗來驗證了,想法無處不在
比如:我delete了一條資料,我能不能通過事務日志[fn_dblog]()把他恢複呢?如果能恢複我能不能寫一個
資料庫恢複工具來恢複已經delete了的資料???
您需要不斷地去想,用自己所學到的知識去設計實驗并證明自己的想法
再比如:我現在看到一篇文章《SQL Server中使用帶有Persisted值的計算列》
文章位址:http://database.ctocio.com.cn/dbzjdysummary/48/8730048.shtml
想法:究竟帶有Persisted值的計算列資料會不會存儲到磁盤上???
帶着這個疑問,我們做一下下面實驗
動手實驗環節
使用下面SQL代碼建立測試環境
1 --建立測試表
2 USE [tempdb]
3 GO
4 CREATE TABLE [dbo].[CCtest]
5 (
6 [empNumb] [int] NULL ,
7 [DOBirth] [datetime] NULL ,
8 [DORetirement] AS ( DATEADD(year, ( 60 ), [DOBirth]) - ( 1 ) ) PERSISTED
9 )
10 GO
11
12 --插入測試資料
13 USE [tempdb]
14 GO
15 INSERT INTO CCTest ( empNumb, DOBirth )
16 SELECT 30, '1985-12-13'
17 UNION ALL
18 SELECT 25, '1980-11-18'
19 UNION ALL
20 SELECT 21, '1978-01-19'
21 UNION ALL
22 SELECT 7, '1985-12-13'
23 UNION ALL
24 SELECT 5, '1975-07-23'
25 GO
26
27 SELECT * FROM dbo.CCTest
28 GO
View Code
再使用下面代碼看一下表中的資料頁是哪一個
1 --建立一個表,用來儲存DBCC IND的結果
2 USE [tempdb]
3 GO
4 CREATE TABLE DBCCResult
5 (
6 PageFID NVARCHAR(200) ,
7 PagePID NVARCHAR(200) ,
8 IAMFID NVARCHAR(200) ,
9 IAMPID NVARCHAR(200) ,
10 ObjectID NVARCHAR(200) ,
11 IndexID NVARCHAR(200) ,
12 PartitionNumber NVARCHAR(200) ,
13 PartitionID NVARCHAR(200) ,
14 iam_chain_type NVARCHAR(200) ,
15 PageType NVARCHAR(200) ,
16 IndexLevel NVARCHAR(200) ,
17 NextPageFID NVARCHAR(200) ,
18 NextPagePID NVARCHAR(200) ,
19 PrevPageFID NVARCHAR(200) ,
20 PrevPagePID NVARCHAR(200)
21 )
22 GO
23
24 --PageType 頁面類型:1:資料頁面;2:索引頁面;3:Lob_mixed_page;4:Lob_tree_page;10:IAM頁面
25 --
26 --IndexID 索引ID:0 代表堆, 1 代表聚集索引, 2-250 代表非聚集索引 大于250就是text或image字段
27
28
29 INSERT INTO DBCCResult EXEC ('DBCC IND(tempdb,CCtest,-1) ')
30
31 SELECT * FROM [dbo].[DBCCResult] ORDER BY [PageType] DESC
可以看到資料頁是78
用下面SQL語句看一下資料頁78的内容
1 DBCC TRACEON(3604,-1)
2 GO
3 DBCC PAGE([tempdb],1,78,3)
4 GO
1 DBCC 執行完畢。如果 DBCC 輸出了錯誤資訊,請與系統管理者聯系。
2
3 PAGE: (1:78)
4
5
6 BUFFER:
7
8
9 BUF @0x03E63850
10
11 bpage = 0x16248000 bhash = 0x00000000 bpageno = (1:78)
12 bdbid = 2 breferences = 0 bUse1 = 5146
13 bstat = 0x1c0000b blog = 0x2159bbbb bnext = 0x00000000
14
15 PAGE HEADER:
16
17
18 Page @0x16248000
19
20 m_pageId = (1:78) m_headerVersion = 1 m_type = 1
21 m_typeFlagBits = 0x4 m_level = 0 m_flagBits = 0x8008
22 m_objId (AllocUnitId.idObj) = 88 m_indexId (AllocUnitId.idInd) = 256
23 Metadata: AllocUnitId = 72057594043695104
24 Metadata: PartitionId = 72057594038714368 Metadata: IndexId = 0
25 Metadata: ObjectId = 37575172 m_prevPage = (0:0) m_nextPage = (0:0)
26 pminlen = 24 m_slotCnt = 6 m_freeCnt = 7949
27 m_freeData = 285 m_reservedCnt = 27 m_lsn = (37:284:165)
28 m_xactReserved = 27 m_xdesId = (0:1007) m_ghostRecCnt = 0
29 m_tornBits = 0
30
31 Allocation Status
32
33 GAM (1:2) = ALLOCATED SGAM (1:3) = ALLOCATED
34 PFS (1:1) = 0x61 MIXED_EXT ALLOCATED 50_PCT_FULL DIFF (1:6) = CHANGED
35 ML (1:7) = NOT MIN_LOGGED
36
37 Slot 0 Offset 0x60 Length 27
38
39 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
40 Memory Dump @0x080FC060
41
42 00000000: 10001800 1e000000 00000000 a07a0000 †.............z..
43 00000010: 00000000 3ad00000 0300f8†††††††††††††....:......
44
45 Slot 0 Column 0 Offset 0x4 Length 4
46
47 empNumb = 30
48
49 Slot 0 Column 1 Offset 0x8 Length 8
50
51 DOBirth = 12 13 1985 12:00AM
52
53 Slot 0 Column 2 Offset 0x10 Length 8
54
55 DORetirement = 12 12 2045 12:00AM
56
57 Slot 1 Offset 0x7b Length 27
58
59 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
60 Memory Dump @0x080FC07B
61
62 00000000: 10001800 19000000 00000000 ee550000 †.............U..
63 00000010: 00000000 88ab0000 0300f8†††††††††††††...........
64
65 Slot 1 Column 0 Offset 0x4 Length 4
66
67 empNumb = 25
68
69 Slot 1 Column 1 Offset 0x8 Length 8
70
71 DOBirth = 03 25 1960 12:00AM
72
73 Slot 1 Column 2 Offset 0x10 Length 8
74
75 DORetirement = 03 24 2020 12:00AM
76
77 Slot 2 Offset 0x96 Length 27
78
79 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
80 Memory Dump @0x080FC096
81
82 00000000: 10001800 15000000 00000000 5b6f0000 †............[o..
83 00000010: 00000000 f5c40000 0300f8†††††††††††††...........
84
85 Slot 2 Column 0 Offset 0x4 Length 4
86
87 empNumb = 21
88
89 Slot 2 Column 1 Offset 0x8 Length 8
90
91 DOBirth = 01 19 1978 12:00AM
92
93 Slot 2 Column 2 Offset 0x10 Length 8
94
95 DORetirement = 01 18 2038 12:00AM
96
97 Slot 3 Offset 0xb1 Length 27
98
99 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
100 Memory Dump @0x080FC0B1
101
102 00000000: 10001800 07000000 00000000 a07a0000 †.............z..
103 00000010: 00000000 3ad00000 0300f8†††††††††††††....:......
104
105 Slot 3 Column 0 Offset 0x4 Length 4
106
107 empNumb = 7
108
109 Slot 3 Column 1 Offset 0x8 Length 8
110
111 DOBirth = 12 13 1985 12:00AM
112
113 Slot 3 Column 2 Offset 0x10 Length 8
114
115 DORetirement = 12 12 2045 12:00AM
116
117 Slot 4 Offset 0xcc Length 27
118
119 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
120 Memory Dump @0x080FC0CC
121
122 00000000: 10001800 05000000 00000000 cc6b0000 †.............k..
123 00000010: 00000000 66c10000 0300f8†††††††††††††....f......
124
125 Slot 4 Column 0 Offset 0x4 Length 4
126
127 empNumb = 5
128
129 Slot 4 Column 1 Offset 0x8 Length 8
130
131 DOBirth = 07 23 1975 12:00AM
132
133 Slot 4 Column 2 Offset 0x10 Length 8
134
135 DORetirement = 07 22 2035 12:00AM
136
137
138 DBCC 執行完畢。如果 DBCC 輸出了錯誤資訊,請與系統管理者聯系。
View Code
1 Slot 4 Offset 0xcc Length 27
2
3 Record Type = PRIMARY_RECORD Record Attributes = NULL_BITMAP
4 Memory Dump @0x080FC0CC
5
6 00000000: 10001800 05000000 00000000 cc6b0000 †.............k..
7 00000010: 00000000 66c10000 0300f8†††††††††††††....f......
8
9 Slot 4 Column 0 Offset 0x4 Length 4
10
11 empNumb = 5
12
13 Slot 4 Column 1 Offset 0x8 Length 8
14
15 DOBirth = 07 23 1975 12:00AM
16
17 Slot 4 Column 2 Offset 0x10 Length 8
18
19 DORetirement = 07 22 2035 12:00AM
可以看到[DORetirement]列真的存儲到磁盤上
那麼計算列是怎麽通過計算插入到表中,或者更新表的[DOBirth]列是怎麽順帶更新[DORetirement]列的??
我們可以看一下執行計劃,從執行計劃中看能否看出端硯
這裡應該使用SET STATISTICS PROFILE ON 才行,用圖形化的執行計劃看不到每個運算符裡面具體做了什麼
1 SET STATISTICS PROFILE ON
2 GO
3 INSERT INTO [dbo].[CCtest] ( [empNumb], [DOBirth] )
4 VALUES ( 89, -- empNumb - int
5 '2013-08-22 11:48:46' -- DOBirth - datetime
6 )
在插入之前已經做了dateadd函數的計算,也就是在“計算标量”這個運算符裡做的
更新語句也是一樣
1 SET STATISTICS PROFILE ON
2 GO
3 UPDATE CCtest SET DOBirth = '1960-03-25' WHERE empnumb = 25
4 GO
可以看到update語句和insert語句都有“計算标量”運算符,dateadd函數的運算就在“計算标量”運算符裡做的
個人意見
其實,做完實驗還可以寫一篇博文把實驗過程記錄下來,例如在部落格園裡寫文章,以後很大機會會用到的
我個人建議寫成博文比較好,或許您的想法還可以繼續深入研究,當您以後遇到跟您的想法差不多的問題解決方案的時候,這時候您就能夠體會到
把想法寫成博文的好處,您能夠針對之前寫的博文繼續深入研究或者修正之前博文的錯誤
在工作中當大夥讨論某個解決方案的時候,你就更有底氣了,你可以根據自己做過的實驗給出自己的解決方案,而不是人雲亦雲
可能您自己的解決方案不是最合适的,但是最起碼您為解決方案出了自己的一份力,甚至您可以把自己的博文拿出來給大家看證明自己的觀點
當然實驗環境跟真實環境會有很大差别,但是最起碼您大概會估計得到有什麼後果,并且知道個中的原理
例如:某個表查詢很慢,你會想到加索引,那麼加聚集索引好呢?還是加非聚集索引好呢?
加了之後副作用會不會很大呢?你做過實驗之後,知道聚集索引和非聚集索引的差別,
結合目前情況,我相信您可以作出正确選擇
如果有一些問題沒有實驗環境,或者做實驗也解決不了,或者自己達不到那個水準不知道怎樣做,這時候沒辦法了,隻能請教高人了
或者寄希望于日後,能否出現您遇到的問題并且有相應的實驗環境
既然這些簡單的實驗隻需要兩三分鐘的事情,為什麽自己不親自動手做一下實驗呢?o(∩_∩)o
--------------------------------------------------------------------
題外話
可能您寫出來的文章,做出來的實驗沒有人評論,沒有人能糾正自己的錯誤,我做的實驗結果不知道對不對,這時候不要洩氣
除了别人主動看你的文章,你也要主動看别人的文章,我的習慣就是看到好文章馬上copy到evernote裡
當然将别人的知識化為自己的并了解透徹需要很長時間的
本人關注了園子裡300多人,收藏了非常多的文章 ,我相信一定有人在日後能夠看到自己寫的文章,做的實驗并作出評論的
相信自己!!!
如有不對的地方,歡迎大家強烈拍磚o(∩_∩)o