数据库(MsServer)
Sep 27

什么是数据库分区(分片) what is  DB partition
什么是数据库分区?
数据库分区是一种对表的横向分割,Sql server 2005企业版和之后的Sql server版本才提供这种技术,这种对表的横向分割不同于2000中的表分割,它对访问用户是透明的,用户并不会感觉的表被横向分割了。(2000中的表横向分割是建n个表例如按时间建表每月一个表,表名不同,最后需要做一个大视图)

为什么要分区?
显而易见分区是为了提高数据库的读写性能,提高数据库的效率;

分区是否总是可以提高效率?
分区是一把双刃剑,并不总能提高效率,这和具体情况有关系。
之所以有分区技术,分区技术用的好的话可以提高性能,是因为一方面分区把一大块数据分成了n小块,这样查询的时候很快定位到某一小块上,在小块中寻址要快很多;另一方面CPU比磁盘IO快很多倍,而硬件上又有多个磁盘,或者是RAID(廉价磁盘冗余阵列),可以让数据库驱动CPU同时去读写不同的磁盘,这样才有可能可以提高效率。
分区在有些时候并不能提高读写效率,比如说我们经常看到的按照日期字段去分区MSDN例子,这个实例中是按照记录的生成时间来分区的,把一年的数据分割成12个分区,每月一个。这样的分区导致分区并不能实现CPU同步写并提高写入性能,因为在同一个时段CPU总是要写入到最新的那一个分区对应的磁盘中。另一个问题是:这样分区是否可以提高读取性能呢?答案是不一定,要看根据什么字段来查询,如果是根据时间来查询,根据时间生成报表那么这种分区肯定会提高查询的效率,但是如果是按照某个客户查询客户最近1年内的账单数据,这样数据分布到不同的分区上,这样的话效率就不一定能提高了,这要看数据在同一个分区上连续分布的读性能高,还是CPU从几个磁盘上同步读取,然后在合并数据的性能更高一些,这和读取数据的记录数也有关系。

如何分区?用什么字段做分区依据?
具体如何分区和涉及的业务有关系,要看业务上最经常的写入和读取操作是什么,然后再考虑分区的策略。

既然与具体业务相关,我们就假定一个业务环境,假如我们要做一个论坛,对论坛的帖子和回复表进行分区。
论坛中最常见的写操作是1)发帖 2)回复帖子,
最常见的读操作是
1) 根据帖子id显示帖子详情和分页的帖子回复
2) 根据帖子版面帖子列表页根据版面id分页读取帖子列表数据
怎么分区更合适呢?现在还没有准确答案,我有两种可能的方案,写下来,大家讨论看看。
方案1. 根据帖子ID区域段分区(1-300w一个分区、300w-600w一个分区…),这样理论上可以提高帖子详细页的读取速度,而对于写操作性能没有益处,对于根据版面id读取帖子列表页有可能有益
方案2. 根据版面id进行分区,这样对于写性能应该有提高,不同的分区对应不同的版面,当有两个版面同时有发帖回帖操作时,有可能可以并发写。对于根据版面id获得帖子列表页数据也可以提高性能,而对于帖子详细信息页没有性能影响。

多大的数据量才需要分区?
这个问题我只能说一个内部标准,如果一张表的记录超过在超过1000w,并以每月百万的数据量增长,那就需要分区。大家有不同的看法请回复讨论。

--------------------------------------------------------------

我想大家都碰到过这样的情况,某个业务表中的数据量很大,急速膨胀,在这样的情况下,我们为了保持高的数据响应速度,根据数据的时间局部性和空间局部性原则,可以通过对数据表进行分片设计.
一般有两种分片方法:横向分片和竖向分片
横向分片是将业务表按使用部门拆分为多个表,各个部门之间的数据相对独立,相互之间互不影响,这种方法适用于各部门相互独立的情况,不过带来的问题就是部门不便扩展,统计及交换数据不便,举个例子,同样的医嘱管理系统,几个病区,一个病区一张表,虽然带来了查询数据效率的提高,但是病区之间病人转科,数据交换不方便
竖向分片是将业务表中不常用的数据转移到另外的表中,如在院和出院病人数据分别存于不同的表中,病人出院后就将在院病人数据转到出院病人表中,因为在院病人数据是经常要操作的,所以这种分片保证了在院病人数据表始终保持一定的量,从而提高查询的效率
我们该怎样使用这两种方法呢,根据本人数据库设计经验,在数据量较小,部门之间数据频繁交换的情况下使用竖向分片,这样会保证程序设计中逻辑相对保持简单,提高了程序的可靠性,也降低了程序员的负担.
竖向分片仍然不足以解决问题的情况下,我们再引入横向分片,将数据经常交换的部门分为一组,放在同一张业务表中,横向分片数要尽量少,减少统计程序的复杂性
不过在要求更高效率的情况下,横向分片加并发的数据检索可大大提高数据统计速度,对要求实时高速的情况下可以使用这种方法,不过我更倾向于ODS,对业务数据自动抽取汇总,大大提高数据统计速度.

FROM: 网络

Sep 19
三大范式:

  第1规范:没有重复的组或多值的列,这是数据库设计的最低要求。

  第2规范: 每个非关键字段必须依赖于主关键字,不能依赖于一个组合式主关键字的某些组成部分。消除部分依赖,大部分情况下,数据库设计都应该达到第二范式。

  第3规范: 一个非关键字段不能依赖于另一个非关键字段。消除传递依赖,达到第三范式应该是系统中大部分表的要求,除非一些特殊作用的表。

  更高的范式要求这里就不再作介绍了,个人认为,如果全部达到第二范式,大部分达到第三范式,系统会产生较少的列和较多的表,因而减少了数据冗余,也利于性能的提高。

  完全按照三大范式规范化设计的系统几乎是不可能的,除非系统特别的小,在规范化设计后,有计划地加入冗余是必要的。冗余可以是冗余数据库、冗余表或者冗余字段,不同粒度的冗余可以起到不同的作用。冗余可以是为了编程方便而增加,也可以是为了性能的提高而增加。从性能角度来说,冗余数据库可以分散数据库压力,冗余表可以分散数据量大的表的并发压力,也可以加快特殊查询的速度,冗余字段可以有效减少数据库表的连接,提高效率。

  主键的设计 

  主键是必要的,SQL SERVER的主键同时是一个唯一索引,而且在实际应用中,我们往往选择最小的键组合作为主键,所以主键往往适合作为表的聚集索引。聚集索引对查询的影响是比较大的,这个在下面索引的叙述。

  在有多个键的表,主键的选择也比较重要,一般选择总的长度小的键,小的键的比较速度快,同时小的键可以使主键的B树结构的层次更少。

  主键的选择还要注意组合主键的字段次序,对于组合主键来说,不同的字段次序的主键的性能差别可能会很大,一般应该选择重复率低、单独或者组合查询可能性大的字段放在前面。

  外键的设计

  外键作为数据库对象,很多人认为麻烦而不用,实际上,外键在大部分情况下是很有用的,理由是:

  外键是最高效的一致性维护方法,数据库的一致性要求,依次可以用外键、CHECK约束、规则约束、触发器、客户端程序,一般认为,离数据越近的方法效率越高。

  谨慎使用级联删除和级联更新,级联删除和级联更新作为SQL SERVER 2000当年的新功能,在2005作了保留,应该有其可用之处。我这里说的谨慎,是因为级联删除和级联更新有些突破了传统的关于外键的定义,功能有点太过强大,使用前必须确定自己已经把握好其功能范围,否则,级联删除和级联更新可能让你的数据莫名其妙的被修改或者丢失。从性能看级联删除和级联更新是比其他方法更高效的方法。

  字段数据类型设计原则:

  A、数据类型尽量用数字型,数字型的比较比字符型的快很多,尤其是作为主键。

  B、 数据类型尽量小,这里的尽量小是指在满足可以预见的未来需求的前提下的,节省一个字节是一个字节,虽然硬盘便宜也不能浪费啊。

  C、 尽量不要允许NULL,除非必要,可以用NOT NULL+DEFAULT代替。

  为什么最好不要为null呢,因为在程序处理过程中,你经常要为null值进行处理,比如使用isnull进行判断,这样削弱查询的速度,还有程序中需要不断的为null值进行判断,多写了代码,减少了程序的性能。

  D、少用TEXT和IMAGE,二进制字段的读写是比较慢的,而且,读取的方法也不多,大部分情况下最好不用。在SQL Server 2005尽可能使用nvarchar(max), 或者varchar(max); 除非必要图片尽量上传到服务器,数据库保留上传地址。

  E、自增字段要慎用

  1. 不利于数据迁移;

  2. 不利于分布式部署;

  3. 无法预知Id,为子表数据插入造成困难;

  4. 没有实际意义,无法让人看出这个数字到底有什么用。

  F、尽可能使用定长数据类型,而不是变长数据类型。

  为什么不要设计过多的变长类型的数据呢?

  1. 对于 SQl Server 为说,变长类型的数据,在更新的时候,如果长度比以前的大,会进行页拆分。会对查询性能造成严重的影响。会增加查询时,I/O 的花费 (Cost) 页分隔越多,查询时,I/O 的开销就越大。对于变长的字段来说,有可能这个字符的内容存储在不同的位置,这个字段的内容存储在不同的位置。存储在不同的页中, 它们之间有指针来关联。这种情况会造成查询时,磁头来回寻址,定位。可能你查一条记录,磁头找这条记录的这个变长字段的内容,都要去好几个页里找,才能完整的找到。这样,就造成了很大个 I/O 开销,降低了查询性能。从物理上来说,文件本来就经常容易产生碎片。再加上变长类型的页拆分。

  页是SQL Server存储数据的基本单位,大小为8kb,可以存储表数据、索引数据、执行计划数据、分配位图、可用空间信息。页是SQL  Server可以读写的最小I/O单位。即便是读取一行数据,它也要把整个页加载到缓存并从缓存中读取数据。

  页拆分是这样产生的:

  比如:有一个变长类型的字段 Content: nvarchar(512)。你添加一条记录,给 Content 的值是 N'ABC',那么,存储的时候,直接就存储 N'ABC' 了。当你下次 Update 这条记录的 Content 字段时,给的值是 N'ABCDEF',那么就会发生页拆分。DEF 对被存储在其它页。因为有可能上一次分配的数据页已经存储了其他行的数据对吧,对,512,只是用来限制这个字段的长度。并不与页拆分有关系。记录的物理顺序,与你 INSERT 的顺序是一致。你 INSERT 了 N条,然后再去修改第一条,这时候可能不在同一个页了。

  以上结论就是把变长字段的内容加大,就会造成页拆分了。也就是说可变长类型是把一页填满,再填另一页,影响比较大的是,每次insert的时候会增加分配数据页的次数。

  当然有可能造成一行数据保存在2个数据页里。但是,同样,不但页拆分对增加查询时的 I/O 开销,字符不必要的太长,也会增加 I/O 开销。

  2. 字段大小对表总大小有影响

  SQL Server 2005单行字段总长是8060字节。

  3. 可变长类型是有长度限制的

From:http://kb.cnblogs.com/page/106731/
好文章共同分享

Tags:
Jul 20
首先,我们来看下nvarchar和varchar的官方帮助里的说明:
varchar(n)

长度为 n 个字节的可变长度且非 Unicode 的字符数据。n 必须是一个介于 1 和 8,000 之间的数值。存储大小为输入数据的字节的实际长度,而不是 n 个字节。所输入的数据字符长度可以为零。varchar 在 SQL-92 中的同义词为 char varying 或 character varying。
nvarchar(n)
包含 n 个字符的可变长度 Unicode 字符数据。n 的值必须介于 1 与 4,000 之间。字节的存储大小是所输入字符个数的两倍。所输入的数据字符长度可以为零。nvarchar 在 SQL-92 中的同义词为 national char varying 和 national character varying。

二、该如何选择两种字符呢?

       varchar和nvarchar都能存储汉字。区别在于,一个汉字占varchar(2),只占nvarchar(1),而字母只占varchar(1),那么在数据库字段求长度的时候,用varchar你就不一定知道它确切的知道它到底有几个字,如果用nvarchar,那么汉字也是nvarchar(1),字母也是nvarchar(1),那么已经很明显了.
       同时,varchar的检索快于nvarchar。
varchar在SQL Server中是采用单字节来存储数据的,nvarchar是使用Unico来存储数据的.中文字符存储到SQL Server中会保存为两个字节(一般采用Unico编码),英文字符保存到数据库中,如果字段的类型为varchar,则只会占用一个字节,而如果字段的类型为nvarchar,则会占用两个字节.   正常情况下,我们使用varchar也可以存储中文字符,但是如果遇到操作系统是英文操作系统并且对中文字体的支持不全面时, 在SQL Server存储中文字符为varchar就会出现乱码(显示为??).而且正常情况下,主机都会支持中文的环境,所以如果使用varchar来存储数据,在开发阶段是发现不了的.多数情况下,在布署的时候也不会有问题.
  但是!如果布署的主机是英文操作系统,并且不支持中文环境,那问题就出来了.所有的varchar字段在存储中文的时候都会变成乱码(显示为??).而且一般情况下你不会知道这是因为你采用了错误的数据类型来存储所造成的,你会试着去装中文字体,试着去设置操作系统的语言环境...这些都不能解决问题,唯一能解决问题的是把数据库字段的类型个性为nvarchar(或者nchar).对项目管理比较熟悉的朋友应该都知道,到布署阶段再来修改数据库是一个很恐怖的事情.
  使用nvarchar的另一个非常好处就是在判断字符串的时候可以不需要考虑中英文两种字符的差别.
  当然,使用nvarchar存储英文字符会增大一倍的存储空间.但是在存储代价已经很低廉的情况下,优先考虑兼容性会给你带来更多好处的.
  所以在Design的时候应该尽量使用nvarchar来存储数据.只有在你确保该字段不会保存中文的时候,才采用varchar来存储.
本文出自 51CTO.COM技术博客
Tags:
Apr 4
锁升级是将众多细粒度锁转换为较少的粗粒度的锁的过程,以削减系统开销。当事务超过它的升级极限时,Microsoft® SQL Server™ 2000 自动将行锁和页锁升级为表锁。   例如,当事务从表中请求行时,SQL Server 自动获取受影响的行上的锁,并在包含这些行的页和表或者索引上放置更高级别的意向锁。当事务控制的锁数量超过了它的极限时,SQL Server 会试图将表上的意向锁更改为更强的锁(例如,将意向排它 (IX) 锁更改为排它 (X) 锁)。获取更强的锁后,表事务持有的所有页级锁和行级锁都被释放,从而削减锁的开销。   SQL Server 可以为同一查询选择行和页锁定,例如,在索引上放置页锁(如果在非聚集的索引节点中选定了足够的邻接键来满足查询)及在数据上放置行锁。以减少必须进行锁升级的可能性。   锁升级极限是由 SQL Server 动态确定的,无须进行配置。   SQL Server 可以动态升级或降级锁粒度或锁类型。例如,如果更新获取大量行锁而阻塞了表的大部分,将行锁升级到表锁。如果获取了表锁,将释放行锁。SQL Server 2000 很少需要升级锁;查询优化器在编译执行计划时通常选择正确的锁粒度。
Dec 23
分页: 1/7 第一页 1 2 3 4 5 6 7 下页 最后页 [ 显示模式: 摘要 | 列表 ]