《Microsoft Sql server 2008 Internals》读书笔记--第五章Table(1)

《Microsoft Sql server 2008 Internals》索引目录:

《Microsoft Sql server 2008 Internal》读书笔记--目录索引

 

   在这章中,我们将对表(table)作一些简单的介绍,并继续深入察看表的一些内部结构。简单的说,表是具有一些特定意义的实体的集合。表不仅是 MS SQL Server的心脏,也是更广泛意义上的关系数据模型更是如此。在SQL Server中,表通常更多的与Base table同义,称它为基表是为了和视图(View)所对应的virtual table相区别。这些virtaul table并不存放真正的实体数据。

  需要了解的基本概念包括:Row、Column、Primary Key、foreign key、

  对表的操作可以方便的使用UI前端工具。但这里主要讨论使用SQL语句。

  命名表和列

  一个表总是被一个数据库的一个架构(Schema)所创建。表总是有所有者(Owners),但不像SQL2005之前, (SQL2005/SQL2008中)表的所有者不用于访问表,而架构管理所有对象的访问。在删除一个对象时,往往需要先转移该对象的架构,这就是为什么 有时候想删除对象却显示“架构正在使用中”之类的提示。通常一个表被创建在默认的架构中,但可以在Create Table时定义架构。而架构中用户的创建只能通过Alter语句实现。在syadmin、db_ddladmin、db_owner角色可以在任意一个 数据库里创建创建何意一个架构。数据库中可以有相同有表名,只要架构不同即可。一个表的全名如下:数据库名.架构名.表名。默认的架构是dbo,在某些情 况下,可能会有四部分,比如有链接服务器时。
  关于Create table的详细说明,请参照MSDN:
http://msdn.microsoft.com/zh-cn/library/ms174979.aspx
http://msdn.microsoft.com/zh-cn/library/ms189462.aspx

  注意:sys是一外特殊的架构,它具有最高的优先级 。如果你自定义了一个对象名为sysobjects,你将会发现,你永远访问不了它。另外,兼容性视图也能通过dbo架构被访问。比如 sys.sysobjects和dbo.sysobjects是一样的。为了区别类视图(catalog views)和动态管理对象(Dynamic Management Objects),你必须定义访问对象的sys架构。

  命名建议:尽量不要包含关键字:比如字段想取“状态”,不要使用state,SQL2000下关键字,Status,SQL2005/2008 关键字,可以用CurState,这样易于理解的名称。即便你用[state]保证sql语句不出错,但这会增加SQl Server的解析成本。

  至于列及列相关的更多资料,请参看MSDN:

http://msdn.microsoft.com/zh-cn/library/ms187742.aspx

  更多的数据类型的资料,请参看MSDN。值得一提的是,根据MSDN提示,SQL2005以后版本新增的varchar(max)和 Nvarchar(Max)最大可以存储最大为 2^31-1 个字节的数据.即2G左右,由于SQL Server采用了更优的存储和读取机制,性能更优!所以请尽量使用 varchar(max)、nvarchar(max) 和 varbinary(max)  数据类型,而不要使用 text、ntext 和 image  数据类型。
  这里重点谈谈NULL

  关于NULL的神奇(Much Ado About NULL)

   关于" NULL是否应该存在" 的争论从来没有消停过,我不想惹恼一些人而成为口水的中心。然而,务实地讲,NULL在MS SQL SERVER中应该是被尽量限制使用的。这从两方面看出:

  1、使用NULL将增加存储引擎的复杂性。SQL Server在每一行保持一个bitmap来表明可空列是否真的是null,如果Null被允许,那么每访问一行数据时,SQL Server必须解码这个bitmap。

  2、允许NULL值,会增加应用程序的复杂性。你必须得增加特定的逻辑代码,以防止出现各种意外的bug。

  作为一个数据库设计人员,你可能理解NULL和三值逻辑在合计函数方面的细微差异。(这句邀月不理解,原文是:As a database designer,you might understand the nuances of NULL and three-valued logic in aggregate functions when you do joins and when you search by values.)因为程序开发人员的理解跟你的想法很难达成 一致。如果可能的话,每一个字段都加上not NULL,并且指定默认值。

  在任何情况下,创建一个表时明确的使用NOT NULL或NULL是一个最佳实践(Best practise)如果指定,那么SQL 默认是Not NULL,而不是很多人想像中的allow NUlls。 引起这种误解的原因是与SQL相关的绝大多数工具和界面都允许Nulls。当然你可以修改默认的会话为“允许Nulls”,如果你不担心你的查询结果和别 的没有修改过默认会话的SQL Server不同的话,你完全可以那么做。

  你可以通过以下几项来修影响默认的NULL选项:

   1、使用GETANSINULL来决定在当前会话中是否允许Nulls,不过还是强烈推荐创建一个列时显式定义它NULL或Not NULL

  2、使用数据库选项SET CONTACT_NULL_YIELDS_NULL在会话中设置。当该开关打开时,select 'abc'+null的结果为null。而关闭时,select 'abc'+null的结果为'abc';

  3、使用数据库选项SET ANSI_NULLS。(后续版本的 Microsoft SQL Server 将删除该功能。请避免在新的开发工作中使用该功能,并着手修改当前还在使用该功能的应用程序。http://msdn.microsoft.com/zh-cn/library/ms188048%28SQL.90%29.aspx )

  当该开关打开时,所有与Null比较时先被鉴定为Unknown,此时,你必须使用Isnull来判断是否有一个Null Value,(这是否就是下个版本被关闭的原因?)关闭时,如果是Null,返回true,此时,SQL 允许使用=null来代替is null和<>null来代替is not null

  4、使用ANSI_DEFAULTS来设置。它相当于同时使用ANSI_NULLS和ANSI_NULL_DFLT_ON

  下面的查询显示了当前会话下的状态:  

select * from sys.dm_exec_sessions
where session_ID=@@spid

  以下是一些关于NULL的基本技巧:

  1、在你的表中永远不允许Null值

  2、在表定义中使用明确的NOT NULL修饰符

  3、不依赖于数据库的关于NULL的任何设置

  如果确有需要使用Null列,SQL Server 2008建议使用稀疏列(sparse column)的概念。稀疏列是对 Null 值采用优化的存储方式的普通列。稀疏列减少了 Null 值的空间需求,但代价是检索非 Null 值的开销增加。当至少能够节省 20% 到 40% 的空间时,才应考虑使用稀疏列。稀疏列和列集是通过使用 CREATE TABLE 或 ALTER TABLE 语句定义的。关于稀疏列的更多知识,请参看MSDN:
http://msdn.microsoft.com/zh-cn/library/cc280604.aspx

  下面将重点关注表的内部存储方式。

posted @ 2010-01-23 16:13  邀月  阅读(1953)  评论(4编辑  收藏  举报