李得志的BLOG

记住:今天你过的生活是你3-5年前决定的,3-5年后的生活需要你今天开始规划。我的QQ:277599553欢迎交流

博客园 首页 新随笔 联系 订阅 管理
  74 Posts :: 0 Stories :: 33 Comments :: 0 Trackbacks

置顶随笔 #

建立一个 Web 应用,分页浏览功能必不可少。这个问题是数据库处理中十分常见的问题。经典的数据分页方法是:ADO 纪录集分页法,也就是利用ADO自带的分页功能(利用游标)来实现分页。但这种分页方法仅适用于较小数据量的情形,因为游标本身有缺点:游标是存放在内存中,很费内存。游标一建立,就将相关的记录锁住,直到取消游标。游标提供了对特定集合中逐行扫描的手段,一般使用游标来逐行遍历数据,根据取出数据条件的不同进行不同的操作。而对于多表和大表中定义的游标(大的数据集合)循环很容易使程序进入一个漫长的等待甚至死机。

更重要的是,对于非常大的数据模型而言,分页检索时,如果按照传统的每次都加载整个数据源的方法是非常浪费资源的。现在流行的分页方法一般是检索页面大小的块区的数据,而非检索所有的数据,然后单步执行当前行。

最早较好地实现这种根据页面大小和页码来提取数据的方法大概就是“俄罗斯存储过程”。这个存储过程用了游标,由于游标的局限性,所以这个方法并没有得到大家的普遍认可。

后来,网上有人改造了此存储过程,下面的存储过程就是结合我们的办公自动化实例写的分页存储过程:

CREATE procedure pagination1
(@pagesize int, --页面大小,如每页存储20条记录
@pageindex int --当前页码
)
as
set nocount on
begin
declare @indextable table(id int identity(1,1),nid int) --定义表变量
declare @PageLowerBound int --定义此页的底码
declare @PageUpperBound int --定义此页的顶码
set @PageLowerBound=(@pageindex-1)*@pagesize
set @PageUpperBound=@PageLowerBound+@pagesize
set rowcount @PageUpperBound
insert into @indextable(nid) select gid from TGongwen
where fariqi >dateadd(day,-365,getdate()) order by fariqi desc
select O.gid,O.mid,O.title,O.fadanwei,O.fariqi from TGongwen O,@indextable t
where O.gid=t.nid and t.id>@PageLowerBound
and t.id<=@PageUpperBound order by t.id
end
set nocount off

以上存储过程运用了SQL SERVER的最新技术――表变量。应该说这个存储过程也是一个非常优秀的分页存储过程。当然,在这个过程中,您也可以把其中的表变量写成临时表:CREATE TABLE #Temp。但很明显,在SQL SERVER中,用临时表是没有用表变量快的。所以笔者刚开始使用这个存储过程时,感觉非常的不错,速度也比原来的ADO的好。但后来,我又发现了比此方法更好的方法。

笔者曾在网上看到了一篇小短文《从数据表中取出第n条到第m条的记录的方法》,全文如下:

从publish 表中取出第 n 条到第 m 条的记录:
SELECT TOP m-n+1 *
FROM publish
WHERE (id NOT IN
(SELECT TOP n-1 id
FROM publish))
id 为publish 表的关键字 

我当时看到这篇文章的时候,真的是精神为之一振,觉得思路非常得好。等到后来,我在作办公自动化系统(ASP.NET+ C#+SQL SERVER)的时候,忽然想起了这篇文章,我想如果把这个语句改造一下,这就可能是一个非常好的分页存储过程。于是我就满网上找这篇文章,没想到,文章还没找到,却找到了一篇根据此语句写的一个分页存储过程,这个存储过程也是目前较为流行的一种分页存储过程,我很后悔没有争先把这段文字改造成存储过程:

CREATE PROCEDURE pagination2
(
@SQL nVARCHAR(4000), --不带排序语句的SQL语句
@Page int, --页码
@RecsPerPage int, --每页容纳的记录数
@ID VARCHAR(255), --需要排序的不重复的ID号
@Sort VARCHAR(255) --排序字段及规则
)
AS
DECLARE @Str nVARCHAR(4000)
SET @Str=''SELECT TOP ''+CAST(@RecsPerPage AS VARCHAR(20))+'' * FROM
(''+@SQL+'') T WHERE T.''+@ID+''NOT IN (SELECT TOP ''+CAST((@RecsPerPage*(@Page-1))
AS VARCHAR(20))+'' ''+@ID+'' FROM (''+@SQL+'') T9 ORDER BY ''+@Sort+'') ORDER BY ''+@Sort
PRINT @Str
EXEC sp_ExecuteSql @Str
GO

其实,以上语句可以简化为:

SELECT TOP 页大小 *
FROM Table1 WHERE (ID NOT IN (SELECT TOP 页大小*页数 id FROM 表 ORDER BY id))
ORDER BY ID

但这个存储过程有一个致命的缺点,就是它含有NOT IN字样。虽然我可以把它改造为:

SELECT TOP 页大小 *
FROM Table1 WHERE not exists
(select * from (select top (页大小*页数) * from table1 order by id) b where b.id=a.id )
order by id

即,用not exists来代替not in,但我们前面已经谈过了,二者的执行效率实际上是没有区别的。既便如此,用TOP 结合NOT IN的这个方法还是比用游标要来得快一些。

虽然用not exists并不能挽救上个存储过程的效率,但使用SQL SERVER中的TOP关键字却是一个非常明智的选择。因为分页优化的最终目的就是避免产生过大的记录集,而我们在前面也已经提到了TOP的优势,通过TOP 即可实现对数据量的控制。

在分页算法中,影响我们查询速度的关键因素有两点:TOP和NOT IN。TOP可以提高我们的查询速度,而NOT IN会减慢我们的查询速度,所以要提高我们整个分页算法的速度,就要彻底改造NOT IN,同其他方法来替代它。

我们知道,几乎任何字段,我们都可以通过max(字段)或min(字段)来提取某个字段中的最大或最小值,所以如果这个字段不重复,那么就可以利用这些不重复的字段的max或min作为分水岭,使其成为分页算法中分开每页的参照物。在这里,我们可以用操作符“>”或“<”号来完成这个使命,使查询语句符合SARG形式。如:

Select top 10 * from table1 where id>200

于是就有了如下分页方案:

select top 页大小 *
from table1
where id>
(select max (id) from
(select top ((页码-1)*页大小) id from table1 order by id) as T
)
order by id

在选择即不重复值,又容易分辨大小的列时,我们通常会选择主键。下表列出了笔者用有着1000万数据的办公自动化系统中的表,在以GID(GID是主键,但并不是聚集索引。)为排序列、提取gid,fariqi,title字段,分别以第1、10、100、500、1000、1万、10万、25万、50万页为例,测试以上三种分页方案的执行速度:(单位:毫秒)

页码 方案1 方案2 方案3
1 60 30 76
10 46 16 63
100 1076 720 130
500 540 12943 83
1000 17110 470 250
10000 24796 4500 140
100000 38326 42283 1553
250000 28140 128720 2330
500000 121686 127846 7168

从上表中,我们可以看出,三种存储过程在执行100页以下的分页命令时,都是可以信任的,速度都很好。但第一种方案在执行分页1000页以上后,速度就降了下来。第二种方案大约是在执行分页1万页以上后速度开始降了下来。而第三种方案却始终没有大的降势,后劲仍然很足。

在确定了第三种分页方案后,我们可以据此写一个存储过程。大家知道SQL SERVER的存储过程是事先编译好的SQL语句,它的执行效率要比通过WEB页面传来的SQL语句的执行效率要高。下面的存储过程不仅含有分页方案,还会根据页面传来的参数来确定是否进行数据总数统计。
获取指定页的数据:

CREATE PROCEDURE pagination3
@tblName varchar(255), -- 表名
@strGetFields varchar(1000) = ''*'', -- 需要返回的列
@fldName varchar(255)='''', -- 排序的字段名
@PageSize int = 10, -- 页尺寸
@PageIndex int = 1, -- 页码
@doCount bit = 0, -- 返回记录总数, 非 0 值则返回
@OrderType bit = 0, -- 设置排序类型, 非 0 值则降序
@strWhere varchar(1500) = '''' -- 查询条件 (注意: 不要加 where)
AS
declare @strSQL varchar(5000) -- 主语句
declare @strTmp varchar(110) -- 临时变量
declare @strOrder varchar(400) -- 排序类型
if @doCount != 0
begin
if @strWhere !=''''
set @strSQL = "select count(*) as Total from [" + @tblName + "] where "+@strWhere
else
set @strSQL = "select count(*) as Total from [" + @tblName + "]"
end 

以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况:

else
begin
if @OrderType != 0
begin
set @strTmp = "<(select min"
set @strOrder = " order by [" + @fldName +"] desc"

如果@OrderType不是0,就执行降序,这句很重要!

end
else
begin
set @strTmp = ">(select max"
set @strOrder = " order by [" + @fldName +"] asc"
end
if @PageIndex = 1
begin
if @strWhere != ''''
set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "
from [" + @tblName + "] where " + @strWhere + " " + @strOrder
else
set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ "
from ["+ @tblName + "] "+ @strOrder

如果是第一页就执行以上代码,这样会加快执行速度

end
else
begin

以下代码赋予了@strSQL以真正执行的SQL代码 

set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["
+ @tblName + "] where [" + @fldName + "]" + @strTmp + "(["+ @fldName + "])
from (select top " + str((@PageIndex-1)*@PageSize) + " ["+ @fldName + "]
from [" + @tblName + "]" + @strOrder + ") as tblTmp)"+ @strOrder
if @strWhere != ''''
set @strSQL = "select top " + str(@PageSize) +" "+@strGetFields+ " from ["
+ @tblName + "] where [" + @fldName + "]" + @strTmp + "(["
+ @fldName + "]) from (select top " + str((@PageIndex-1)*@PageSize) + " ["
+ @fldName + "] from [" + @tblName + "] where " + @strWhere + " "
+ @strOrder + ") as tblTmp) and " + @strWhere + " " + @strOrder
end
end
exec (@strSQL)
GO

上面的这个存储过程是一个通用的存储过程,其注释已写在其中了。 在大数据量的情况下,特别是在查询最后几页的时候,查询时间一般不会超过9秒;而用其他存储过程,在实践中就会导致超时,所以这个存储过程非常适用于大容量数据库的查询。 笔者希望能够通过对以上存储过程的解析,能给大家带来一定的启示,并给工作带来一定的效率提升,同时希望同行提出更优秀的实时数据分页算法。

以上的这第三种存储过程在小数据量的情况下,有如下现象:
1、分页速度一般维持在1秒和3秒之间。
2、在查询最后一页时,速度一般为5秒至8秒,哪怕分页总数只有3页或30万页。
虽然在超大容量情况下,这个分页的实现过程是很快的,但在分前几页时,这个1-3秒的速度比起第一种甚至没有经过优化的分页方法速度还要慢,借用户的话说就是“还没有ACCESS数据库速度快”,这个认识足以导致用户放弃使用您开发的系统。

笔者就此分析了一下,原来产生这种现象的症结是如此的简单,但又如此的重要:排序的字段不是聚集索引!

笔者只所以把“查询优化”和“分页算法”这两个联系不是很大的论题放在一起,就是因为二者都需要一个非常重要的东西――聚集索引。
在前面的讨论中我们已经提到了,聚集索引有两个最大的优势:
1、以最快的速度缩小查询范围。
2、以最快的速度进行字段排序。
第1条多用在查询优化时,而第2条多用在进行分页时的数据排序。
而聚集索引在每个表内又只能建立一个,这使得聚集索引显得更加的重要。聚集索引的挑选可以说是实现“查询优化”和“高效分页”的最关键因素。

但要既使聚集索引列既符合查询列的需要,又符合排序列的需要,这通常是一个矛盾。笔者前面“索引”的讨论中,将fariqi,即用户发文日期作为了聚集索引的起始列,日期的精确度为“日”。这种作法的优点,前面已经提到了,在进行划时间段的快速查询中,比用ID主键列有很大的优势。

但在分页时,由于这个聚集索引列存在着重复记录,所以无法使用max或min来最为分页的参照物,进而无法实现更为高效的排序。而如果将ID主键列作为聚集索引,那么聚集索引除了用以排序之外,没有任何用处,实际上是浪费了聚集索引这个宝贵的资源。

为解决这个矛盾,笔者后来又添加了一个日期列,其默认值为getdate()。用户在写入记录时,这个列自动写入当时的时间,时间精确到毫秒。即使这样,为了避免可能性很小的重合,还要在此列上创建UNIQUE约束。将此日期列作为聚集索引列。

有了这个时间型聚集索引列之后,用户就既可以用这个列查找用户在插入数据时的某个时间段的查询,又可以作为唯一列来实现max或min,成为分页算法的参照物。

经过这样的优化,笔者发现,无论是大数据量的情况下还是小数据量的情况下,分页速度一般都是几十毫秒,甚至0毫秒。而用日期段缩小范围的查询速度比原来也没有任何迟钝。聚集索引是如此的重要和珍贵,所以笔者总结了一下,一定要将聚集索引建立在:
1、您最频繁使用的、用以缩小查询范围的字段上;
2、您最频繁使用的、需要排序的字段上。

posted @ 2007-12-06 09:41 李得志 阅读(271) | 评论 (2)编辑

2008年8月15日 #

 

《狼图腾》读后感

李得志

 

自从有了网络就很少认认真真的读过一本书了,对狼也没什么认识,因为没见过狼,对狼说不上喜欢还是厌恶,但读完《狼图腾》以后,让我从狼身上学到了许多东西,那种坚忍、顽强、不屈、自我牺牲与团队合作精神等等一些值得我们学习的东西。

1. ----- 要学会忍耐,只有有耐性的行家才能最后把握住机会。

例:狼抓黄羊(草原上跑的最快的羊)的战略:a. 狼等羊吃的撑的跑不动了再下手;b. 狼等羊憋了一夜的尿而未排出前抓羊; c. 狼采用三面打围的方法而不是四面打围,故意留出一个方向让羊跑,这样局势完全在自己的预料之中,因而最终打到的羊也会更多;d. 故意放走一些羊,一次打光了,来年吃啥?狼不像人这么贪心,狼比人会算帐,会算大帐!

感悟: 不管做什么事,一定要有耐心!做事要有长远打算!切记“狗急了还会跳墙”,何况人?

2. ----- 那些被狼从肚侧大剖腹的马,本来就是大腹便便的饱马,胃包里装满了草原春天的第一茬青草和上年的秋草,饱胀而饱含水份,下坠分量很重。被撑薄的马肚皮一旦被狼牙豁开,巨大的胃包和肥柔的马肠就呼噜一下滑坠到雪地上。仍在惯性飞奔的两条马后腿,跟上来就是狠狠的几蹄,踏破了自己的胃囊,缠住了自己的肚肠。刹那间,胃包崩裂,胃食飞溅,柔肠寸断。惊吓过度的马仍在奔跑,后蹄把腹腔中的胃袋胃管食道肝胆统统踩绕在蹄下,最后把胸腔中的气管心脏肺叶也一起踩拽出来。大马可能是踩破了自己的肝胆,胆破致死;也可能是踩碎了自己的心脏,心碎而死;或着是踩扁了自己的肺,窒息而亡。狼的自杀是极其残忍痛楚的,因此狼也就不会让它的陪命者死得痛快。狼就是用这种方式让马也陪它一同尝尝自杀的滋味。马虽然是被狼他杀的,但马也是半自杀的。马死得更痛苦、更冤屈、也更悲惨。

感悟: 心态一定要好,越是看似危急的时候,若仍能保持一种良好的心态的话,那必定能柳暗花明的一天;千万不要自谑。

3. ----- 狼懂气象,懂地形,懂选择时机,懂知己知彼,懂战略战术,懂近战、夜战、游击战、运动战、奔袭战、偷袭战、闪击战,懂集中优势兵力打歼灭战。还能有计划、有目的、有步骤地实现全歼马群的战役意图。这个战例简直可以上军事教科书了。咱俩都是军人出身,我看除了阵地战、壕沟战狼不会,咱们

八路军游击队的那套战略战术军事兵法,狼全都会。想不到草原狼还有这两下子,原先我以为狼只会蛮干或者偷鸡摸狗,咬几只羊什么的。

   -----知己知彼。兵贵神速。兵不厌诈。上知天文,下知地理。常备不懈,声东击西。集中兵力,各个击破。化整为零,隐避精干。出其不意,攻其不备。打得赢就打,打不赢就走。伤其十指不如断其一指。敌进我退,敌驻我扰,敌疲我打,敌退我追等。都是狼在进攻马群时采取的战略。

感悟: 狼在大草原上“混”,懂这么多道理;你马上就要在社会上“闯”了,你会什么呢?你储备了什么了呀?

4. -----这条狼是让马踢破肚子了,但一下子死不了,活又活不成,这么活着不比死还难受?活狼看着也更难受,给它这一口,让它死个痛快,身子不疼了,魂也归腾格里了。头狼这么干不是狠毒,是在发善心,是怕伤狼落到人的手里,受人的侮辱!狼是宁死也不愿受辱的硬汉,头狼也不愿看自己的兄弟儿女受辱。你是务农出身,你们的人里面有几个宁死不降的?狼的这个秉性让每个草原老人想想就要落泪。

   ------狼杀狼,是狼自个儿在搞计划生育。强行加速报废,只把精兵强将留下。草原狼群的锐气万年不减,道理就在于此。

感悟: 没什么可说的了,只能说是佩服!若不能对自己狠点的话,那还怎么会有锐气可言呀?!严格要求自己。

5. ----- 老人说:你不知道,有的狼对自个儿也特别狠,它要是被夹住了腿,会把腿连骨带筋全咬断,瘸着三条腿逃掉。我给它下两个,只要夹住一条腿,它就会疼得没命地拽链子,没命转圈,转着转着后腿就踩着第二个夹子了,这地方链子刚好够得着。要是狼的前后两条腿都给夹住了,它就算能把两条断腿都咬掉,剩下两条腿它咋跑?

   -----小狼崽比狗崽出生晚了一个半月,狼崽的个头要比狗崽小一圈,身长也要短一头。但是小狼崽的力气却远远超过狗崽,它抢奶头的技术和本事也狠过狗崽。母狗腹部有两排奶头,乳房有大有小,出奶量更是有多有少。让陈阵和杨克吃惊的是小狼崽并不急于吃奶,而是发疯似的顺着奶头一路尝下去,把正在吃奶的狗崽一个一个挤开拱倒。一时间,一向平静的狗窝像是闯进来一个暴徒劫匪,打得狗窝狗仰崽翻,乱作一团。小狼崽蛮劲野性勃发,连拱带顶,挑翻了一只又一只的狗崽,然后把两排奶头从上到下,从左到右,全部尝了个遍。它尝一个,吐一个;尝一个,又吐一个,最后在伊勒的腹部中间,挑中了一个最大最鼓,出奶量最足的奶头,叼住了就不撒嘴,猛嘬猛喝起来。只见它叼住一个奶头,又用爪子按住了另一个大奶头,一副吃在碗里,霸住锅里,肥水不流外人田的恶霸架式。三只温顺的胖狗崽,不一会儿全被狼崽轰赶到两边去了。

感悟: 狠!对自己狠点,对自己的对手狠点!这才是狼性。

 

posted @ 2008-08-15 17:11 李得志 阅读(21) | 评论 (0)编辑

2008年6月2日 #

  要防止同一用户同时登陆,首页应该记录在线用户的信息(这里与用户名为例),然后判断正在登陆的用户里面是否已存在。在这里使用一个cache存放已经登陆的用户名,但是还有一个问题就是要知道用户是什么时候离开系统的呢?这就要定期清除cache中的内容了,也就是设置一个cache的时间。这个时间可以跟用户的session值联系起来,刚好当用户session值失效的时候该用户在cache里面的信息也会被清空.这样就达到了防止同时登陆的效果,具体代码如下:  

放在登陆成功的地方:
string key = TextBox1.Text; //用户名文本框设为cache关键字 
string uer = Convert.ToString(Cache[key]); //读取cache中用户相应的值
//判断cache中是否有用户的信息,如果没有相关的值,说明用户未登陆
if (uer == null || uer == String.Empty)
{
 //定义cache过期时间
 TimeSpan SessTimeout = new TimeSpan(0, 0, System.Web.HttpContext.Current.Session.Timeout, 0, 0);
 //第一次登陆的时候插入一个用户相关的cache值,
 HttpContext.Current.Cache.Insert(key, key, null, DateTime.MaxValue, SessTimeout, System.Web.Caching.CacheItemPriority.NotRemovable, null);
 Session["ADMINID"] = TextBox1.Text;
 Response.Redirect("main.ASPx");
}
else
{
 //重复登陆
 Response.Write("");
}  
posted @ 2008-06-02 09:49 李得志 阅读(39) | 评论 (0)编辑

2008年4月18日 #

CTRL + SHIFT + B生成解决方案
CTRL + F7 生成编译
CTRL + O 打开文件
CTRL + SHIFT + O打开项目
CTRL + SHIFT + C显示类视图窗口
F4 显示属性窗口
SHIFT + F4显示项目属性窗口
CTRL + SHIFT + E显示资源视图
F12 转到定义
CTRL + F12转到声明
CTRL + ALT + J对象浏览
CTRL + ALT + F1帮助目录
CTRL + F1 动态帮助
F1 帮助
SHIFT + F1当前窗口帮助
CTRL + ALT + F3帮助-搜索
SHIFT + ALT + ENTER全屏显示
CTRL + -向后定位
CTRL + SHIFT + -向前定位
CTRL + F4关闭文档窗口
CTRL + PAGE DOWN光标定位到窗口上方
CTRL + PAGE UP光标定位到窗口下方
CTRL + F6
CTRL + TAB下一个文档窗口
CTRL + SHIFT + F6
CTRL + SHIFT + TAB上一个文档窗口
ALT + F6下一个面板窗口
CTRL + K, CTRL + L取消remark
CTRL + K, CTRL + C注释选择的代码
CTRL + K, CTRL + U取消对选择代码的注释
CTRL + M, CTRL + O折叠代码定义
CTRL + M, CTRL + L展开代码定义
CTRL + DELETE删除至词尾
CTRL + BACKSPACE删除至词头
SHIFT + TAB取消制表符
CTRL + U转小写
CTRL + SHIFT + U转大写
CTRL + SHIFT + END选择至文档末尾
CTRL + SHIFT + HOME选择至文档末尾开始
SHIFT + END选择至行尾
SHIFT + HOME选择至行开始处
SHIFT + ALT + END垂直选择到最后尾
SHIFT + ALT + HOME垂直选择到最前面
CTRL + A全选
CTRL + W选择当前单词
CTRL + SHIFT + PAGE UP选择至本页前面
CTRL + SHIFT + PAGE DOWN选择至本页后面
CTRL + END文档定位到最后
CTRL + HOME文档定位到最前
CTRL + G转到…
CTRL + K, CTRL + P上一个标签
CTRL + K, CTRL + N下一个标签
ALT + F10调试-ApplyCodeChanges
CTRL + ALT+ Break停止调试
CTRL + SHIFT + F9 取消所有断点
CTRL + F9允许中断
CTRL + SHIFT + F5调试-重新开始
F5运行调试
CTRL + F5运行不调试
F10跨过程序执行
F11单步逐句执行
CTRL + J列出成员
CTRL + PAGE DOWN下一个视图
CTRL + B格式-粗体
CTRL + SHIFT + T格式-文字缩进
posted @ 2008-04-18 16:12 李得志 阅读(43) | 评论 (0)编辑

2008年3月26日 #

在web.config修改如下
<globalization requestEncoding="gb2312" responseEncoding="gb2312" />

posted @ 2008-03-26 09:14 李得志 阅读(181) | 评论 (0)编辑

2008年3月9日 #

1、用程序中,
保证在实现功能的基础上,尽量减少对数据库的访问次数;
通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担;
能够分开的操作尽量分开处理,提高每次的响应速度;
在数据窗口使用SQL时,尽量把使用的索引放在选择的首列;
算法的结构尽量简单;
在查询时,不要过多地使用通配符如SELECT * FROM T1语句,要用到几列就选择几列如:SELECT COL1,COL2 FROM T1;
在可能的情况下尽量限制尽量结果集行数如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因为某些情况下用户是不需要那么多的数据的。
不要在应用中使用数据库游标,游标是非常有用的工具,但比使用常规的、面向集的SQL语句需要更大的开销;
按照特定顺序提取数据的查找。

2、避免使用不兼容的数据类型。例如float和int、char和varchar、binary和varbinary是不兼容的。
数据类型的不兼容可能使优化器无法执行一些本来可以进行的优化操作。例如:
SELECT name FROM employee WHERE salary > 60000
在这条语句中,如salary字段是money型的,则优化器很难对其进行优化,因为60000是个整型数。
我们应当在编程时将整型转化成为钱币型,而不要等到运行时转化。

3、尽量避免在WHERE子句中对字段进行函数或表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:
SELECT * FROM T1 WHERE F1/2=100
应改为:
SELECT * FROM T1 WHERE F1=100*2

SELECT * FROM RECORD WHERE SUBSTRING(CARD_NO,1,4)=’5378’
应改为:
SELECT * FROM RECORD WHERE CARD_NO LIKE ‘5378%’

SELECT member_number, first_name, last_name   FROM members
WHERE DATEDIFF(yy,datofbirth,GETDATE()) > 21
应改为:
SELECT member_number, first_name, last_name   FROM members
WHERE dateofbirth < DATEADD(yy,-21,GETDATE())
即:任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要尽可能将操作移至等号右边。

4、避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等这样的操作符,
因为这会使系统无法使用索引,而只能直接搜索表中的数据。例如:
SELECT id FROM employee WHERE id != 'B%'
优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。

5、尽量使用数字型字段,一部分开发人员和数据库管理人员喜欢把包含数值信息的字段设计为字符型,
这会降低查询和连接的性能,并会增加存储开销。
这是因为引擎在处理查询和连接回逐个比较字符串中每一个字符,而对于数字型而言只需要比较一次就够了。

6、合理使用EXISTS,NOT EXISTS子句。如下所示:
1.SELECT SUM(T1.C1)FROM T1 WHERE(
(SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0)
2.SELECT SUM(T1.C1) FROM T1WHERE EXISTS(
   SELECT * FROM T2 WHERE T2.C2=T1.C2)
两者产生相同的结果,但是后者的效率显然要高于前者。因为后者不会产生大量锁定的表扫描或是索引扫描。
如果你想校验表里是否存在某条纪录,不要用count(*)那样效率很低,而且浪费服务器资源。可以用EXISTS代替。如:
IF (SELECT COUNT(*) FROM table_name WHERE column_name = 'xxx')
可以写成:
IF EXISTS (SELECT * FROM table_name WHERE column_name = 'xxx')

经常需要写一个T_SQL语句比较一个父结果集和子结果集,从而找到是否存在在父结果集中有而在子结果集中没有的记录,如:
1.SELECT a.hdr_key   FROM hdr_tbl a---- tbl a 表示tbl用别名a代替
WHERE NOT EXISTS (SELECT * FROM dtl_tbl b WHERE a.hdr_key = b.hdr_key)

2.SELECT a.hdr_key   FROM hdr_tbl a
LEFT JOIN dtl_tbl b ON a.hdr_key = b.hdr_key   WHERE b.hdr_key IS NULL

3.SELECT hdr_key   FROM hdr_tbl
WHERE hdr_key NOT IN (SELECT hdr_key FROM dtl_tbl)
三种写法都可以得到同样正确的结果,但是效率依次降低。

7、尽量避免在索引过的字符数据中,使用非打头字母搜索。这也使得引擎无法利用索引。  
见如下例子:
SELECT * FROM T1 WHERE NAME LIKE ‘%L%’
SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’
SELECT * FROM T1 WHERE NAME LIKE ‘L%’
即使NAME字段建有索引,前两个查询依然无法利用索引完成加快操作,引擎不得不对全表所有数据逐条操作来完成任务。
而第三个查询能够使用索引来加快操作。

8、充分利用连接条件,在某种情况下,两个表之间可能不只一个的连接条件,
这时在   WHERE 子句中将连接条件完整的写上,有可能大大提高查询速度。例:
SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO
SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO   AND A.ACCOUNT_NO=B.ACCOUNT_NO
第二句将比第一句执行快得多。

9、消除对大型表行数据的顺序存取,尽管在所有的检查列上都有索引,但某些形式的WHERE子句强迫优化器使用顺序存取。如:
SELECT * FROM orders WHERE (customer_num=104   AND order_num>1001) OR order_num=1008
解决办法可以使用并集来避免顺序存取:
SELECT * FROM orders WHERE customer_num=104 AND order_num>1001
UNION
SELECT * FROM orders WHERE order_num=1008
这样就能利用索引路径处理查询。

10、避免困难的正规表达式。LIKE关键字支持通配符匹配,技术

posted @ 2008-03-09 11:59 李得志 阅读(194) | 评论 (1)编辑

2008年2月22日 #

一个网站基本完工后,需要通过下面三步测试才可以交活。
  一、 制作者测试,包括美工测试页面、程序员测试功能。在做完后第一时间内有制作者本人进行测试。
  a) 页面 包括首页、二级页面、三级页面的页面在各种常用分辨率下有无错位;图片上有没有错别字;各连接是否是死连接;各栏目图片与内容是否对应等
  b) 功能 达到客户要求;数据库连接正确;各个动态生成连接正确;传递参数格式、内容正确;试填测试内容没有报错;页面显示正确
  二、 全面测试 根据交工标准和客户要求,由专人进行全面测试
  也是包括页面和程序两方面,而且要结合起来测,保证填充足够的内容后不会导致页面变形。另外要检查是否有错别字,文字内容是否有常识错误。
  三、 发布测试 网站发布到主服务器之后的测试,主要是防止环境不同导致的错误
附:网站测试与软件测试的区别
   软件测试在于于软件bug,它是在测试过程中出现的对系统有影响的,但是在设计中没有的或者对修改后的bug测试和开发人员有不同意见等
   软件未达到产品说明书标明的功能。
   软件出现了产品说明书指明不会出现的错误。
   软件功能超出产品说明书指明范围。
   软件未达到产品说明书虽未指出但应达到的目标。
   软件测试员认为软件难以理解、不易使用、运行速度缓慢,或者最终用户认为不好。
  测试的主要方面:
  一、功能测试
  对于网站的测试而言,每一个独立的功能模块需要单独的测试用例的设计导出,主要依据为《需求规格说明书》及《详细设计说明书》,对于应用程序模块需要设计者提供基本路径测试法的测试用例。
  1、链接测试
  链接是Web应用系统的一个主要特征,它是在页面之间切换和指导用户去一些不知道地址的页面的主要手段。链接测试可分为三个方面:
  1)测试所有链接是否按指示的那样确实链接到了该链接的页面;
  2)测试所链接的页面是否存在;
  3)保证Web应用系统上没有孤立的页面,所谓孤立页面是指没有链接指向该页面,只有知道正确的URL地址才能访问。
  链接测试可以自动进行,现在已经有许多工具可以采用。链接测试必须在集成测试阶段完成,也就是说,在整个Web应用系统的所有页面开发完成之后进行链接测试。
  Xenu------主要测试链接的正确性的工具
  可惜的是对于动态生成的页面的测试会出现一些错误。
  2、表单测试
  当用户给Web应用系统管理员提交信息时,就需要使用表单操作,例如用户注册、登陆、信息提交等。在这种情况下,我们必须测试提交操作的完整性,以校验提交给服务器的信息的正确性。例如:用户填写的出生日期与职业是否恰当,填写的所属省份与所在城市是否匹配等。如果使用了默认值,还要检验默认值的正确性。如果表单只能接受指定的某些值,则也要进行测试。例如:只能接受某些字符,测试时可以跳过这些字符,看系统是否会报错。
  要测试这些程序,需要验证服务器能正确保存这些数据,而且后台运行的程序能正确解释和使用这些信息。
  B/S结构实现的功能可能主要的就在这里,提交数据,处理数据等如果有固定的操作流程可以考虑自动化测试工具的录制功能,编写可重复使用的脚本代码,可以在测试、回归测试时运行以便减轻测试人员工作量。
  我们对UM子系统中各个功能模块中的各项功能进行逐一的测试,主要测试方法为:边界值测试、等价类测试,以及异常类测试。测试中要保证每种类型都有2个以上的典型数值的输入,以确保测试输入的全面性。
  3、Cookies测试
  Cookies通常用来存储用户信息和用户在某应用系统的操作,当一个用户使用Cookies访问了某一个应用系统时,Web服务器将发送关于用户的信息,把该信息以Cookies的形式存储在客户端计算机上,这可用来创建动态和自定义页面或者存储登陆等信息。
  如果Web应用系统使用了Cookies,就必须检查Cookies是否能正常工作而且对这些信息已经加密。测试的内容可包括Cookies是否起作用,是否按预定的时间进行保存,刷新对Cookies有什么影响等。
  4、设计语言测试
  Web设计语言版本的差异可以引起客户端或服务器端严重的问题,例如使用哪种版本的HTML等。当在分布式环境中开发时,开发人员都不在一起,这个问题就显得尤为重要。除了HTML的版本问题外,不同的脚本语言,例如Java、JavaScript、 ActiveX、VBScript或Perl等也要进行验证。
  5、数据库测试
  在Web应用技术中,数据库起着重要的作用,数据库为Web应用系统的管理、运行、查询和实现用户对数据存储的请求等提供空间。在Web应用中,最常用的数据库类型是关系型数据库,可以使用SQL对信息进行处理。
  在使用了数据库的Web应用系统中,一般情况下,可能发生两种错误,分别是数据一致性错误和输出错误。数据一致性错误主要是由于用户提交的表单信息不正确而造成的,而输出错误主要是由于网络速度或程序设计问题等引起的,针对这两种情况,可分别进行测试。
  二、性能测试
  网站的性能测试对于网站的运行而言异常重要,但是目前对于网站的性能测试做的不够,我们在进行系统设计时也没有一个很好的基准可以参考,因而建立网站的性能测试的一整套的测试方案将是至关重要的。
  网站的性能测试主要从三个方面进行:连接速度测试、负荷测试(Load)和压力测试(Stress),
  连接速度测试指的是打开网页的响应速度测试。负荷测试指的是进行一些边界数据的测试,压力测试更像是恶意测试,压力测试倾向应该是致使整个系统崩溃。
  1、连接速度测试
  用户连接到Web应用系统的速度根据上网方式的变化而变化,他们或许是电话拨号,或是宽带上网。当下载一个程序时,用户可以等较长的时间,但如果仅仅访问一个页面就不会这样。如果Web系统响应时间太长(例如超过5秒钟),用户就会因没有耐心等待而离开。
  另外,有些页面有超时的限制,如果响应速度太慢,用户可能还没来得及浏览内容,就需要重新登陆了。而且,连接速度太慢,还可能引起数据丢失,使用户得不到真实的页面。
  2、负载测试
  负载测试是为了测量Web系统在某一负载级别上的性能,以保证Web系统在需求范围内能正常工作。负载级别可以是某个时刻同时访问Web系统的用户数量,也可以是在线数据处理的数量。例如:Web应用系统能允许多少个用户同时在线?如果超过了这个数量,会出现什么现象?Web应用系统能否处理大量用户对同一个页面的请求?
  3、压力测试
  负载测试应该安排在Web系统发布以后,在实际的网络环境中进行测试。因为一个企业内部员工,特别是项目组人员总是有限的,而一个Web系统能同时处理的请求数量将远远超出这个限度,所以,只有放在Internet上,接受负载测试,其结果才是正确可信的。
  进行压力测试是指实际破坏一个Web应用系统,测试系统的反映。压力测试是测试系统的限制和故障恢复能力,也就是测试Web应用系统会不会崩溃,在什么情况下会崩溃。黑客常常提供错误的数据负载,直到Web应用系统崩溃,接着当系统重新启动时获得存取权。
  压力测试的区域包括表单、登陆和其他信息传输页面等。
  采用的测试工具:
  性能测试可以采用相应的工具进行自动化测试,我们目前采用如下工具
  ab -----Apache 的测试工具
  OpenSTA—开发系统测试架构
  三、接口测试
  在很多情况下,web 站点不是孤立。Web 站点可能会与外部服务器通讯,请求数据、
  验证数据或提交订单。
  1、 服务器接口
  第一个需要测试的接口是浏览器与服务器的接口。测试人员提交事务,然后查看服务器
  记录,并验证在浏览器上看到的正好是服务器上发生的。测试人员还可以查询数据库,确认事务数据已正确保存。
  2、 外部接口
  有些 web 系统有外部接口。例如,网上商店可能要实时验证信用卡数据以减少欺诈行
  为的发生。测试的时候,要使用 web 接口发送一些事务数据,分别对有效信用卡、无效信用卡和被盗信用卡进行验证。如果商店只使用 Visa 卡和 Mastercard 卡, 可以尝试使用 Discover 卡的数据。(简单的客户端脚本能够在提交事务之前对代码进行识别,例如 3 表示 American Express,4 表示 Visa,5 表示 Mastercard,6 代表Discover。)通常,测试人员需要确认软件能够处理外部服务器返回的所有可能的消息。
  3、错误处理
  最容易被测试人员忽略的地方是接口错误处理。通常我们试图确认系统能够处理所有错
  误,但却无法预期系统所有可能的错误。尝试在处理过程中中断事务,看看会发生什么情况?
  订单是否完成?尝试中断用户到服务器的网络连接。尝试中断 web 服务器到信用卡验证服
  务器的连接。在这些情况下,系统能否正确处理这些错误?是否已对信用卡进行收费?如果
  用户自己中断事务处理,在订单已保存而用户没有返回网站确认的时候,需要由客户代表致
  电用户进行订单确认。
  四、可用性测试
  可用性/易用性方面目前我们只能采用手工测试的方法进行评判,而且缺乏一个很好的评判基准进行,此一方面需要大家共同讨论。
  1、导航测试
  导航描述了用户在一个页面内操作的方式,在不同的用户接口控制之间,例如按钮、对话框、列表和窗口等;或在不同的连接页面之间。通过考虑下列问题,可以决定一个Web应用系统是否易于导航:导航是否直观?Web系统的主要部分是否可通过主页存取?Web系统是否需要站点地图、搜索引擎或其他的导航帮助?
  在一个页面上放太多的信息往往起到与预期相反的效果。Web应用系统的用户趋向于目的驱动,很快地扫描一个Web应用系统,看是否有满足自己需要的信息,如果没有,就会很快地离开。很少有用户愿意花时间去熟悉Web应用系统的结构,因此,Web应用系统导航帮助要尽可能地准确。
  导航的另一个重要方面是Web应用系统的页面结构、导航、菜单、连接的风格是否一致。确保用户凭直觉就知道Web应用系统里面是否还有内容,内容在什么地方。
  Web应用系统的层次一旦决定,就要着手测试用户导航功能,让最终用户参与这种测试,效果将更加明显。
  2、图形测试
  在Web应用系统中,适当的图片和动画既能起到广告宣传的作用,又能起到美化页面的功能。一个Web应用系统的图形可以包括图片、动画、边框、颜色、字体、背景、按钮等。图形测试的内容有:
  (1)要确保图形有明确的用途,图片或动画不要胡乱地堆在一起,以免浪费传输时间。Web应用系统的图片尺寸要尽量地小,并且要能清楚地说明某件事情,一般都链接到某个具体的页面。
  (2)验证所有页面字体的风格是否一致。
  (3)背景颜色应该与字体颜色和前景颜色相搭配。
  (4)图片的大小和质量也是一个很重要的因素,一般采用JPG或GIF压缩。
  3、内容测试
  内容测试用来检验Web应用系统提供信息的正确性、准确性和相关性。
  信息的正确性是指信息是可靠的还是误传的。例如,在商品价格列表中,错误的价格可能引起财政问题甚至导致法律纠纷;信息的准确性是指是否有语法或拼写错误。这种测试通常使用一些文字处理软件来进行,例如使用Microsoft Word的"拼音与语法检查"功能;信息的相关性是指是否在当前页面可以找到与当前浏览信息相关的信息列表或入口,也就是一般Web站点中的所谓"相关文章列表"。
  4、整体界面测试
  整体界面是指整个Web应用系统的页面结构设计,是给用户的一个整体感。例如:当用户浏览Web应用系统时是否感到舒适,是否凭直觉就知道要找的信息在什么地方?整个Web应用系统的设计风格是否一致?
  对整体界面的测试过程,其实是一个对最终用户进行调查的过程。一般Web应用系统采取在主页上做一个调查问卷的形式,来得到最终用户的反馈信息。
  对所有的可用性测试来说,都需要有外部人员(与Web应用系统开发没有联系或联系很少的人员)的参与,最好是最终用户的参与。
  五、兼容性测试
  需要验证应用程序可以在用户使用的机器上运行。如果您用户是全球范围的,需要测试各种操作系统、浏览器、视频设置和 modem 速度。最后,还要尝试各种设置的组合。
  1、平台测试
  市场上有很多不同的操作系统类型,最常见的有Windows、Unix、Macintosh、Linux等。Web应用系统的最终用户究竟使用哪一种操作系统,取决于用户系统的配置。这样,就可能会发生兼容性问题,同一个应用可能在某些操作系统下能正常运行,但在另外的操作系统下可能会运行失败。
  因此,在Web系统发布之前,需要在各种操作系统下对Web系统进行兼容性测试。
  2、浏览器测试
  浏览器是Web客户端最核心的构件,来自不同厂商的浏览器对Java,、JavaScript、 ActiveX、 plug-ins或不同的HTML规格有不同的支持。例如,ActiveX是Microsoft的产品,是为Internet Explorer而设计的,JavaScript是Netscape的产品,Java是Sun的产品等等。另外,框架和层次结构风格在不同的浏览器中也有不同的显示,甚至根本不显示。不同的浏览器对安全性和Java的设置也不一样。
  测试浏览器兼容性的一个方法是创建一个兼容性矩阵。在这个矩阵中,测试不同厂商、不同版本的浏览器对某些构件和设置的适应性。
  采用测试工具:
  通过白盒测试或者黑盒测试导出的测试用例,采用相应的工具进行测试,可以采用OpenSTA进行测试,此测试工具可以采用不同的浏览器进行测试。
  3.视频测试
  页面版式在 640x400、600x800 或 1024x768 的分辨率模式下是否显示正常? 字体是否太小以至于无法浏览? 或者是太大? 文本和图片是否对齐?
  4.Modem/连接速率测试
  是否有这种情况,用户使用 28.8 modem下载一个页面需要 10 分钟,但测试人员在测
  试的时候使用的是 T1 专线? 用户在下载文章或演示的时候,可能会等待比较长的时间,
  但却不会耐心等待首页的出现。最后,需要确认图片不会太大。
  5、打印机测试
  用户可能会将网页打印下来。因此网页在设计的时候要考虑到打印问题,注意节约纸张和油墨。有不少用户喜欢阅读而不是盯着屏幕,因此需要验证网页打印是否正常。有时在屏幕上显示的图片和文本的对齐方式可能与打印出来的东西不一样。测试人员至少需要验证订单确认页面打印是正常的。
  6、组合测试
  最后需要进行组合测试。600x800 的分辨率在 MAC 机上可能不错,但是在 IBM 兼容
  机上却很难看。在 IBM 机器上使用 Netscape 能正常显示,但却无法使用 Lynx 来浏览。
  如果是内部使用的 web 站点,测试可能会轻松一些。如果公司指定使用某个类型的浏览器,
  那么只需在该浏览器上进行测试。如果所有的人都使用 T1 专线,可能不需要测试下载施加。
  (但需要注意的是,可能会有员工从家里拨号进入系统) 有些内部应用程序,开发部门可能
  在系统需求中声明不支持某些系统而只支持一些那些已设置的系统。但是,理想的情况是,
  系统能在所有机器上运行,这样就不会限制将来的发展和变动。
  六、安全测试
  Web应用系统的安全性测试区域主要有:
  1、 目录设置
  Web 安全的第一步就是正确设置目录。每个目录下应该有 index.html 或 main.html 页
  面,这样就不会显示该目录下的所有内容。如果没有执行这条规则。那么选中一幅图片,单击鼠标右键,找到该图片所在的路径"…com/objects/images"。然后在浏览器地址栏中手工输入该路径,发现该站点所有图片的列表。这可能没什么关系。但是进入下一级目录 "…com/objects" ,点击 jackpot。在该目录下有很多资料,其中有些都是已过期页面。如果该公司每个月都要更改产品价格信息,并且保存过期页面。那么只要翻看了一下这些记录,就可以估计他们的边际利润以及他们为了争取一个合同还有多大的降价空间。如果某个客户在谈判之前查看了这些信息,他们在谈判桌上肯定处于上风。
  2.登录
  现在的Web应用系统基本采用先注册,后登陆的方式。因此,必须测试有效和无效的用户名和密码,要注意到是否大小写敏感,可以试多少次的限制,是否可以不登陆而直接浏览某个页面等。
  3.Session
  Web应用系统是否有超时的限制,也就是说,用户登陆后在一定时间内(例如15分钟)没有点击任何页面,是否需要重新登陆才能正常使用。
  4.日志文件
  为了保证Web应用系统的安全性,日志文件是至关重要的。需要测试相关信息是否写进了日志文件、是否可追踪。
  5.加密
  当使用了安全套接字时,还要测试加密是否正确,检查信息的完整性。
  6.安全漏洞
  服务器端的脚本常常构成安全漏洞,这些漏洞又常常被黑客利用。所以,还要测试没有经过授权,就不能在服务器端放置和编辑脚本的问题。
  目前网络安全问题日益重要,特别对于有交互信息的网站及进行电子商务活动的网站尤其重要。目前我们的测试没有涵盖网站的安全性的测试,我们拟定采用工具来测定,
  工具如下
  SAINT------- Security Administrator’s Integrated Network Tool
  此工具能够测出网站系统的相应的安全问题,并且能够给出安全漏洞的解决方案,不过是一些较为常见的漏洞解决方案。
  七、代码合法性测试
  代码合法性测试主要包括2个部分:程序代码合法性检查与显示代码合法性检查。
  1、程序代码合法性检查
  程序代码合法性检查主要标准为《intergrp小组编程规范》,目前采用由SCM管理员进行规范的检查,未来期望能够有相应的工具进行测试。
  2、显示代码合法性检查
  显示代码的合法性检查,主要分为Html、JavaScript、Css代码检查,目前采用
  HTML代码检查------采用CSE HTML Validator进行测试
  JavaScript、Css也可以在网上下载相应的测试工具。
  八、 文档测试
  l、产品说明书属性检查清单
  1)完整.是否有遗漏和丢失,完全吗? 单独使用是否包含全部内容
  2)准确.既定解决方案正确吗? 目标明确吗? 有没有错误?
  3)精确、不含糊、清晰.描述是否一清二楚? 还是自说自话?容易看懂和理解吗?
  4)一致.产品功能能描述是否自相矛盾,与其他功能有没有冲突
  5)贴切.描述功能的陈述是否必要?有没有多余信息? 功能是否原来的客户要求?
  6)合理.在特定的预算和进度下,以现有人力,物力和资源能否实现?
  7)代码无关.是否坚持定义产品,而不是定义其所信赖的软件设计,架构和代码
  8)可测试性.特性能否测试? 测试员建立验证操作的测试程序是否提供足够的信息?
  2、 产品说明书用语检查清单
  1)说明。 对问题的描述通常表现为粉饰没有仔细考虑的功能----可归结于前文所述的属性.从产品说明书上找出这样的用语,仔细审视它们在文中是怎样使用的.产品说明书可能会为其掩饰和开脱,也可能含糊其词----无论是哪一种情况都可视为软件缺陷.
  2)总是,每一种,所有,没有,从不.如果看到此类绝对或肯定的,切实认定的叙述,软件测试员就可以着手设计针锋相对的案例.
  3)当然,因此,明显,显然,必然.这些话意图诱使接受假定情况.不要中了圈套.
  4)某些,有时,常常,通常,惯常,经常,大多,几乎.这些话太过模糊."有时"发生作用的功能无法测试.
  5)等等,诸如此类,依此类推.以这样的词结束的功能清单无法测试.功能清单要绝对或者解释明确,以免让人迷惑,不知如何推论.
  6)良好,迅速,廉价,高效,小,稳定.这些是不确定的说法,不可测试.如果在产品说明书中出现,就必须进一步指明含义.
  7)已处理,已拒绝,已忽略,已消除.这些廉洁可能会隐藏大量需要说明的功能.
  8)如果...那么...(没有否则).找出有"如果...那么..."而缺少配套的"否则"结构的陈述.想一想"如果"没有发生会怎样.
  相关的测试工具
  OpenSTA
  主要做性能测试的负荷及压力测试,使用比较方便,可以编写测试脚本,也可以先行自动生成测试脚本,而后对于应用测试脚本进行测试。
  SAINT
  网站安全性测试,能够对于指定网站进行安全性测试,并可以提供安全问题的解决方案。
  CSE HTML Validator
  一个有用的对于HTML代码进行合法性检查的工具
  Ab(Apache Bench)
  Apache自带的对于性能测试方面的工具,功能不是很多,但是非常实用。
  Crash-me
  Mysql自带的测试数据库性能的工具,能够测试多种数据库的性能。
posted @ 2008-02-22 14:21 李得志 阅读(141) | 评论 (0)编辑

2008年1月21日 #

     摘要: xx局改造方案建议书项目名称:xx局改造工程项目 项目编号:wibj-gdq-200403 文档编号:wibj-gdq-200403-fa 版 本:1.0 发行日期:2004年03月 目  录 一、概  述 5 二、需求分析 5 2.1 异构系统 6 2.2 异构应用 8 2.3 异构数据 8 2.4 网站结构 9 2.5 内容海量 10 2.6 内容深度 10 2.7 服务深度 10 2.8 发... 阅读全文
posted @ 2008-01-21 19:40 李得志 阅读(131) | 评论 (0)编辑

2008年1月10日 #

●十条创业感悟
1、做小生意,解决生活中的问题;做大生意,解决社会中遇到的问题。
2、生活中处处充满商机,若没有发现,是因为你缺少一双发现商机的眼睛。
3、创业,最需要的不是资金,也不是人才,而是一个好的思路;没有资金,可以筹集;没有人才,可以召集;而没有一个好的思路,就很难找来资金和人才,创业思路决定企业的出路。
4、创业,设定目标很重要,没有目标,就缺少了奋斗的方向,这样就容易走弯路。
5、选合作伙伴,是选择互补性!比如你懂管理,找一个懂营销的做你的合作伙伴;你有资金,找一个有项目懂技术的人做你的合作伙伴。
6、在创业者眼里,没有什么不可能的事情,只有一些亟待解决的问题。
7、失败对创业者来说是一笔财富,只有小的失败才能积累大的成功。
8、创业,机会很重要,但机会往往青睐有准备的人,如果没有准备,当机会突然降临时,是很难把握住的,因为把机会转变成财富,需要一定的能力,而能力不是短时间能得到的!
9、创业,有许多潜规则,这是书本上看不到的,因为潜规则本身就是说不清道不明的东西,是需要悟的,只有你经历过了,你才可能悟到。
10、创业,贵在坚持,对于你看好的事情,一定不要轻易放弃,因为,失败与成功之间只有一步之遥。
posted @ 2008-01-10 10:00 李得志 阅读(289) | 评论 (8)编辑

2008年1月6日 #

     摘要: js验证表单大全,超级的强悍的javascript代码js验证表单大全1. 长度限制<script>function test() {if(document.a.b.value.length>50){alert("不能超过50个字符!");document.a.b.focus();return false;}}</script><form name=a >... 阅读全文
posted @ 2008-01-06 15:48 李得志 阅读(48) | 评论 (0)编辑

2007年12月27日 #

int flag=0;
   Connection.Open();
   string sql="insert into MsgInfo(title,content,sendtime) values('"+bVO.Subject+"','"+bVO.Content+"','"+bVO.Fbtime+"')";
   SqlCommand sqlComm = new SqlCommand(sql,Connection);
   flag = sqlComm.ExecuteNonQuery();
   sql="select @@identity as id from MsgInfo";
   sqlComm = new SqlCommand(sql,Connection);
   SqlDataReader tmpReader = sqlComm.ExecuteReader();
   if(tmpReader.Read())
   {
    flag = Convert.ToInt32(tmpReader["id"].ToString());
  
}
   Connection.Close();
   return flag;

posted @ 2007-12-27 15:47 李得志 阅读(125) | 评论 (3)编辑