想说一下动手做实验的重要性
想说一下动手做实验的重要性
前言
有时候一个人会有很多想法,或者当你看到别人的文章的时候你会有想法,又或者想验证一下别人的观点
这时候就需要自己动手做实验来验证了,想法无处不在
比如:我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
再使用下面代码看一下表中的数据页是哪一个
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 输出了错误信息,请与系统管理员联系。
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
--------------------------------------------------------------------