一、第一到四章主要讲述了,分层架构思想,数据关系映射,基本的数据架构图提出的基本思想。

二、第五章对后面章节的内容着了铺垫并发、事务、锁(如悲观离线锁、乐观离线锁) 、ACID原则等的基础内容。

三、第六章为后面的第十六章会话状态做铺垫性描述。

四、第七章讲述了分布式基础,为后面的分布式做基础描述,提出了尽可能避免过度设计、过度使用分布式,能单机解决的问题绝不使用分布式方案。因为跨进程的访问是很消耗资源的。提出了分布对象设计第一定律:不要分布使用对象。而且要紧可能小范围内使用分布对象,尽可能的发挥集群系能(通常总会需要对象分布到不同的进程中)。其提出在同平台下优先使用平台自己提供的远程调用机制,然后才是使用webserivce的方式。

五、第八章讲述了领域模型的基础提出了:脚本事务模型、表模型、领域模型,脚本事务模型注意依赖一直接书写sql等脚本来解决业务问题,其对于简单的应用比较合适,成本比较低廉。而表模型,主要是依赖于平台提供的dataset 、datetable等来直接进行数据的逻辑运算、对于规模不大的应用比较方便快捷在这一块.NET做的相当的方便。而领域模型主要是把所有的运算都以对象的形式来进行运算,在.NET种我认为是把数据库的值映射到类中,用类来进行逻辑运算,大量的使用了面向对象的思想来进行编程此模式对规模不大的运用成本太高,对比较复杂的和规模逐渐变大的系统后面的成本会逐渐的比其他2种模式的成本更低。而实际的运用中不可能只是其中一种模式在系统中运用,而是可能多种模式在系统中并存使用。对于本章当时自己为了了解几种模式的区别和能在一个系统中找出这几种模式,我也花了较长的时间去理解。

六、至此前面一致八章是第一部分,主要的是为第二部分着基础内容铺垫,使读者能有一个平滑的过程理解本书。 所有有的问题在第一致第五描述清楚的在后面将不再描述。

七、 第九章深入介绍事务脚本、领域模型、表模型,详细内如如第五。其增加了一个服务层的描述,主要思想是把内部业务逻辑进行封装(封装方式是3种模式)对外提供一个初粒度或者细粒度的访问接口(是对物业逻辑封装的方法,并不一定是个真实的接口)。

八、第十章讲述了表数据入口、行数据入口、活动记录、数据映射器。

  1. 表数据入口:从数据库中取数据是取出全部数据,在dateset、datetable之间是有过滤器来选取其中的某条数据、update、insert也是基于dataset、datetable、等ADO.NET的几大对象的数据更新方式,如直接使用适配器的update方法等。其基本思想是分2步取数据,第一步是取出数据库中的所有数据(select * from table,注:没有where语句)。然后在利用datetable的过滤器或者筛选器(select 、filter)通过过滤条件(如用已知的ID来过滤)来选取其中的某条语句,就得到一条数据;其是表模式的使用体现
  2. 表数据入口的优缺点:需要读取过大的数据在内存中,占有较大的内存空间,cup压力大。对于小数据,或者对数据的操作运算比较频繁的时候直接在内存中运算比每次都去数据库中读取数据速度快。其对update的操作也不方便。还有可能存在数据实时性稍低的情况,比较读取数据到dataset等中取运算不能实时读取数据库中最新的数据。
  3. 行数据入口:从数据库查询数据时,直接带有如“select * from  table where id=参数”的方式直接从数据库中选取具体的某行数据。他对数据的操作完全是基于数据库的,而不像表数据入口是居然ADO.NET对象的。Update 、delete的操作也是携带了where 条件直接对数据库的数据进行操作。其是脚本事务模式的体现。
  4. 行数据入口的优缺点:直接对数据库选取的数据比较精确,但是当需要较多关于数据库的数据读取时,对数据库的操作过多,可能带来数据库压力比较大。对类似的数据需要多次的进行读取时,对性能有一定影响。
  5. 活动记录:对数据库中的数据进行,通过数据映射后形成对象,然后相关的逻辑运算都在对象中进行,其必须依赖于数据映射。必须把数据库对象数据转换为类对象。对所有的插入操作、更新操作、删除操作、查询操作所需要的数据都是以对象的形式进行传输,如果是数据集在NET中可以利用泛型等来进行数据集的操作来进行对象间的数据传输;其是领域模型的使用体现。
  6. 活动记录优缺点:必须依赖于数据映射,并且其效率在大部分情况下低于另外2种。并且其的代码量比另外2种更多,需要建立比较多的运算对象(类)。但是其在代码的编写过程中比较方便,而且如果需求变更时,对代码的改动量、和维护来说在大型系统中比较有优势。
  7. 数据映射:把数据库的数据映射到实体对象中去。方便运算过程中直接使用。而不是需要对象数据时使用sql脚本去取数据。现在出现的大量的ORM就是这个东西如EF,linq to sql等都是这写东西。他省去了开发人员不懂数据库语言时的方便,只需多拽就可以实现从数据库中读取数据并且映射成类。但是其性能有一定的缺陷,但是现在已经做的很好了,在中小型系统中使用是完全可以接受的。

九、第十一章讲述了工作单元、标识映射、延迟加载方面的内容。

  1. 工作单元:基本思想是把一组相关的操作封装在一个方法中,实现一次性提交,其需要的基础数据在更早时准备好,存在在特别设计的数组中,到提交方法时只需要提交即可。提交方法中包含有3个方法,一个方法是插入数据,一个更新插入进去的脏数据、然后是删除新插入的数据。这种模式如数据库中的事务是一个道理一样。但是我们可以把他的思想引入到代码。
  2. 标识映射:把已经获取到的数据插入一个临时变量中或者缓存中,当要获取该对象时优先通过ID等标识从临时变量或者缓存中获取,如果获取不到在到数据库中查询在缓存。
  3. 延迟加载:在数据运算时只携带运算相关的键(如ID),当计算需要跟多数据时在通过该键(ID)去数据库中(或者某个存储对象中)读取出对象的全部数据,实现一种延迟加载的方式。重影,键(携带一个或者多个真是数据)是真实数据的一个重影。使用方式有:虚代理、值保持器(类似标识映射的方式)、重影。如果延迟加载加载了多余的数据,时叫做波动加载。

十、第十二章讲述了标识域、外键映射、关联表映射、依赖映射、嵌入值、序列化LOB、单表继承、类表继承、具体表继承、继承映射器。

  1. 标识域:其实就是通常说的主键一类的东西,用于在内存中和数据库对象管理起来,给表中的某行一个主键、然后内存中也有一个主键,然后通过主键即可以找带数据对象。该键可以是自增涨ID或者GUID或者身份证号之类的唯一值。同时又有表键唯一和数据库键唯一。表键唯一是在一张表中唯一的一个值;而数据库键唯一是指该键值在整个数据库中是一个唯一值。
  2. 组合键:使用多个键值作为主键,只有多个键值在一起使才可以确定一个唯一的行。
  3. 外键映射:把表A中存储了表A本身的主键同时其还存储了表B的主键,及通过表A存储了表B的一个主键值就可以找到表B中和表A关联的数据行了。
  4. 关联表映射:在表A和表B之间增加一个表C存储表A的主键和表B的主键关联形成一行,就实现了A表通过 C表就可以找到B表关联的数据;此方法通常是在表A和表B已经存在并且修改表A或者表B时代价太大而是要的一种第3方表的形式。不足:大量的关联查询损耗性能。
  5. 依赖映射:基本思想是在数据库持久化时,数据库中的某个类(依赖者)依赖于其他的类(所有者)。每个依赖者有且只有一个所有者。比如A表有列a.c而B表有多行a.c的值与A表的a.c相同;类似于一个目录下有多个文件一样的结构。
  6. 嵌入值:把数据库中的某些字段的值用在类的实例化时,该类通过自身的一些计算拥有了一些拥有展示的值,形成一个实例类。而该类的值(除了从数据库中读取的),可以通过计算得来,如果把这些值直接存储在数据库中则可以提高效率(直接查询,而不需要运算)。
  7. 序列化LOB:把一个对象直接序列化成字符串(json、二进制)或者xml后直接存储在数据库中。有json、二进制序列化和xml序列化,这个方式会导致如果类修改了,可能使早期存储的数据不能反序列化回来,导致数据丢失。并且数据是人眼很难看懂的必须通过程序反序列化后才看得明白。如果序列化的对象被多处拷贝以后,当想要修改其中的某个值是必须把所有的拷贝对象都拿出了执行并且修改。将是一个很痛苦的过程。
  8. 单表继承:如有A、B、C 这3个类继承关系是A:B:C即C继承B,B继承A。则会有不同的建表的方式,而单表继承是把A、B、C所有的字段都建立在一个表中,所有的数据都存储在一个表中。这3个类随便怎么调整继承关系度不必修改表(新增字段除外),不需要连接表操作、可能是A类中没有的字段在表中也有数据列对应,比较多余,浪费数据空间。
  9. 类表继承:同意是ABC这3个表分别为他们3个类建立3个表即A表、B表、C表,当调整3个类的继承关系时不必修改表,清新的类,没有浪费空间,但是其有多表连接操作,导致性能问题。如字段从A类移动到B类则必须同时修改表,实现对应。
  10. 具体表继承:即给A类的字段建立一个表,而B类继承了A类,则B表的字段必须包含A表的字段和其自身的字段,C类继承了B类,所有C类对应的C表必须包含A类的字段、B类的字段和C类本身的字段。优缺点每个表都是自包含的,并且没有不相关的域,读取数据时不需要连接操作、只有类被访问的时候表才会被读取,分散负载。其处理主键比麻烦、不能把数据库映射关系抽象到类中、类中的字段修改位置改动比较大,如C类自己的字段如果调整到B类中择需要调子C表和B表,比较麻烦、超类上的一次查找需要检查所有的表,导致多处访问数据库,或者特殊操作,查找A类中的一个信息可能要查询A、B、C这3个表,或者比较特殊的查询操作。
  11. 继承映射器:即在抽象类或者接口中定义基本的数据读取规则,而在实现类中去实现查找,去实现类属性和数据库字段的关联。

十一、第十三章讲述了元数据映射、查询对象、资源库。

  1. 元数据映射:本身提出了代码生成和反射程序2种方法;反射是通过映射生成可执行的代码程序,如NET中的反射。反射调试困难,代码执行速度慢,但其具有很高的灵活性,可以动态选择程序的执行,可以把元数据保持到xml中等地方。NET的可以从dll中进行反射,并且NET的代码提示靠的也是元数据、其调试模式下生成pdb文件也属于元数据的一种方式,反射是当修改某部分代码时很难发现问题;而代码生成主要是输入元数据,输出映射实现的源代码。代码生成本人感觉是,想非强制类型语言(如js)可以动态构建、拼接js语句然后在执行拼接的js语句的一种方式。
  2. 查询对象:是解释器模式在表示sql查询上的应用。客户端可以构造各式各样的sql语句,然后交有服务端去解释执行语句。服务端通过一定的领域模类构造出一些方便构造sql语句的方法,然后这些方法生成的语句叫由服务端去执行;比如linq to sql里面定义的一些方法,其实其本质也是解析构造出sql语句交由服务端执行生成。
  3. 资源库:协调领域和数据映射层,利用类似于集合的接口来访问领域对象。其是定义对数据库访问的抽象类、或者接口;必须在子类中实现自己对数据库的查询具体对象接口、删除对象接口、增加对象的接口等。他定义了一个高层次的数据访问规则,有子类负责实现。由于其只是定义了高层接口,就不需要关心具体的数据源、高层接口负责业务的定义。

十二、第十四章讲述了MVC(常见的模式还有MVP、MVVM、PM)、页面控制器、前端控制器、模板视图、转换视图、两步视图、应用控制器。

  1. MVC:视图充(V)当模型(M)的观察者、控制器(C)是视图(V)的策略;其本质就是观察者模式和策略模式的混合使用。
  2. 页面控制器(MVP):M:Model、V:View、P:Presenter;其原理是V修改了通过P传递给M,然后M修改后又通过P传递给V。
  3. 前端控制器:对页面进行访问时,通常都要进行安全验证,安全验证是通用的,各个页面的逻辑和展现的东西却是不同的,所有在所有页面访问前都见上一个安全验证,使所有的验证逻辑都走相同的逻辑。在NET就如同HttpHandle一样,或者全局文件,的管道模式。
  4. 模板视图:就是生成一个模板的HTML模板页,在需要修改内容的地方做标识,在运行网站的时候,把标识替换成网站需要的内容即可。
  5. 转换视图:把一个页面需要的数据先保存在一个文档中,然后在对这个文档的数据进行转换成为html代码。 如我们需要的数据都在xml中,我们在用某种语言(XSLT是本书推荐的一种对于处理这种转换的最具有优势的语言)把这些xml转换为htmL代码。
  6. 两步视图:第一步在动态页面中处理数据逻辑,然后最终代码会生成相应的html代码输出到客户端。我们假设在其第一次运行动态页面生成了最终的显示逻辑代码后即htmL代码,我们把生成的这些htmL代码截取保存起来。就把动态的页面转化为了静态页面,以后再访问的时候,就直接访问静态页面,而不需要走动态页面那么复杂的运算过程。其第一步是运行动态代码生成需要展现的逻辑,第二步是保存页面逻辑形成的html代码。
  7. 应用控制器:决定运行那个领域逻辑和决定用那种视图来显示应答消息;如同MVC中的路由控制器一样。根据输入的命令来跳转到相应的视图逻辑中去。根据不同的命令来显示不同的视图。

十三、第十五章讲述了远程外观、数据传输对象

  1. 远程外观:把需要的一组数据封装在一个粗粒度的方法中返回,其中粗粒度的方法调用了很多细粒度的方法。访问时提供一些基本信息,而返回时返回一组比较全面的信息,这些信息你每次运算可能只需要其中的一部分。如NET下webserivce就是一种比较好的远程外观。其实现了跨进程和分布式的数据访问,但其有性能损伤的问题;同时在这里还提到了会话外观,但本人对会话外观还未完全理解清楚。着重提供一组粗粒度的结果集,而不是细粒度的方法返回结果集。
  2. 在远程外观中提到了服务层,其基本思想是把一些方法集封装成一个服务,供远程外观或者其他的调用。在服务器中不涉及具体逻辑,只是一个返回某项业务的服务。
  3. 数据传输对象:在调用者之间传输数据的方式; 远程外观中粗粒度的结果集,必然导致不需要的数据在网络上传输,通常的方法是对对象进行序列化传输,有二进制数据传输、文本、json数据传输、基于(soap、wsdl协议的)序列化为xml的数据传输。数据传输必然存在服务端发送序列化后的数据客户端必须能解析服务端序列化后发回的数据,服务端和客户端对数据的封装必须能方向进行实例化回原来的对象。其关键是如何把对象序列化传输,客户端收到数据后如果解析数据的问题,通过什么方式进行数据的映射,序列化传输的数据映射为对象的问题。对于数据的序列化提出优先使用平台自身提供的序列化方式。

十四、第十六章讲述了乐观离线锁、悲观离线锁、粗粒度锁、隐含锁

  1. 乐观离线锁:同时可以多个人编辑数据,对数据提交时冲突的地方进行合并出来类,类似于源代码管理工具TFS的思想;对出来事务时比较弱;其提交数据时进行版本管理,只有版本号一直的数据才能在相同的事务中提交。
  2. 悲观离线锁,就是只能有一个人独占文件进行编辑,其他人不能改动,类似于源代码管理工具VSS的思想。悲观离线锁对处理事务比较有优势,并且其是乐观离线锁应用的补充。其有独占写锁,独占读锁、读写锁。
  3. 粗粒度锁:就是对一堆的方法调用时把这一堆方法放到同一个锁里面。这一堆方法拥有同一个版本号,那么这一堆方法就共用了这一个锁,叫做共享锁,单锁有2类,所有有乐观共享锁和悲观共享锁。同时其产生了一堆方法(或者对象),这堆方法拥有一个锁的控制对象,只有锁住这个对象就锁住了所有,这种就是跟对象锁
  4. 隐含锁:在某些系统平台中某些方法方法提交了系统锁,或者在对一堆方法的调用时,其中的某个方法加了锁,而其他的方法没有锁,而我们调用的地方根本没有加锁的机会,而无意中产生了锁。

十五、第十七章讲述了客户端会话状态、服务器会话状态、数据库会话状态(注:此会话不是专指session,当然也包括session,而是在交互时需要的一些数据)

  1. 客户端会话状态:把会话信息存储到客户端,如存储在Cookie、URL、隐藏域中,如果是复杂对象可以进行序列化后存储。数据存储在客户端不安全,可能存在数据丢失、数据量大时保持困难。
  2. 服务器会话状态:把大量交互的数据存储在服务器内存中,而给客户端存储这些数据的一个标识(如NET的sessionid),当需要这些数据时,客户端出示标识,就可以从服务器内存中读取数据。其容易导致服务器崩溃、集群处理比较困难、占用较大服务器内存。
  3. 数据库会话状态:将会话的数据存储到数据库中,把会话数据存储在数据库中,给客户端一个标识(sessiondid),当需要数据时,用标识(sessionid)去数据库中查找数据。集群方便、但是对数据库性能有要去。讲会话数据存储在临时表或者会话信息存储到和业务一起的数据表中,然后加标识位区分会话数据。
  4. .NET中对于session可以存储在IIS进程中,服务器内存中(可以是IIS服务器本身的内存中,也可以是另外一台服务器的内存中)、数据库中。

十六、第十八章讲述了入口、映射器、层超类型、分离接口、注册表、值对象、货币、特殊情况、插件、服务桩、记录集

 

posted @ 2012-05-24 22:35 狼-志 阅读(9) 评论(0) 编辑

一、通过一步步调查发现发现存储,字段名,等信息的表及表结构如下:
CREATE TABLE [sys].[syscolpars]
(
[id] [int] NOT NULL,
[number] [smallint] NOT NULL,
[colid] [int] NOT NULL,
[name] [sys].[sysname] NULL,--存储列名等的
[xtype] [tinyint] NOT NULL,
[utype] [int] NOT NULL,
[length] [smallint] NOT NULL,
[prec] [tinyint] NOT NULL,
[scale] [tinyint] NOT NULL,
[collationid] [int] NOT NULL,
[status] [int] NOT NULL,
[maxinrow] [smallint] NOT NULL,
[xmlns] [int] NOT NULL,
[dflt] [int] NOT NULL,
[chk] [int] NOT NULL,
[idtval] [varbinary] (64) NULL
) ON [PRIMARY]
GO

字段name就是存储定义表时,表列名名称,等信息的。可见其定义的类型为 [sys].[sysname],而非常规类型。

通过执行 “exec   sp_help   sysname ”发现其定义的类型为nvarchar (128)为并且不区分大小写,又因为nvarchar 类型是用unicode编码所以我认为只要能识别unicode编码,用中文命列名就不应该有问题,个人建议。

 

 

附加Chinese_PRC_CI_AS的解释:

Chinese_PRC_CI_AS不是编码,只是sql中定义的规则

在 Microsoft SQL Server 2000 中,
字符串的物理存储由排序规则控制。排序规则指定表示每个字符的位模式以及存
储和比较字符所使用的规则

前半部份:指UNICODE字符集,Chinese_PRC_指针对大陆简体字UNICODE的排序规则。
排序规则的后半部份即后缀 含义:
  _BIN 二进制排序
  _CI(CS) 是否区分大小写,CI不区分,CS区分
  _AI(AS) 是否区分重音,AI不区分,AS区分  
  _KI(KS) 是否区分假名类型,KI不区分,KS区分
     _WI(WS) 是否区分宽度 WI不区分,WS区分

 

 

posted @ 2012-05-24 13:54 狼-志 阅读(3) 评论(0) 编辑

这个架构基于squid、nginx和lvs等技术,从架构上对bbs进行全面优化和保护,有如下特点:

1、高性能:所有的点击基本上全部由前端缓存负责,提供最快速的处理。

2、高保障度:不需考虑应用程序稳定与否、程序语言是何种、数据库是何种,都能从架构上保证稳定。

3、高可用性:对应用程序的修改达到最简化:在程序的某些地方加入清缓存的语句即可,当然还需要做页面静态化的工作和统计工作。

首先看图,这个图比较大:



这个架构的特点和一些流程的说明:

1、主域名和图片域名分离

域名分离可以使流量分离,缓存策略分离等等,好处诸多。bbs初期一定要做好规划,将图片用另外的域名独立服务,即使没有足够机器,域名也要先分开。另 外,图片服务器可以使用有别于主域名的另一个域名,一个好处是可以减少读取cookie对图片服务器的压力,另一个是提高安全性,避免cookie泄露。

2、使用LVS作为前端、二级代理和数据库的访问入口

使用LVS作为入口,比其他任何一种方式都来得更优质。首先LVS的负载能力很强,因为它工作在网络协议的第4层,使用虚拟ip技术,所以它本身并不担负 任何流量的处理,仅仅是一个封包转发的功能;第二,LVS的配置相对简单而且稳定,一般去调整的几率比较低,也减少了因人为等因素而出现故障;第 三,LVS可以处理任何端口的负载均衡,所以它基本可以做所有服务的负载均衡和容错。在这个架构中,除了处理http的80端口之外,LVS也处理了数据 库mysql的3306端口,在数据库这个应用中是采用的双机热备策略。

3、使用nginx+squid作为最前端的缓存组合

在这个架构中,是最能体现app_nginx_squid_nginx架构的优势的。在这个架构中的bbs运行在缓存上,用户每发布一张帖子,都需要使用 purge指令清除该帖子的缓存,如果是squid在最前端,那么每次发布一张帖子,都需要在所有的squid中调用purge指令,这样在机器比较多的 时候,purge将成为一个巨大的压力。

所以在这里将nginx放在最前端并使用手工url_hash的方式分流,将经常需要purge的帖子页面和列表页面按一个url对应一台squid的策 略,分布到各台squid上,并提供了一台或一组backup的squid,个别squid出现异常时将自动使用backup的机器继续提供一段时间的服 务直到其正常。在这样的架构下,purge就不再是关键问题,因为一个url只会对应到一台机器上,所以purge的时候,后端app_server找到 对应的机器就可以了。

可以看到在前端中还有一台nginx(purge)的机器,这台机器是专用于purge的,只要发送purge指令和需要清除的url到这台机器,就可以 找到相应的服务器并清除缓存了。另外,purge时还需要清理backup机器上的缓存,所以无论前端机器增加到多少,purge指令只会在2台机器上执 行,如果backup机器使用到2-3台,purge指令就会在3-4台机器上执行,仍然在可接受范围之内。

nginx作为前端,另有的好处:

1/使用nginx的日志统计点击量非常方便
2/nginx也可作为缓存,一般可以直接负责favicon.ico和logo等固定的小图片

4、基于nginx的中层代理

nginx中层代理的优势,在:

nginx和squid配合搭建的web服务器前端系统

这篇文章中有解释。

在这个架构中,假如后端的app_server上把帖子页和列表页直接生成了静态页面,那么使用中层代理再做一次url_hash,将可以解决后端 app_server的硬盘容量的压力,但是如果使用到url_hash的话,那做容错就相对麻烦了。所以建议不要采用生成静态页的方式,后端的压力一般 不会非常的大,所以没有必要生成静态页。假如前端squid的命中率实在太低下,造成大量穿透,可以考虑使用二级代理暂顶。

5、基于LVS的数据库双机热备

在这个架构中,因为大量的并发和访问量都由前端的缓存处理掉了,所以后端的mysql主要压力来自于数据的写入,所以压力并不是非常大,并且负载比较稳 定,一般不会随着访问量上升而提高过快,估计目前一台64位的机器,加满内存并使用高速的硬盘,前端负载数亿访问量时数据库都不会出现性能问题。在数据库 这方面应主要考虑故障恢复,因为数据库崩溃的话,按照一般使用备份恢复的做法,耗时很长而且难免丢失数据,是很棘手的问题。使用双机热备的方案,出现故障 时首先可由一台时刻同步着的备用数据库即刻充当主数据库,然后卸下的数据库可以有充分的时间对其进行维修,所以是个很安全有效的办法。

当然,数据库的优化还是要细心做的,参考:

mysql性能的检查和调优方法

细心地调一遍,性能会好很多。

6、图片服务器

图片服务器我在这个架构中没有特别详细的介绍,在大型的bbs系统下,图片常常会出现容灾现象——图片数量严重超过了单台前端服务器容纳能力,导致前端服务器命中率低下。处理容灾问题也是非常棘手的,往后会有更详细的介绍。

7、简单的点击量统计办法

1/使用js的script标签访问另一(台)组服务器的空文件,然后定期向数据库更新
2/在前端的nginx上直接开启日志功能,按需要统计点击量的链接规则进行记录,然后定期更新数据库

 

 

 

转:http://www.oschina.net/question/54100_11155

posted @ 2012-04-19 11:03 狼-志 阅读(30) 评论(0) 编辑

1           前端优化必要性

随着互联网的发展,前端优化越来越被人们重视,在一个大型的大型电子商务网站技术架构中,前端架构一定是一项必不可少的工作,国内几个大型的互联网公司也有非常强大的前端技术人员。在业界享有名气淘宝 UED团队就有好几十人。在浏览器访问一个网站时,有 10%-20% 的时间是花在下载 HTML 上面,有 80%-90% 时间是花在下载页面中所有组件上面。如果我们可以把后端时间缩短一半,整体响应时间只能减少 5%-10% 。然而我们关注前端,同样是其响应时间缩短一半,那整体性能能减少 40%-45% 

看些研究数据:

l  Amazon  0.1 s -> 1% 用户放弃交易

l  Google  0.4s ->  0.6% 放弃搜索

l  Yahoo!  0.4s ->  减少 5%-9% 的流量

l  Bing  2s ->  收入下降 4.3 %

2           前端优化最佳实践

在前端发展了那么长时间,其优化经验也有很多值得借鉴,下面作简单介绍。

2.1       14 条优化军规

1.         尽可能的减少 HTTP 请求数

2.         使用 CDN

3.         添加 Expires  ( 或者 Cache-control)

4.         Gzip 组件

5.          CSS 样式放在页面的上方。

6.         将脚本放在底部 ( 包括内联的 )

7.         避免在 CSS 中使用 Expressions

8.          javascript  css 独立成外部文件

9.         减少 DNS 查询

10.     压缩 JavaScript  CSS 文件 ( 包括内联的 )

11.     避免跳转

12.     移除重复的脚本

13.     配置 ETags

14.     缓存 Ajax 请求

以上内容在网上都有介绍,在此不作多说,有兴趣的同学可以 google 一把。

2.2       拆分初始化负载

Ajax 和动态 HTML 的日益普及网页上面的 js  css 也变得非常庞大, web 程序也变得像桌面程序一样,很大一部分代码不会在启动时候使用,而是采取插件式架构,允许动态加载模块。

         在一个大型结构复杂的网页上面,为了不影响用户体验,可以把 js 分为两部分,一部分是渲染页面必须的,剩下是一部分。这样也在一定程度上面提高用户体验,给用户第一时间看到完整的页面。再寻找哪些 js 可以被拆分,可以通过一些辅助工具来判断, firebug 就是一个非常好的工具,可以通过查看哪些函数 onload 之前未被使用。通过判断可以把其中一部分拆分出来,但是有些不开始拆分,例如页面的错误处理和业务判断等 js 是不能拆分的,如果要拆分合理必将是一项严谨的工作。

2.3       无阻塞加载脚本

Js 有两种方式被包含在页面中,一种是行内脚本,一种是外部脚本。对外面脚本浏览器在下载 js 或者执行脚本的同时不会下载其他内容,有时候这种情况是必要,但是却会影响页面其他展示,理想情况是不堵塞其他内容下载的方式来加载 js 。目前也有对应的技术,用得比较多的是 XHR Eval  xhr 注入, script ifram  script dom element  script defer document.write script Tag 。具体使用情况要根据环境来定。

由于使用外部脚本,有人可能会想到把全部使用内部脚本,这种做法不可取,这样会增加页面大小,而且浏览器不会缓存 js ,少数内部脚本是可取的。但是大多情况下使用外部脚本,这样无论在团队开发,还是版本控制还会带来很大好处。

2.4       使用现成组件

现成开源的 js 组件很多,可以根据熟悉程度和业务应用性使用, jquery  yui  ext  dojo 。如果自行开发,除非有强大团队,要不维护成本太高,而且功能不完善。

Prototype

惊艳,野性, 代码风格类 Ruby ,新手不易上手,文档缺乏

Jquery

乖巧 灵活 易用

Dojo

强大,复杂,笨重

它的设计初衷就是:不光只运行在浏览器的脚本环境中,甚至像 pdf/rhino 这些也拥有

脚本环境的地方也能使用

Yui

温顺,矫健,文档齐全,编码语法相对传统,封装的形式比较接近于 Java

Ext

Ext:  野生,炫,侵入太强,适用于精英团队

 

2.5       针对 Content 优化

1.         组件延迟加载

不可见的组件 非当前的 Tab ,隐藏的图片

附加组件:动画 , 拖动

2.         预加载组件

无条件的预加载 (Google 首页的例子)

有条件的预加载(淘宝首页搜索提示功能的例子)

3.         减少 DOM 元素个数

元素越多,下载的数据越多, JS 操作 DOM 速度越慢

4.         尽量少使用 iframe

l  公共文件的重复加载

l  浏览器的消耗

2.6       图片优化

l  优化图片

尝试使用 PNG  png 拥有 gif 所有功能,还支持 alpha 透明,文件比较小,所以尽可能使用 png 格式图片。

删除图片的元数据,例如 photoshop 的元数据,这样在一定程度上能减少图片大小而不影响图片质量。

l  CSS sprites

可以把网站常用的小图片集合在一张图片中,通过 Css 定位到小图上面,从而减少 http 请求。

l  不要在 HTML 中缩放图片  

<img width="100" height="100" src=  cat.jpg" />

3           怎么样才算足够快

0.1 

用户直接操作 ui 中对象的感觉极限。例如,用户直接选择表格的一列到该列高亮显示,或者反馈被选择的时间间隔。

1 

用户随意在计算机指令空间操作而无需过度等等时间的感觉极限。 0.2-1.0 的时间延迟会被用户注意到,会让用感觉到计算机正在对指令进行处理中。等待的时间过长,会让用户失去流畅的体验。

10 

用户专注于任务的极限,超过 10 秒的任何操作都要有一个进度指示器,以及有一个让用户中断操作,而且有清晰的标示方法。假设用户超过 10 秒后返回界面,他们将要重新适应。在实际工作中有些操作超过 10 秒是可以接受的,比如撤换操作任务。

换句话说 js 在执行如果超过 0.1 秒,会让人感觉到不平滑。如果超过 1 秒会让人感觉应用程序缓慢;超过10 秒那么用户会非常沮丧。这些就是用于足够快的标准。

转自:http://blog.csdn.net/riguangli/article/details/5775025

 
posted @ 2012-04-19 10:44 狼-志 阅读(16) 评论(0) 编辑

如果说要对一个站点或者应用程序经常优化,可以说缓存的使用是最快也是效果最明显的方式。一般而言,我们会把一些常用的,或者需要花费大量的资源或时间而产生的数据缓存起来,使得后续的使用更加快速。

如果真要细说缓存的好处,还真是不少,但是在实际的应用中,很多时候使用缓存的时候,总是那么的不尽人意。换句话说,假设本来采用缓存,可以使得性能提升为100(这里的数字只是一个计量符号而已,只是为了给大家一个“量”的体会),但是很多时候,提升的效果只有80,70,或者更少,甚至还会导致性能严重的下降,这个现象在使用分布式缓存的时候尤为突出。

在本篇文章中,我们将为大家讲述导致以上问题的9大症结,并且给出相对应的解决方案。文章以.NET为例子进行代码的演示,对于来及其他技术平台的朋友也是有参考价值的,只要替换相对应的代码就行了!

为了使得后文的阐述更加的方便,也使得文章更为的完整,我们首先来看看缓存的两种形式:本地内存缓存,分布式缓存。

首先对于本地内存缓存,就是把数据缓存在本机的内存中,如下图1所示:

从上图中可以很清楚的看出:

  • 应用程序把数据缓存在本机的内存,需要的时候直接去本机内存进行获取。
  • 对于.NET的应用而言,在获取缓存中的数据的时候,是通过对象的引用去内存中查找数据对象的,也就说,如果我们通过引用获取了数据对象之后,我们直接修改这个对象,其实我们真正的是在修改处于内存中的那个缓存对象。

对于分布式的缓存,此时因为缓存的数据是放在缓存服务器中的,或者说,此时应用程序需要跨进程的去访问分布式缓存服务器,如图2:

不管缓存服务器在哪里,因为涉及到了跨进程,甚至是跨域访问缓存数据,那么缓存数据在发送到缓存服务器之前就要先被序列化,当要用缓存数据的时候,应用程序服务器接收到了序列化的数据之后,会将之反序列化。序列化与反序列化的过程是非常消耗CPU的操作,很多问题就出现在这上面。

另外,如果我们把获取到的数据,在应用程序中进行了修改,此时缓存服务器中的原先的数据是没有修改的,除非我们再次将数据保存到缓存服务器。请注意:这一点和之前的本地内存缓存是不一样的。

对于缓存中的每一份数据,为了后文的讲述方面,我们称之为“缓存项“。

普及完了这两个概念之后,我们就进入今天的主题:使用缓存常见的9大误区:

  1. 太过于依赖.NET默认的序列化机制
  2. 缓存大对象
  3. 使用缓存机制在线程间进行数据的共享
  4. 认为调用缓存API之后,数据会被立刻缓存起来
  5. 缓存大量的数据集合,而读取其中一部分
  6. 缓存大量具有图结构的对象导致内存浪费
  7. 缓存应用程序的配置信息
  8. 使用很多不同的键指向相同的缓存项
  9. 没有及时的更新或者删除再缓存中已经过期或者失效的数据

下面,我们就每一点来具体的看看!

太过于依赖.NET默认的序列化机制

当我们在应用中使用跨进程的缓存机制,例如分布式缓存memcached或者微软的AppFabric,此时数据被缓存在应用程序之外的进程中。每次,当我们要把一些数据缓存起来的时候,缓存的API就会把数据首先序列化为字节的形式,然后把这些字节发送给缓存服务器去保存。同理,当我们在应用中要再次使用缓存的数据的时候,缓存服务器就会将缓存的字节发送给应用程序,而缓存的客户端类库接受到这些字节之后就要进行反序列化的操作了,将之转换为我们需要的数据对象。

另外还有三点需要注意的就是:

  • 这个序列化与反序列化的机制都是发生在应用程序服务器上的,而缓存服务器只是负责保存而已。
  • .NET中的默认使用的序列化机制不是最优的,因为它要使用反射机制,而反射机制是是非常耗CPU的,特别是当我们缓存了比较复杂的数据对象的时候。

基于这个问题,我们要自己选择一个比较好的序列化方法来尽可能的减少对CPU的使用。常用的方法就是让对象自己来实现ISerializable接口。

首先我们来看看默认的序列化机制是怎么样的。如图3:

然后,我们自己来实现ISerializable接口,如下图4所示:

我们自己实现的方式与.NET默认的序列化机制的最大区别在于:没有使用反射。自己实现的这种方式速度可以是默认机制的上百倍。

可能有人认为没有什么,不就是一个小小的序列化而已,有必要小题大做么?

在开发一个高性能应用(例如,网站)而言,从架构,到代码的编写,以及后面的部署,每一个地方都需要优化。一个小问题,例如这个序列化的问题,初看起来不是问题,如果我们站点应用的访问量是百万,千万,甚至更高级别的,而这些访问需要去获取一些公共的缓存的数据,这个之前所谓的小问题就不小了!

下面,我们来看第二个误区。

缓存大对象

有时候,我们想要把一些大对象缓存起来,因为产生一次大对象的代价很大,我们需要产生一次,尽可能的多次使用,从而提升响应。

提到大对象,这里就很有必要对其进行一个比较深入的介绍了。在.NET中,所谓的大对象,就是指的其占用的内存大于了85K的对象,下面通过一个比较将问题说清楚。

如果现在有一个Person类的集合,定义为List<Person>,每个Person对象占用1K的内存,如果这个Person集合中包含了100个Person对象实例,那么这个集合是否是大对象呢?

回答是:不是!

因为集合中只是包含的Person对象实例的引用而言,即,在.NET的托管堆上面,这个Person集合分配的内存大小也就是100个引用的大小而言。

然后,对于下面的这个对象,就是大对象了: byte[] data = new byte[87040](85 * 1024 = 87040)。

说到了这里,那就就谈谈,为什么说:产生一次大对象的代价很大。

因为在.NET中,大对象是分配在大对象托管堆上面的(我们简称为“大堆”,当然,还有一个对应的小堆),而这个大堆上面的对象的分配机制和小堆不一样:大堆在分配的时候,总是去需找合适的内存空间,结果就是导致出现内存碎片,导致内存不足!我们用一个图来描述一下,如图5所示:

上图非常明了,在图5中:

  • 垃圾回收机制不会在回收对象之后压缩大堆(小堆是压缩的)。
  • 分配对象的时候,需要去遍历大堆,去需找合适的空间,遍历是要花成本的。
  • 如果某些空间小于85K,那么就不能分配了,只能白白浪费,也导致内存碎片。

讲完了这些之后,我们言归正传,来看看大对象的缓存。

正如之前讲过,将对象缓存和读取的时候是要进行序列化与反序列化的,缓存的对象越大(例如,有1M等),整个过程中就消耗更多的CPU。

对于这样的大对象,要看它使用的是否很频繁,是否是公用的数据对象,还是每个用户都要产生的。因为我们一旦缓存了(特别在分布式缓存中),就需要同时消耗缓存服务器的内存与应用程序服务器的CPU。如果使用的不频繁,建议每次生成!如果是公用的数据,那么建议多多的测试:将生产大对象的成本与缓存它的时候消耗的内存和CPU的成本进行比较,选择成本小的!如果是每个用户都要产生的,看看是否可以分解,如果实在不能分解,那么缓存,但是及时的释放!

使用缓存机制在线程间进行数据的共享

当数据放在缓存中的时候,我们程序的多个线程都可以访问这个公共的区域。多个线程在访问缓存数据的时候,会产生一些竞争,这也是多线程中常常发生的问题。

下面我们分别从本地内存缓存与分布式缓存两个方面介绍竞争的带来的问题。

看下面的一段代码:

对于本地内存缓存,对于上面的代码,当这个三个线程运行起来之后,在线程1中,item的值很多时候可能为1,线程2可能是2,线程3可能是3。当然,这不一定!只是大多数情况下的可能值!

如果是对于分布式缓存,就不好说了!因为数据的修改不是立刻发生在本机的内存中的,而是经过了一个跨进程的过程。

有一些缓存模块已经实现了加锁的方式来解决这个问题,例如AppFabric。大家在修改缓存数据的时候要特别注意这一点。

认为调用缓存API之后,数据会被立刻缓存起来

有时候,当我们调用了缓存的API之后,我们就会认为:数据已经被换成了,之后就可以直接读取缓存中的数据。尽管情况很多时候如此,但是不是绝对的!很多的问题就是这样产生的!

我们通过一个例子来讲解。

例如,对于一个ASP.NET 应用而言,如果我们在一个按钮的Click事件中调用了缓存API,然后在页面呈现的时候,就去读取缓存,代码如下:

上面的代码照道理来说是对的,但是会发生问题。按钮点击之后回传页面,然后呈现页面的时候显示数据,流程没有问题。但是没有考虑到这样一个问题:如果服务器的内存紧张,而导致进行服务器内存的回收,那么很有可能缓存的数据就没有了!

这里有朋友就要说了:内存回收这么快?

这主要看我们的一些设置和处理。

一般而言,缓存机制都是会设置绝对过期时间与相对过期时间,二者的区别,大家应很清楚,我这里不多说。对于上面的代码而言,如果我们设置的是绝对过期时间,假设1分钟,如果页面处理的非常慢,时间超过了1分钟,那么等到呈现的时候,可能缓存中的数据已经没有了!

有时候,即使我们在第一行代码中缓存了数据,那么也许在第三行代码中,我们去缓存读取数据的时候,就已经没有了。这或许是因为在服务器内存压力很大的,缓存机制将最少访问的数据直接清掉。或者服务器CPU很忙,网络也不好,导致数据没有被即使的序列化保存到缓存服务器中。

另外,对于ASP.NET而言,如果使用了本地内存缓存,那么,还涉及到IIS的配置问题(对缓存内存的限制),我们有机会专门为大家分享这方面的知识。

所以,每次在使用缓存数据的时候,要判断是否存在,不然,会有很多的“找不到对象”的错误,产生一些我们认为的“奇怪而又合理的现象”。

 

转:http://www.infoq.com/cn/articles/misunderstanding-using-cache

posted @ 2012-04-14 20:14 狼-志 阅读(17) 评论(0) 编辑
标题:普通行列转换(version 2.0)
说明:普通行列转换(version 1.0)仅针对sql server 2000提供静态和动态写法,version 2.0增加sql server 2005的有关写法。
  
问题:假设有张学生成绩表(tb)如下:
姓名 课程 分数
张三 语文 74
张三 数学 83
张三 物理 93
李四 语文 74
李四 数学 84
李四 物理 94
想变成(得到如下结果): 
姓名 语文 数学 物理 
---- ---- ---- ----
李四 74   84   94
张三 74   83   93
-------------------
*/
  
create table tb(姓名 varchar(10) , 课程 varchar(10) , 分数 int)
insert into tb values('张三' , '语文' , 74)
insert into tb values('张三' , '数学' , 83)
insert into tb values('张三' , '物理' , 93)
insert into tb values('李四' , '语文' , 74)
insert into tb values('李四' , '数学' , 84)
insert into tb values('李四' , '物理' , 94)
go
  
--SQL SERVER 2000 静态SQL,指课程只有语文、数学、物理这三门课程。(以下同)
select 姓名 as 姓名 ,
  max(case 课程 when '语文' then 分数 else 0 end) 语文,
  max(case 课程 when '数学' then 分数 else 0 end) 数学,
  max(case 课程 when '物理' then 分数 else 0 end) 物理
from tb
group by 姓名
  
--SQL SERVER 2000 动态SQL,指课程不止语文、数学、物理这三门课程。(以下同)
declare @sql varchar(8000)
set @sql = 'select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [' + 课程 + ']'
from (select distinct 课程 from tb) as a
set @sql = @sql + ' from tb group by 姓名'
exec(@sql) 
  
--SQL SERVER 2005 静态SQL。
select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b
  
--SQL SERVER 2005 动态SQL。
declare @sql varchar(8000)
select @sql = isnull(@sql + '],[' , '') + 课程 from tb group by 课程
set @sql = '[' + @sql + ']'
exec ('select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b')
  
---------------------------------
  
/*
问题:在上述结果的基础上加平均分,总分,得到如下结果:
姓名 语文 数学 物理 平均分 总分 
---- ---- ---- ---- ------ ----
李四 74   84   94   84.00  252
张三 74   83   93   83.33  250
*/
  
--SQL SERVER 2000 静态SQL。
select 姓名 姓名,
  max(case 课程 when '语文' then 分数 else 0 end) 语文,
  max(case 课程 when '数学' then 分数 else 0 end) 数学,
  max(case 课程 when '物理' then 分数 else 0 end) 物理,
  cast(avg(分数*1.0) as decimal(18,2)) 平均分,
  sum(分数) 总分
from tb
group by 姓名
  
--SQL SERVER 2000 动态SQL。
declare @sql varchar(8000)
set @sql = 'select 姓名 '
select @sql = @sql + ' , max(case 课程 when ''' + 课程 + ''' then 分数 else 0 end) [' + 课程 + ']'
from (select distinct 课程 from tb) as a
set @sql = @sql + ' , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名'
exec(@sql) 
  
--SQL SERVER 2005 静态SQL。
select m.* , n.平均分 , n.总分 from
(select * from (select * from tb) a pivot (max(分数) for 课程 in (语文,数学,物理)) b) m,
(select 姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名
  
--SQL SERVER 2005 动态SQL。
declare @sql varchar(8000)
select @sql = isnull(@sql + ',' , '') + 课程 from tb group by 课程
exec ('select m.* , n.平均分 , n.总分 from
(select * from (select * from tb) a pivot (max(分数) for 课程 in (' + @sql + ')) b) m , 
(select 姓名 , cast(avg(分数*1.0) as decimal(18,2)) 平均分 , sum(分数) 总分 from tb group by 姓名) n
where m.姓名 = n.姓名')
  
drop table tb    
  
------------------
------------------
  
/*
问题:如果上述两表互相换一下:即表结构和数据为:
姓名 语文 数学 物理
张三 74  83  93
李四 74  84  94
想变成(得到如下结果): 
姓名 课程 分数 
---- ---- ----
李四 语文 74
李四 数学 84
李四 物理 94
张三 语文 74
张三 数学 83
张三 物理 93
--------------
*/
  
create table tb(姓名 varchar(10) , 语文 int , 数学 int , 物理 int)
insert into tb values('张三',74,83,93)
insert into tb values('李四',74,84,94)
go
  
--SQL SERVER 2000 静态SQL。
select * from
(
 select 姓名 , 课程 = '语文' , 分数 = 语文 from tb 
union all
 select 姓名 , 课程 = '数学' , 分数 = 数学 from tb
 union all
 select 姓名 , 课程 = '物理' , 分数 = 物理 from tb
) t
order by 姓名 , case 课程 when '语文' then 1 when '数学' then 2 when '物理' then 3 end
  
--SQL SERVER 2000 动态SQL。
--调用系统表动态生态。
declare @sql varchar(8000)
select @sql = isnull(@sql + ' union all ' , '' ) + ' select 姓名 , [课程] = ' + quotename(Name , '''') + ' , [分数] = ' + quotename(Name) + ' from tb'
from syscolumns 
where name! = N'姓名' and ID = object_id('tb') --表名tb,不包含列名为姓名的其它列
order by colid asc
exec(@sql + ' order by 姓名 ')
  
--SQL SERVER 2005 动态SQL。
select 姓名 , 课程 , 分数 from tb unpivot (分数 for 课程 in([语文] , [数学] , [物理])) t
  
--SQL SERVER 2005 动态SQL,同SQL SERVER 2000 动态SQL。
  
--------------------
/*
问题:在上述的结果上加个平均分,总分,得到如下结果:
姓名 课程   分数
---- ------ ------
李四 语文   74.00
李四 数学   84.00
李四 物理   94.00
李四 平均分 84.00
李四 总分   252.00
张三 语文   74.00
张三 数学   83.00
张三 物理   93.00
张三 平均分 83.33
张三 总分   250.00
------------------
*/
  
select * from
(
 select 姓名 as 姓名 , 课程 = '语文' , 分数 = 语文 from tb 
union all
 select 姓名 as 姓名 , 课程 = '数学' , 分数 = 数学 from tb
 union all
 select 姓名 as 姓名 , 课程 = '物理' , 分数 = 物理 from tb
 union all
 select 姓名 as 姓名 , 课程 = '平均分' , 分数 = cast((语文 + 数学 + 物理)*1.0/3 as decimal(18,2)) from tb
 union all
 select 姓名 as 姓名 , 课程 = '总分' , 分数 = 语文 + 数学 + 物理 from tb
) t
order by 姓名 , case 课程 when '语文' then 1 when '数学' then 2 when '物理' then 3 when '平均分' then 4 when '总分' then 5 end
 
 
posted @ 2012-04-02 17:22 狼-志 阅读(24) 评论(0) 编辑

  select * from a where a.Status='w' collate Chinese_PRC_CS_AI--区分大小写
--select * from a where a='abCdE' collate    Chinese_PRC_CI_AI--不区分大小写

 

 

SQL语句实现:

select * from a where a='AbCdE' collate Chinese_PRC_CS_AI--区分大小写
select * from a where a='abCdE' collate Chinese_PRC_CI_AI--不区分大小写

如何更改SQL SERVER 2000的排序规则

Alter datebase Alter datebase 数据库 Chinese_PRC_BIN

ALTERTABLE tb
ALTERCOLUMN colname nvarchar(100) COLLATE Chinese_PRC_CI_AS
--不区分大小写
ALTERTABLE tb
ALTERCOLUMN colname nvarchar(100) COLLATE Chinese_PRC_CS_AS
--区分大小写


使用如下命令,可以获得更多的规则:
SELECT*
FROM ::fn_helpcollations()


更改数据库排序规则后,表中字段的排序规则仍然没变,如果在企业管理器中在设计表的界面去一个字段一个字段的改太累人了,
EXEC sp_configure 'allow updates',1RECONFIGUREWITH OVERRIDE

update dbo.syscolumns set collationid=65572where collationid=53284

EXEC sp_configure 'allow updates',0RECONFIGUREWITH OVERRIDE
go


修改数据库的排序规则的时候,要确保你的数据库没有任何连接.

最好在查询分析器中用下面的方法,注意修改数据库名:

/*
关闭用户打开的进程处理
*/
use master
go

ifexists (select*from dbo.sysobjects where id =object_id(N'[dbo].[p_killspid]') andOBJECTPROPERTY(id, N'IsProcedure') =1)
dropprocedure[dbo].[p_killspid]
GO

createproc p_killspid
@dbnamevarchar(200) --要关闭进程的数据库名
as
declare@sqlnvarchar(500)
declare@spidnvarchar(20)

declare #tb cursorfor
select spid=cast(spid asvarchar(20)) from master..sysprocesses where dbid=db_id(@dbname)
open #tb
fetchnextfrom #tb into@spid
while@@fetch_status=0
begin
exec('kill '+@spid)
fetchnextfrom #tb into@spid
end
close #tb
deallocate #tb
go

--关闭用户连接
exec p_killspid '数据库名'
go

--修改排序规则
Alter datebase Alter datebase 数据库名 Chinese_PRC_BIN
 
 
 
转:http://hi.baidu.com/solorez/blog/item/7d1a2b973fc7a36955fb9631.html
posted @ 2012-03-30 15:44 狼-志 阅读(29) 评论(0) 编辑
摘要: 当发现有多个解决方案引用一个dll时,为了不重复引用所以将.net的一个dll注册到GAC中去。 gacutil.exe。开始菜单-Microsoft Visual Studio 2008 -Visual Studio Tools-Visual Studio 2008 命令提示,在控制台中输入 gacutil.exe 回车,既可以看到一些参数。 输入:gacutil.exe -i dll路径 注册成功后,刷新整个解决方案,成功。阅读全文
posted @ 2012-02-07 22:00 狼-志 阅读(30) 评论(0) 编辑
摘要: 面向海量服务的设计原则和策略总结 博客分类:杂项应用服务器网络应用Cache网络协议互联网 互联网服务的特点就是面向海量级的用户,面向海量级的用户如何提供稳定的服务呢?这里,对这几年的一些经验积累和平时接触的一些理念做一个总结。 一、原则 1.Web服务的CAP原理 CAP指的是三个要素:一致性(Consistency)、可用性(Availability)、分区容忍性(Partition tolerance)。CAP原理指的是这三个要素最多只能同时实现两点,不可能三者兼顾,对于海量级服务,一般这是一条常记心中的基准准则。 如下是《Web服务的CAP 》关于CAP的定义:一致性:可以参考数据库的阅读全文
posted @ 2012-01-15 16:06 狼-志 阅读(26) 评论(0) 编辑
摘要: body { background-color:Black;/*火狐+Google*/ background-color:red\9\0;/*IE9*/ background-color:blue\0;/*IE8*/ *background-color:navy;/*IE7*/ _background-color:green;/*IE6*/}注意点: IE9 支持 \9\0, 中间不要有空格,写成 background-color:red \9\0;不会识别。必须 background-color:red\9\0; IE8 支持 \0,同样中间不要有空格。 IE6,IE7 都支持 * ,但是I阅读全文
posted @ 2012-01-14 11:37 狼-志 阅读(45) 评论(0) 编辑