
2008年6月24日
|
Feature
|
Table Variable
|
Temp Table
|
Note
|
|
Table Name
|
Max 128 characters
|
Max 116 characters
|
|
|
Data Storage
|
In memory and TempDB
|
TempDB
|
|
|
Meta Data
|
In memory
|
TempDB
|
A table variable inherits current database settings and can use the registered UDTs, user defined data types, and xml collections in the database. A temp table inherits the settings of TempDB and cannot use the types created in the user database if the same types do not exist in the TempDB.
|
|
Scope
|
Current batch
|
Current session
|
Temp tables created in a stored procedure (SP) can be referenced by dynamic queries in the SP, sub SPs, triggers fired by the affected tables of the SP.
|
|
Constraints
|
Allowed
|
Allowed
|
For table variables, since no DDL is allowed, constraints can not be created in separate DDL statements.
|
|
DDL
|
Not allowed
|
Allowed.
|
E.g. create Index on the temp table.
|
|
Concurrent
|
Supported
|
Supported
|
Constraints and Indexes with explicit name in a temp table cause duplicate name error.
|
|
Statistics
|
Not supported
|
Supported
|
Estimated row number in execution plan for table variable is always 1
|
|
Parallel execution plan
|
Supported only for select
|
Supported
|
Parallel query execution plans are not generated for queries that modify table variables.
|
|
Transaction and Locking
|
Not participated
|
Participated
|
Data in table variable is not affected if the transaction is rolled back
|
|
Cause Recompile
|
No
|
Yes
|
Temp Table creation causes SPs/batches to recompile
|
|
SELECT INTO <t>
|
Not supported
|
Supported
|
|
|
INSERT <t> EXEC
|
Not supported
|
Supported
|
|
|
Use
|
UDFs, Stored procedures, Triggers, Batches
|
Stored procedures, Triggers, Batches
|
Temp tables can't be used in UDFs.
|
from:http://www.sqlservercentral.com/articles/Table+Variables/63878/
Very Good~
posted @
2008-09-06 07:09 PerfectDesign 阅读(240) |
评论 (0) |
编辑
今天写段测试代码,发现在ff不可用,找了些原因,发现这个错误:
uncaught exception: ?(¹Õ XMLHttpRequest.open öCP ³
原来是跨域的问题,但是我的域没有问题啊?都是同样的二级子域,就是端口不一样,在ie下是好的呢
很是郁闷。所以只有改成一样的端口,另外,如果要真的想跨域,只有引入脚本块,就跟谷歌的统计一样
posted @
2008-08-22 10:33 PerfectDesign 阅读(2943) |
评论 (1) |
编辑
http://www.simple-talk.com/sql/performance/investigating-sql-server-2008-wait-events-with-xevents/
虽然我还不能安装sql2008,但是已经对他是垂涎欲滴了,多了解先,文中提到2008的bol越来越多的涉及到底层内幕,颇感欣慰,当然最好都能有中文版的,哈哈
posted @
2008-08-21 08:42 PerfectDesign 阅读(3149) |
评论 (0) |
编辑
摘要: 上一次只是讲了讲普通数据页面,后来自己回想一下,应该跟大家讲讲其他类型的页面,作为一个知识体系贯穿起来。 再长叹一声,我的兄弟因伤退赛,唉,真是可惜了..................
阅读全文
posted @
2008-08-18 16:32 PerfectDesign 阅读(5064) |
评论 (9) |
编辑
数据库的页构成
页
SQL Server中的页是最基本的数据单位组成,他有8KB,也就是8192个字节(mssql7.0以前是一个页面2KB),而sql server的一个页面,由页头,数据行,和slot table组成(行偏移的位置的记录数组。
页头
页头是一个固定的96字节的大小,他是一个页面的元数据,记载与本页相关的许多信息,具体的参数,大家可以参看我很久以前写的一篇文章,SQL server数据页页头参数列表,这篇文章没有太细致的对参数进行讲解,我在这里仔细说一下:
PAGEID:
页面的ID,在mssql中,唯一定位一行数据(包括索引)的,靠的是mssql里面的一个我把它称之为的三段式表达式:FPS ID,即 file id,page id,slot id。File ID 为文件ID,找到行所在的文件,pageID找到行所在的页面,slot ID为插槽ID,即这一行位于这个页面的第几个插槽。插槽的概念会在稍后提到。1:1:2表示这行数据位于第一个文件的第一个页面的第二个插槽。
Nextpage:
这个参数在页面处于页面链的时候,指示这个页面的下一个页面地址,这个的表达格式是 fileid:pageid,比如:1:2,请注意一下,这个页面指针并不是完全指向物理磁盘上的页面地址,因为外部碎片的存在!如果是堆表,那么这两个参数会是null。
objID:
在sysobjects 表内的对应的ID
Lsn:
Log sequence number ,日志序列号,他用来记录当这个页面行数据发生改变时的日志记录号,和此前版本的lsn,这个对于事务的管理非常重要,他将指示数据是否被回滚,或者被重做。
Slotcnt:
页面插槽总数。也就是这个页面有多少行。一个萝卜一个坑,一行数据一个槽。
Level:
在索引页中的级别,0为子叶节点。
Indexed:
0为普通数据页面(堆表),1为聚集索引页面,大于1都为非聚集索引。
Pminlen:
每行数据的固定长度,比如一行数据有3个int字段,1个char5的字段,2个varchar字段,那么固定长度是17.这个参数在mssql定位字段数据时起到至关重要的作用。
freeCnt:
页面空闲的字节数,在每次需要插入数据时就检测这个值,空间是否够用。
m_ghostRecCnt:
页面含有的幻影行的数目。幻影行是sql server在删除数据时,并不及时删除数据,而是仅仅将他标记为幻影行,并不对磁盘中的数据进行清空。这样做有非常大的好处。如果数据回滚,那么只需要将标记去掉即可。数据库会在空闲的时候将页面进行整理,去掉幻影行,而没有必要即时性的整理页面。
Slot table
插槽表是用于记录行在页内的逻辑顺序和物理顺序的对应数组。比如逻辑上是第一行的数据可能在这个页面内是物理上位于第二行。而这个物理上的位置,指的是在这个页面的8KB的空间内的位置,slottable有记录行的逻辑顺序数,物理顺序数,还有相对页头的偏移量,以便数据查找定位。在这里衍生的一个问题就是,逻辑上的行顺序可能存储在磁盘上的物理顺序也不会是一个顺序!(当然还有可能页面存在lob数据,成为一个页指针)
猜想:Slottable实际上是对空间的一个利用,当然也涉及到了当数据行进行增删改查时,对页面的破坏,最后在设计上导入了slot table。假设一个场景,当一个页面全部被填充满了,freecnt为0的时候,删除一个数据(页面存储100个数据,删除其中的第2个),那么如果根据正常的逻辑,应该是将2到第100行的数据全部移动,然后整理出末尾还剩一行的数据。这样现实吗?那样页面所有数据都要移动,似乎不大现实。所以mssql在设计上引入了slot table ,这样,物理上和逻辑上的顺序由slot table 映射起来,存储引擎负责向slot table 要数据位置,slot table负责映射其真正的物理位置,slottable在其中搭建起一个桥梁,降低了他们之间的耦合,使得当逻辑顺序发生变化的时候,物理位置却不需要相应的变化,哈哈,相信这个也是一个典型的设计上的解耦的例子吧~~
posted @
2008-08-17 22:02 PerfectDesign 阅读(5667) |
评论 (34) |
编辑
http://technet.microsoft.com/zh-cn/magazine/cc671165.aspx
SQL Server 高效维护数据库的关键技巧 是technet上的,都是些经验之谈。
posted @
2008-08-13 15:21 PerfectDesign 阅读(4592) |
评论 (0) |
编辑
目前的批量删除和批量更新,很是烦人,解决方案无非三种:
XML,SQL自定义函数split,和CLR实现split。这几种都比较烦人,代码很多,维护麻烦,很不爽。
现在sql2008新增的一个功能,我也不知道中文名怎么翻译,暂且叫他表参数吧。
大家可以看看示例:
这个就是用户定义的表类型:

然后给他定义一个类型:

Code
-- ================================
-- Create User-defined Table Type
-- ================================
USE Test
GO
-- Create the data type
CREATE TYPE dbo.MyType AS TABLE
(
col1 int NOT NULL,
col2 varchar(20) NULL,
col3 datetime NULL,
PRIMARY KEY (col1)
)
GO
可以看到,生成的表类型的组成情况,并且居然可以给表类型建立索引,呵呵

这个是操作 表类型的脚本:

Code
DECLARE @MyTable MyType
INSERT INTO @MyTable(col1,col2,col3)
VALUES (1,'abc','1/1/2000'),
(2,'def','1/1/2001'),
(3,'ghi','1/1/2002'),
(4,'jkl','1/1/2003'),
(5,'mno','1/1/2004')
SELECT * FROM @MyTable
下面演示如何将表参数作为一个存储过程参数传递,以及ADO.NET的代码
sql部分:

Code
USE [Test]
GO
CREATE TABLE [dbo].[MyTable] (
[col1] [int] NOT NULL PRIMARY KEY,
[col2] [varchar](20) NULL,
[col3] [datetime] NULL,
[UserID] [varchar] (20) NOT NULL
)
GO
CREATE PROC usp_AddRowsToMyTable @MyTableParam MyType READONLY,
@UserID varchar(20) AS
INSERT INTO MyTable([col1],[col2],[col3],[UserID])
SELECT [col1],[col2],[col3],@UserID
FROM @MyTableParam
GO
如何在sql中调用此存储过程:

Code
DECLARE @MyTable MyType
INSERT INTO @MyTable(col1,col2,col3)
VALUES (1,'abc','1/1/2000'),
(2,'def','1/1/2001'),
(3,'ghi','1/1/2002'),
(4,'jkl','1/1/2003'),
(5,'mno','1/1/2004')
EXEC usp_AddRowsToMyTable @MyTableParam = @MyTable, @UserID = 'Kathi'
SELECT * FROM MyTable
其中还涉及到一个权限问题,需要执行以下代码:

Code
GRANT EXECUTE ON TYPE::dbo.MyType TO TestUser;
从.net app那调用此存储过程:

Code
'Create a local table
Dim table As New DataTable("temp")
Dim col1 As New DataColumn("col1", System.Type.GetType("System.Int32"))
Dim col2 As New DataColumn("col2", System.Type.GetType("System.String"))
Dim col3 As New DataColumn("col3", System.Type.GetType("System.DateTime"))
table.Columns.Add(col1)
table.Columns.Add(col2)
table.Columns.Add(col3)
'Populate the table
For i As Integer = 20 To 30
Dim vals(2) As Object
vals(0) = i
vals(1) = Chr(i + 90)
vals(2) = System.DateTime.Now
table.Rows.Add(vals)
Next

Code
'Create a command object that calls the stored proc
Dim command As New SqlCommand("usp_AddRowsToMyTable", conn)
command.CommandType = CommandType.StoredProcedure
'Create a parameter using the new type
Dim param As SqlParameter = command.Parameters.Add("@MyTableParam", SqlDbType.Structured)
command.Parameters.AddWithValue("@UserID", "Kathi")

Code
'Set the value of the parameter
param.Value = table
'Execute the query
command.ExecuteNonQuery()
详情可以参看:
http://www.sqlteam.com/article/sql-server-2008-table-valued-parameters
posted @
2008-08-11 12:18 PerfectDesign 阅读(2457) |
评论 (3) |
编辑
摘要: 本篇文章将由粗到细,讲解数据库的物理组成结构。有些东西可能是废话或是摘抄自BOL,等权威文章,但是作为一个知识体系结构,还是需要啰嗦一下。还包括了一些性能优化方面的知识。
阅读全文
posted @
2008-08-08 16:22 PerfectDesign 阅读(3842) |
评论 (11) |
编辑
摘要: 终于决定自己动手写一个了,以前一直是在看别人的文章,也是因为自己的文笔不好,另外也是怕自己被人喷,但是还是鼓足勇气自己写上一个优化系列吧,算是对我这些日子对SQl Server数据库优化工作的一个总结。
阅读全文
posted @
2008-08-08 09:50 PerfectDesign 阅读(3653) |
评论 (23) |
编辑
SQL优化--使用 EXISTS 代替 IN 和 关联查询(inner join) 昨天的这篇文章提及到的一些问题,在这里我做一下自己的测试,测试结果以微软标准Adventureworks数据库内数据结构为准。
测试语句:

Code
set statistics io on
set statistics time on
select a.* from Production.Product a inner join Production.ProductModel b
on (a.ProductModelID = b.ProductModelID)
select a.* from Production.Product a where exists (select 'X' from Production.ProductModel b
where a.ProductModelID = b.ProductModelID)
select a.* from Production.Product a where a.ProductModelID in (select b.ProductModelID from Production.ProductModel b)
测试统计:

Code
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 15 毫秒,占用时间 = 63 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
(9440 行受影响)
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Product'。扫描计数 1,逻辑读取 474 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'ProductModel'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
SQL Server 执行时间:
CPU 时间 = 63 毫秒,占用时间 = 1984 毫秒。
(9440 行受影响)
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Product'。扫描计数 1,逻辑读取 474 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'ProductModel'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
SQL Server 执行时间:
CPU 时间 = 78 毫秒,占用时间 = 1780 毫秒。
(9440 行受影响)
表 'Worktable'。扫描计数 0,逻辑读取 0 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'Product'。扫描计数 1,逻辑读取 474 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
表 'ProductModel'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
(1 行受影响)
SQL Server 执行时间:
CPU 时间 = 109 毫秒,占用时间 = 1366 毫秒。
SQL Server 分析和编译时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 1 毫秒。
执行计划


可以看到无论是查询计划还是统计IO,都是一样的。
这都是优化器的功劳,并不存在哪个谓词就好些,除非你的测试环境是2000以下。
posted @
2008-08-06 09:04 PerfectDesign 阅读(2226) |
评论 (8) |
编辑
查到有这样一段话,很耗CPU资源:

Code
set statistics io on
set statistics time on
SELECT TOP 10 FeedBackID,UserID,ContentID,[Content],
Time,AddType,IP FROM CYZoneFeedBack
where contentid in (select articleid from cyzonearticle where userid=@user and delflag=0 and publishtype<>'b')
and CYZoneFeedBack.DelFlag =0 order by CYZoneFeedBack.Time desc
分析是这样的:

原来是排序造成了这么多开销。罪魁祸首在于 order by CYZoneFeedBack.Time 这句话,后改成:

Code
set statistics io on
set statistics time on
SELECT TOP 10 FeedBackID,UserID,ContentID,[Content],
Time,AddType,IP FROM CYZoneFeedBack
where contentid in (select articleid from cyzonearticle where userid=107and delflag=0 and publishtype<>'b')
and CYZoneFeedBack.DelFlag =0 order by CYZoneFeedBack.feedbackid desc
执行计划变为:

很明显省掉了排序的操作。有时候,排序和时间是有相关性的,而聚集索引,没有建在时间上,会导致排序成本的增加,恰当的利用自增ID来做时间排序,也能省掉很多开销。
posted @
2008-08-01 14:15 PerfectDesign 阅读(504) |
评论 (1) |
编辑
前一篇post经常性登录失败问题,http://www.cnblogs.com/perfectdesign/archive/2008/06/24/sql_login_problem.html
目前已经没有了,我总结了一下,问题应该是出现在连接串内使用了持久化安全性和windows验证这2个选项,这个选项导致在有其他应用程序在审核失败后,其安全性可能又被数据库延续了下来,所以导致失败。在修改连接串后数据库恢复正常。
posted @
2008-07-31 17:04 PerfectDesign 阅读(1997) |
评论 (0) |
编辑
方法一,是我自己经常用到的:

Code
select a.name,b.text from sys.sysobjects a inner join syscomments b
on a.id = b.id and b.text like '%你要找的字符串%'
方法二:
刚在外文资料上看到的:

Code
--Declare whatever you can :)
Declare @SString nvarchar(50)
Declare @getdbname sysname
Declare @sqlstm nvarchar(1000)
Declare dbname cursor for
--get all the names of the Databases in order by name
Select '['+name+']' from master.dbo.sysdatabases order by name
open dbname
--Get the first Name
FETCH NEXT FROM dbname into @getdbname
WHILE @@FETCH_STATUS=0
BEGIN
--set the search string
SET @SString = '<Place the String Here>'
--append the search pattern
SET @SString = '%' + @SString + '%'
--set the statement to define the search condition, with variables
SET @sqlstm = '
Select Specific_Catalog as Database_Name, Routine_Name as ''Stored Procedure Name'',Routine_Definition
From '+ @getdbname+'.Information_Schema.Routines
Where PatIndex('+''''+@SString+''''+', Routine_Definition) > 0'
--Execute the Query
EXEC (@sqlstm)
FETCH NEXT FROM dbname into @getdbname
END
--Close the Cursor and Deallocate it from memory
Close dbname
Deallocate dbname
(出处:http://www.sqlservercentral.com/scripts/Search/63397/)
第二个用的cursor查找,所有库的,二者范围不一样。
供大家急需时参考。
posted @
2008-07-31 16:58 PerfectDesign 阅读(141) |
评论 (0) |
编辑
调试了半天时间,却发现原来这个webclient的方法太垃圾了,后改为
UploadData,纪念一下,原来这个是 vs2005的bug........
posted @
2008-07-28 16:02 PerfectDesign 阅读(2676) |
评论 (0) |
编辑
一位DBA朋友狼总结了一个关于此方面的几个原则,其实我们在设计的时候也是在不经意间也遵循了这些原则,拿来跟大家共享一下,特别有感于这些天面试程序员,简历上写精通数据库设计,一问就说几个范式,其他冗余的数据都是垃圾,偶真是比较汗颜啊。。。。
不废话了,原则如下:
反规范化设计
为了提升性能而使用反规范化设计
常用方法:
A、在多个表中存储某个字段的副本
B、在父表中存储汇总值
C、将活动数据和历史数据分开存储
D、应用程序本地缓存数据
E、使用临时表、中间表、索引视图
大家如果还有其他原则,可以跟帖,谢谢!
posted @
2008-07-14 14:35 PerfectDesign 阅读(3824) |
评论 (5) |
编辑
最近我的一位好朋友,先是母亲检查出来已经是癌症晚期,然后父亲又发现胃癌,昨晚喝酒,朋友说我这些天白头发多了不少,哎,一切都是关于健康的消息,想想自己也曾经熬夜奋战,也曾经斗志昂扬,再想想健康,自己的脊椎,从颈部到腰,都时常疼痛,朋友们,工作的同时也不要忽略了自己的健康。
posted @
2008-07-08 13:40 PerfectDesign 阅读(3631) |
评论 (8) |
编辑
Storing data in a scalable web application can be tricky. A user
could be interacting with any of dozens of web servers at a given time,
and the user's next request could go to a different web server than the
one that handled the previous request. All web servers need to be
interacting with data that is also spread out across dozens of
machines, possibly in different locations around the world.
Thanks to Google App Engine, you don't have to worry about any of
that. App Engine's infrastructure takes care of all of the
distribution, replication and load balancing of data behind a simple
API—and you get a powerful query engine and transactions as well.
The App Engine datastore has a sophisticated query engine for data
models. Because the App Engine datastore is not a traditional
relational database, queries are not specified using SQL. Instead, you
can prepare queries using a SQL-like query language we call GQL. GQL
provides access to the App Engine datastore query engine's features
using a familiar syntax.
posted @
2008-06-29 18:09 PerfectDesign 阅读(5111) |
评论 (0) |
编辑
摘要:
阅读全文
posted @
2008-06-29 17:15 PerfectDesign 阅读(5426) |
评论 (0) |
编辑
这个问题困扰我好几天了,生产数据库上时常会出现
用户 'xxxx' 登录失败。 [客户端: <local machine>] (来自事件管理器)
但是服务器重启后就好了,数