第一篇:51CTO下载-Sql server2005 优化查询速度50个方法小结
Sql server2005 优化查询速度50个方法小结
Sql server2005优化查询速度51法查询速度慢的原因很多,常见如下几种,大家可以参考下。
I/O吞吐量小,形成了瓶颈效应。
没有创建计算列导致查询不优化。
内存不足。
网络速度慢。
查询出的数据量过大(可以采用多次查询,其他的方法降低数据量)。
锁或者死锁(这也是查询慢最常见的问题,是程序设计的缺陷)。
sp_lock,sp_who,活动的用户查看,原因是读写竞争资源。
返回了不必要的行和列。
查询语句不好,没有优化。
可以通过如下方法来优化查询 :
1、把数据、日志、索引放到不同的I/O设备上,增加读取速度,以前可以将Tempdb应放在RAID0上,SQL2000不在支持。数据量(尺寸)越大,提高I/O越重要。
2、纵向、横向分割表,减少表的尺寸(sp_spaceuse)。
3、升级硬件。
4、根据查询条件,建立索引,优化索引、优化访问方式,限制结果集的数据量。注意填充因子要适当(最好是使用默认值0)。索引应该尽量小,使用字节数小的
列建索引好(参照索引的创建),不要对有限的几个值的字段建单一索引如性别字段。
5、提高网速。
6、扩大服务器的内存,Windows 2000和SQL server 2000能支持4-8G的内存。配置虚拟内存:虚拟内存大小应基于计算机上并发运行的服务进行配置。运行 Microsoft SQL Server? 2000 时,可考虑将虚拟内存大小设置为计算机中安装的物理内存的 1.5 倍。如果另外安装了全文检索功能,并打算运行 Microsoft 搜索服务以便执行全文索引和查询,可考虑:将虚拟内存大小配置为至少是计算机中安装的物理内存的 3 倍。将 SQL Server max server memory 服务器配置选项配置为物理内存的 1.5 倍(虚拟内存大小设置的一半)。
7、增加服务器 CPU个数;但是必须明白并行处理串行处理更需要资源例如内存。使用并行还是串行程是MsSQL自动评估选择的。单个任务分解成多个任务,就可以在处理器 上运行。例如耽搁查询的排序、连接、扫描和GROUP BY字句同时执行,SQL SERVER根据系统的负载情况决定最优的并行等级,复杂的需要消耗大量的CPU的查询最适合并行处理。但是更新操作Update,Insert,Delete还不能并行处理。
8、如果是使用like进行查询的话,简单的使用index是不行的,但是全文索引,耗空间。like 'a%' 使用索引 like '%a' 不使用索引用 like '%a%' 查询时,查询耗时和字段值总长度成正比,所以不能用CHAR类型,而是VARCHAR。对于字段的值很长的建全文索引。
9、DB Server 和APPLication Server 分离;OLTP和OLAP分离。
10、分布式分区视图可用于实现数据库服务器联合体。联合体是一组分开
管理的服务器,但它们相互协作分担系统的处理负荷。这种通过分区数据形成数据库服 务器联合体的机制能够扩大一组服务器,以支持大型的多层 Web 站点的处理需要。有关更多信息,参见设计联合数据库服务器。(参照SQL帮助文件'分区视图')
在实现分区视图之前,必须先水平分区表。
在创建成员表后,在每个成员服务器上定义一个分布式分区视图,并且每个视图具有相同的名称。这样,引用分布式分区视图名的查询可以在任何一个成员服务器 上运行。系统操作如同每个成员服务器上都有一个原始表的复本一样,但其实每个服务器上只有一个成员表和一个分布式分区视图。数据的位置对应用程序是透明 的。
11、重建索引 DBCC REINDEX ,DBCC INDEXDEFRAG,收缩数据和日志 DBCC SHRINKDB,DBCC SHRINKFILE.设置自动收缩日志.对于大的数据库不要设置数据库自动增长,它会降低服务器的性能。在T-sql的写法上有很大的讲究,下面列出常见的要点:首 先,DBMS处理查询计划的过程是这样的:
查询语句的词法、语法检查。
将语句提交给DBMS的查询优化器。
优化器做代数优化和存取路径的优化。
由预编译模块生成查询规划。
然后在合适的时间提交给系统处理执行。
最后将执行结果返回给用户其次,看一下SQL SERVER的数据存放的结构:一个页面的大小为8K(8060)字节,8个页面为一个盘区,按照B树存放。
12、Commit和rollback的区别 Rollback:回滚所有的事物。Commit:
提交当前的事物.没有必要在动态SQL里写事物,如果要写请写在外面如: begin tran exec(@s)commit trans 或者将动态SQL 写成函数或者存储过程。[SPAN]
13、在查询Select语句中用Where字句限制返回的行数,避免表扫描,如果返回不必要的数据,浪费了服务器的I/O资源,加重了网络的负担降低性能。如果表很大,在表扫描的期间将表锁住,禁止其他的联接访问表,后果严重。
14、SQL的注释申明对执行没有任何影响。
15、尽可能不使用光标,它占用大量的资源。如果需要row-by-row地执行,尽量采用非光标技术,如:在客户端循环,用临时表,Table变量,用子查询,用Case语句等等。游标可以按照它所支持的提取选项进行分类: 只进 必须按照从第一行到最后一行的顺序提取行。FETCH NEXT 是唯一允许的提取操作,也是默认方式。可滚动性可以在游标中任何地方随机提取任意行。游标的技术在SQL2000下变得功能很强大,他的目的是支持循环。有四个并发选项 READ_ONLY:不允许通过游标定位更新(Update),且在组成结果集的行中没有锁。OPTIMISTIC WITH valueS:乐观并发控制是事务控制理论的一个标准部分。乐观并发控制用于这样的情形,即在打开游标及更新行的间隔中,只有很小的机会让第二个用户更新 某一行。当某个游标以此选项打开时,没有锁控制其中的行,这将有助于最大化其处理能力。如果用户试图修改某一行,则此行的当前值会与最后一次提取此行时获 取的值进行比较。如果任何值发生改变,则服务器就会知道其他人已更新了此行,并会返回一个错误。如果值是一样的,服务器就执行修改。选择这个并发选项 OPTIMISTIC WITH ROW VERSIONING:此乐观并发控制选项基于行版本控制。使用行版本控制,其中的表必须具有某种
版本标识符,服务器可用它来确定该行在读入游标后是否有 所更改。在 SQL Server 中,这个性能由 timestamp 数据类型提供,它是一个二进制数字,表示数据库中更改的相对顺序。每个数据库都有一个全局当前时间戳值:@@DBTS。每次以任何方式更改带有 timestamp 列的行时,SQL Server 先在时间戳列中存储当前的 @@DBTS 值,然后增加 @@DBTS 的值。如果某 个表具有 timestamp 列,则时间戳会被记到行级。服务器就可以比较某行的当前时间戳值和上次提取时所存储的时间戳值,从而确定该行是否已更新。服务器不必比较所有列的值,只需 比较 timestamp 列即可。如果应用程序对没有 timestamp 列的表要求基于行版本控制的乐观并发,则游标默认为基于数值的乐观并发控制。
SCROLL LOCKS 这个选项实现悲观并发控制。在悲观并发控制中,在把数据库的行读入游标结果集时,应用程序将试图锁定数据库行。在使用服务器游标时,将行读入游标时会在其 上放置一个更新锁。如果在事务内打开游标,则该事务更新锁将一直保持到事务被提交或回滚;当提取下一行时,将除去游标锁。如果在事务外打开游标,则提取下 一行时,锁就被丢弃。因此,每当用户需要完全的悲观并发控制时,游标都应在事务内打开。更新锁将阻止任何其它任务获取更新锁或排它锁,从而阻止其它任务更 新该行。然而,更新锁并不阻止共享锁,所以它不会阻止其它任务读取行,除非第二个任务也在要求带更新锁的读取。滚动锁根据在游标定义的 Select 语句中指定的锁提示,这些游标并发选项可以生成滚动锁。滚动锁在提取时在每行上获取,并保持到下次提取或者游标关闭,以先发生者为准。下次提取时,服务器 为新提取中的行获取滚动锁,并释放上次提取中行的滚动锁。滚动锁独立于事务锁,并可以保持到一个提交或回滚操作之
后。如果提交时关闭游标的选项为关,则 COMMIT 语句并不关闭任何打开的游标,而且滚动锁被保留到提交之后,以维护对所提取数据的隔离。所获取滚动锁的类型取决于游标并发选项和游标 Select 语句中的锁提示。锁提示 只读 乐观数值 乐观行版本控制 锁定无提示 未锁定 未锁定 未锁定 更新 NOLOCK 未锁定 未锁定未锁定 未锁定 HOLDLOCK 共享 共享 共享 更新 UPDLOCK 错误 更新 更新 更新 TABLOCKX 错误 未锁定 未锁定更新其它 未锁定 未锁定 未锁定 更新 *指定 NOLOCK 提示将使指定了该提示的表在游标内是只读的。
16、用Profiler来跟踪查询,得到查询所需的时间,找出SQL的问题所在;用索引优化器优化索引。
17、注意UNion和UNion all 的区别。UNION all好。
18、注意使用DISTINCT,在没有必要时不要用,它同UNION一样会使查询变慢。重复的记录在查询里是没有问题的。
19、查询时不要返回不需要的行、列。
20、用sp_configure 'query governor cost limit'或者SET QUERY_GOVERNOR_COST_LIMIT来限制查询消耗的资源。当评估查询消耗的资源超出限制时,服务器自动取消查询,在查询之前就扼杀掉。SET LOCKTIME设置锁的时间。
21、用select top 100 / 10 Percent 来限制用户返回的行数或者SET ROWCOUNT来限制操作的行。
22、在SQL2000以前,一般不要用如下的字句: “IS NULL”, “<>”, “!=”, “!>”, “!<”, “NOT”, “NOT EXISTS”, “NOT IN”, “NOT LIKE”, and “LIKE
'%500'”,因为他们不走索引全是表扫描。也不要在Where字句中的列名加函数,如Convert,substring等,如果必须用函数的时候,创建计算列再创建索引来替代.还可以变通写法:Where SUBSTRING(firstname,1,1)= 'm'改为Where firstname like 'm%'(索引扫描),一定要将函数和列名分开。并且索引不能建得太多和太大。NOT IN会多次扫描表,使用EXISTS、NOT EXISTS,IN , LEFT OUTER JOIN 来替代,特别是左连接,而Exists比IN更快,最慢的是NOT操作.如果列的值含有空,以前它的索引不起作用,现在2000的优化器能够处理了。相同 的是IS NULL,“NOT”, “NOT EXISTS”, “NOT IN”能优化她,而“<>”等还是不能优化,用不到索引。[SPAN]
23、使用Query Analyzer,查看SQL语句的查询计划和评估分析是否是优化的SQL。一般的20%的代码占据了80%的资源,我们优化的重点是这些慢的地方。
24、如果使用了IN或者OR等时发现查询没有走索引,使用显示申明指定索引: Select * FROM PersonMember(INDEX = IX_Title)Where processid IN('男','女')。
25、将需要查询的结果预先计算好放在表中,查询的时候再Select。这在SQL7.0以前是最重要的手段。例如医院的住院费计算。
26、MIN()和 MAX()能使用到合适的索引。
27、数据库有一个原则是代码离数据越近越好,所以优先选择Default,依次为Rules,Triggers, Constraint(约束如外健主健CheckUNIQUE……,数据类型的最大长度等等都是约束),Procedure.这样不仅维护工作小,编写程 序质量高,并且执行的速度快。
28、如果要插入大的二进制值到Image列,使用存储过程,千万不要用内嵌Insert来插入(不知JAVA是 否)。因为这样应用程序首先将二进制值转换成字符串(尺寸是它的两倍),服务器受到字符后又将他转换成二进制值.存储过程就没有这些动作: 方法:Create procedure p_insert as insert into table(Fimage)values(@image), 在前台调用这个存储过程传入二进制参数,这样处理速度明显改善。
29、Between在某些时候比IN 速度更快,Between能够更快地根据索引找到范围。用查询优化器可见到差别。select * from chineseresume where title in('男','女')Select * from chineseresume where between '男' and '女' 是一样的。由于in会在比较多次,所以有时会慢些。
30、在必要是对全局或者局部临时表创建索引,有时能够提高速度,但不是一定会这样,因为索引也耗费大量的资源。他的创建同是实际表一样。
31、不要建没有作用的事物例如产生报表时,浪费资源。只有在必要使用事物时使用它。
32、用OR的字句可以分解成多个查询,并且通过UNION 连接多个查询。他们的速度只同是否使用索引有关,如果查询需要用到联合索引,用UNION all执行的效率更高.多个OR的字句没有用到索引,改写成UNION的形式再试图与索引匹配。一个关键的问题是否用到索引。
33、尽量 少用视图,它的效率低。对视图操作比直接对表操作慢,可以用stored procedure来代替她。特别的是不要用视图嵌套,嵌套视图增加了寻找原始资料的难度。我们看视图的本质:它是存放在服务器上的被优化好了的已经产生 了查询规划的SQL。对单个表检索数据时,不要使用指向多个表的视图,直
接从表检索或者仅仅包含这个表的视图上读,否则增加了不必要的开销,查询受到干 扰.为了加快视图的查询,MsSQL增加了视图索引的功能。
34、没有必要时不要用DISTINCT和ORDER BY,这些动作可以改在客户端执行。它们增加了额外的开销。这同UNION 和UNION ALL一样的道理。
select top 20 ad.companyname,comid,position,ad.referenceid,worklocation, convert(varchar(10),ad.postDate,120)as postDate1,workyear,degreedescription FROM jobcn_query.dbo.COMPANYAD_query ad where referenceID in('JCNAD00329667','JCNAD132168','JCNAD00337748','JCNAD00338345','JCNAD00333138','JCNAD00303570','JCNAD00303569','JCNAD00303568','JCNAD00306698','JCNAD00231935','JCNAD00231933','JCNAD00254567','JCNAD00254585','JCNAD00254608','JCNAD00254607','JCNAD00258524','JCNAD00332133','JCNAD00268618','JCNAD00279196','JCNAD00268613')order by postdate desc
35、在IN后面值的列表中,将出现最频繁的值放在最前面,出现得最少的放在最后面,减少判断的次数。
36、当用Select INTO时,它会锁住系统表(sysobjects,sysindexes等等),阻塞其他的连接的存取。创建临时表时用显示申明语句,而不是 select INTO.drop table t_lxh begin tran select * into t_lxh from chineseresume where name = 'XYZ'--commit 在另一个连接中Select * from sysobjects可以看到 Select INTO 会锁住系统表,Create table 也会锁系统表(不管是临时表还是系统表)。所以千万不要在事物内使用它!!这样的话如果是经常要用的临时表请使用实表,或者临时表变量。
37、一般在GROUP BY 个HAVING字句之前就能剔除多余的行,所以尽量不要用它们来做剔除行的工作。他们的执行顺序应该如下最优:select 的Where字句选择所有合适的行,Group By用来分组个统计行,Having字句用来剔除多余的分组。这样Group By 个Having的开销小,查询快.对于大的数据行进行分组和Having十分消耗资源。如果Group BY的目的不包括计算,只是分组,那么用Distinct更快。
38、一次更新多条记录比分多次更新每次一条快,就是说批处理好。[SPAN]
39、少用临时表,尽量用结果集和Table类性的变量来代替它,Table 类型的变量比临时表好。
40、在SQL2000下,计算字段是可以索引的,需要满足的条件如下:
计算字段的表达是确定的。
不能用在TEXT,Ntext,Image数据类型。
必须配制如下选项 ANSI_NULLS = ON, ANSI_PADDINGS = ON, ……。
41、尽量将数据的处理工作放在服务器上,减少网络的开销,如使用存储过程。存储过程是编译好、优化过、并且被组织到一个执行规划里、且存储在数据库中 的SQL 语句,是控制流语言的集合,速度当然快。反复执行的动态SQL,可以使用临时存储过程,该过程(临时表)被放在Tempdb中。以前由于SQL SERVER对复杂的数学计算不支持,所以不得不将这个工作放在其他的层上而增加网络的开销。SQL2000支持UDFs,现在支持复杂的数学计算,函数 的返回值不要太大,这样的开销很大。用户自定义函数象光标一样执行的消耗大量的资源,如果返回大的结果采用存储过程。
42、不要在一句话里再三的使用相同的函数,浪费资源,将结果放在变量里再调用更快。
43、Select COUNT(*)的效率教低,尽量变通他的写法,而EXISTS快.同时请注意区别: select count(Field of null)from Table 和 select count(Field of NOT null)from Table 的返回值是不同的!!
44、当服务器的内存够多时,配制线程数量 = 最大连接数+5,这样能发挥最大的效率;否则使用 配制线程数量<最大连接数启用SQL SERVER的线程池来解决,如果还是数量 = 最大连接数+5,严重的损害服务器的性能。
45、按照一定的次序来访问你的表。如果你先锁住表A,再锁住表B,那么在所有的存储过程中都要按照这个顺序来锁定它们。如果你(不经意的)某个存储过程中先锁定表B,再锁定表A,这可能就会导致一个死锁。如果锁定顺序没有被预先详细的设计好,死锁很难被发现。
46、通过SQL Server Performance Monitor监视相应硬件的负载 Memory: Page Faults / sec计数器如果该值偶尔走高,表明当时有线程竞争内存。如果持续很高,则内存可能是瓶颈。
Process:
% DPC Time 指在范例间隔期间处理器用在缓延程序调用(DPC)接收和提供服务的百分比。(DPC 正在运行的为比标准间隔优先权低的间隔)。由于 DPC 是以特权模式执行的,DPC 时间的百分比为特权时间百分比的一部分。这些时间单独计算并且不属于间隔计算总数的一部 分。这个总数显示了作为实例时间百分比的平均忙时。
%Processor Time计数器 如果该参数值持续超过95%,表明瓶颈是CPU。可以考虑增加一个处理器或换一个更快的处理器。
% Privileged Time 指非闲置处理器时间用于特权模式的百分比。(特权模式是为操作系统组件和操纵硬件驱动程序而设计的一种处理模式。它允许直接访问硬件和所有内存。另一种模 式为用户模式,它是一种为应用程序、环境分系统和整数分系统设计的一种有限处理模式。操作系统将应用程序线程转换成特权模式以访问操作系统服务)。特权时 间的 % 包括为间断和 DPC 提供服务的时间。特权时间比率高可能是由于失败设备产生的大数量的间隔而引起的。这个计数器将平均忙时作为样本时间的一部分显示。
% User Time表示耗费CPU的数据库操作,如排序,执行aggregate functions等。如果该值很高,可考虑增加索引,尽量使用简单的表联接,水平分割大表格等方法来降低该值。Physical Disk: Curretn Disk Queue Length计数器该值应不超过磁盘数的1.5~2倍。要提高性能,可增加磁盘。
SQLServer:Cache Hit Ratio计数器该值越高越好。如果持续低于80%,应考虑增加内存。注意该参数值是从SQL Server启动后,就一直累加记数,所以运行经过一段时间后,该值将不能反映系统当前值。
47、分析select emp_name form.employee where salary > 3000 在此
语句中若salary是Float类型的,则优化器对其进行优化为Convert(float,3000),因为3000是个整数,我们应在编程时使 用3000.0而不要等运行时让DBMS进行转化。同样字符和整型数据的转换。
48、查询的关联同写的顺序
select a.personMemberID, * from chineseresume a,personmember b where personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681'(A = B ,B = '号码')
select a.personMemberID, * from chineseresume a,personmember b where a.personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681' and b.referenceid = 'JCNPRH39681'(A = B ,B = '号码',A = '号码')
select a.personMemberID, * from chineseresume a,personmember b where b.referenceid = 'JCNPRH39681' and a.personMemberID = 'JCNPRH39681'(B = '号码',A = '号码')
49、(1)IF 没有输入负责人代码 THEN code1=0 code2=9999 ELSE code1=code2=负责人代码 END IF 执行SQL语句为: Select 负责人名 FROM P2000 Where 负责人代码>=:code1 AND负责人代码 <=:code2
(2)IF 没有输入负责人代码 THEN Select 负责人名 FROM P2000 ELSE code= 负责人代码 Select 负责人代码 FROM P2000 Where 负责人代码=:code END IF 第一种方法只用了一条SQL语句,第二种方法用了两条SQL语句。在没有输入负责人代码时,第二种方法显然比第一种方法执行效率高,因为
它没有限制条件;在输入了负责人代码时,第二种方法仍然比第一种方法效率高,不仅是少了一个限制条件,还因相等运算是最快的查询运算。我们写程序不要怕麻烦
50、关于JOBCN现在查询分页的新方法(如下),用性能优化器分析性能的瓶颈,如果在I/O或者网络的速度上,如下的方法优化切实有效,如果在CPU或者内存上,用现在的方法更好。请区分如下的方法,说明索引越小越好。
begin
DECLARE @local_variable table(FID int identity(1,1),ReferenceID varchar(20))
insert into @local_variable(ReferenceID)
select top 100000 ReferenceID from chineseresume order by ReferenceID
select * from @local_variable where Fid > 40 and fid <= 60
end 和
begin
DECLARE @local_variable table(FID int identity(1,1),ReferenceID varchar(20))
insert into @local_variable(ReferenceID)
select top 100000 ReferenceID from chineseresume order by updatedate
select * from @local_variable where Fid > 40 and fid <= 60
end 的不同
begin
create table #temp(FID int identity(1,1),ReferenceID varchar(20))
insert into #temp(ReferenceID)
select top 100000 ReferenceID from chineseresume order by updatedate
select * from #temp where Fid > 40 and fid <= 60 drop table #temp
end[SPAN]
另附:存储过程编写经验和优化措施
一、适合读者对象:数据库开发程序员,数据库的数据量很多,涉及到对SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。
二、介绍:在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作。如果项目的SP较多,书写又没有一 定的规范,将会影响以后的系统维护困难和大SP逻辑的难以理解,另外如果数据库的数据量大或者项目对SP的性能要求很,就会遇到优化的问题,否则速度有可 能很慢,经过亲身经验,一个经过优化过的SP要比一个性能差的SP的效率甚至高几百倍。
三、内容:
1、开发人员如果用到其他库的Table或View,务必在当前库中建立View来实现跨库操作,最好不要直接使用“databse.dbo.table_name”,因为sp_depends不能显示出该SP所使用的跨库table或view,不方便校验。
2、开发人员在提交SP前,必须已经使用set showplan on分析过查询计划,做过自身的查询优化检查。
3、高程序运行效率,优化应用程序,在SP编写过程中应该注意以下几点:
a)SQL的使用规范:
尽量避免大事务操作,慎用holdlock子句,提高系统并发能力。
尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑先根据条件提取数据到临时表中,然后再做连接。
尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进行表连接的操作。
注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围从大到小。
不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
尽量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用,而且count(1)比count(*)更有效率。
尽量使用“>=”,不要使用“>”。
注意一些or子句和union子句之间的替换
注意表之间连接的数据类型,避免不同类型数据之间的连接。
注意存储过程中参数和数据类型的关系。
注意insert、update操作的数据量,防止与其他应用冲突。如果数据量超过200个数据页面(400k),那么系统将会进行锁升级,页级锁会升级成表级锁。
b)索引的使用规范:
索引的创建要与应用结合考虑,建议大的OLTP表不要超过6个索引。
尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通过index index_name来强制指定索引
避免对大表查询时进行table scan,必要时考虑新建索引。
在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用。
要注意索引的维护,周期性重建索引,重新编译存储过程。
c)tempdb的使用规范:
尽量避免使用distinct、order by、group by、having、join、cumpute,因为这些语句会加重tempdb的负担。
避免频繁创建和删除临时表,减少系统表资源的消耗。
在新建临时表时,如果一次性插入数据量很大,那么可以使用select into代替create table,避免log,提高速度;如果数据量不大,为了缓和系统表的资源,建议先create table,然后insert。
如果临时表的数据量较大,需要建立索引,那么应该将创建临时表和建立索引的过程放在单独一个子存储过程中,这样才能保证系统能够很好的使用到该临时表的索引。
如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate table,然后drop table,这样可以避免系统表的较长时间锁定。
慎用大的临时表与其他大表的连接查询和修改,减低系统表负担,因为这种操作会在一条语句中多次使用tempdb的系统表。
d)合理的算法使用:
根据上面已提到的SQL优化技术和ASE Tuning手册中的SQL优化内容,结合实际应用,采用多种算法进行比较,以获得消耗资源最少、效率最高的方法。具体可用ASE调优命令:set statistics io on, set statistics time on , set showplan on 等。
第二篇:提高手机游戏速度的优化小结
目录
1.优化方法简介:...........................................................................2 2.各种优化方法的介绍:...............................................................2
2.1.修改刷新游戏界面的Timer函数及其delay值......................2 2.2.取片内RAM作为游戏运行的BUFFER.......................................3 2.3.修改ADS编译选项,以期达到提高游戏速度的目的..........7 2.4.通过提高MCU时钟频率的方法来提高游戏速度....................7 2.5.优化系统函数gdi_layer_blt().............................................8 2.6.优化系统函数gdi_image_draw()...........................................8
3.优化结论:...................................................................................8
3.1.绘图方面的代码跟踪................................................................9 3.2.GDI多层显示的代码跟踪.........................................................9
1.优化方法简介:
针对目前部分游戏速度不够流畅的问题,我们之前讨论并确定了4种提高游戏速度的优化方法,加上外部兄弟公司的建议,暂时有以下一些优化方法: 1> 修改刷新游戏界面的Timer函数及其delay值; 2> 取片内RAM作为游戏运行的BUFFER;
3> 修改ADS编译优化选项,以期达到以空间换时间的目的; 4> 通过提高MCU时钟频率的方法来提高游戏速度;
5> 优化使用GDI多层方式必须调用的系统函数gdi_layer_blt(); 6> 优化游戏绘图时必须调用的系统绘图接口函数gdi_image_draw(); 7> 使用DMA的方法刷新LCD的局部BUFFER显示; 8> 使用2层的绘图机制,删除未使用的另外2层;
9> 使用4层的绘图机制,将BUFFER区域较小且刷新较频繁的图片独立为1层,以减少刷新时间;
2.各种优化方法的介绍:
到目前为止,已试验了其中的一些优化方法,但还有一些优化方法待试验,以下详细介绍各种已试验的优化方法,包括应用该方法时应该注意的地方,以及试验结果。
2.1.修改刷新游戏界面的Timer函数及其delay值
对于方法1,已拿七龙珠游戏进行了一些试验,原来使用的Timer函数是:StartTimer(),设置的Delay=75ms,将Delay值修改为5ms时,七龙珠等游戏的速度有比较大的提高,刷新也比较流畅了,基本能满足要求,但因为该Timer函数只是一个应用层使用的接口函数,其精度不是太高,无法准确的控制各游戏的速度;MTK6225平台使用该Timer函数能达到的最快速度是5帧/秒,也就是说其Delay值最小只能是20,即使把Delay值设为5,也达不到Delay值对应的速度; 针对应用层的Timer函数StartTimer()精度不高,还试验了使用驱动层的Timer函数:kal_set_timer()来控制游戏的刷新,该函数的精度更高,但查阅MTK的相关资料知道,MTK6225平台的APP_TASK不能使用该Timer函数,如果一定要使用该Timer函数来控制游戏的刷新,则需要新建一个游戏TASK,该方法还未试验,使用该Timer函数的效果如何,需要试验来进一步确认;
2.2.取片内RAM作为游戏运行的BUFFER 由于片内RAM的可用空间非常有限,大概只有72KB(该数据来自MTK6225的Datasheet资料)左右,由于一些系统文件以及对速度有较高要求的模块已放置片内RAM中运行,目前剩余的片内RAM空间大概只有8KB左右,调试阶段也可以删除一些放在片内RAM的其它文件,使得优化游戏的可用片内RAM空间更大一些;
片内RAM方法的使用,主要是通过使用如下的编译指令:
#pragma arm section code=“MAOL_INTERNCODE”, rodata=“MAOL_INTERN_RO”, rwdata=“MAOL_INTERN_RW”, zidata=“MAOL_INTERN_ZI” ………………………… 函数或者数据 …………………………
#pragma arm section code, rodata, rwdata, zidata 将需要放在片内RAM中分配空间或运行的数据或者函数放在以上编译指令中,然后将包含该编译指令的目标文件放在Scat***.txt文件的INTSRAM_CODE区域中即可;
以下是使用片内RAM方法时,得出的一些试验结果以及需要注意的地方: 1.通过运行如下的冒泡排序算法试验,将该算法放在片内RAM运行,所占用的时间大概是普通方法的1/4,void mf_game_test_func(void){ mf_u32 i,j,k;static mf_u32 num[1000];for(i=0;i<1000;i++){ num[i] = i;}
for(i=0;i<1000;i++)for(j=0;j
2.为了更直观的看到2种方法的速度差别,分别使用普通方法和片内RAM的方法,轮流显示1个小球滚动(从LCD的左上角滚动至右下角;另外,为了体现2种方法的速度差别,在函数中添加了上述的冒泡算法;另外,为了直观显示,普通方法时使用七龙珠游戏的绿球,片内RAM方法则使用同样大小的粉球),2种方法的速度差别比较大,TRACE信息显示,使用普通方法显示1帧时,需要1726ms,而使用片内RAM的方法时,只需要365ms,可见速度差别较大;另外,将程序下载到手机看实际结果时,小球滚动的速度也明显不一样;
3.在片内RAM上运行的母函数,如果调用了子函数,如果子函数运行所需的时间远小于母函数的运行时间,则该子函数是否放在片内RAM,对母函数的运行时间不会有什么影响,该母函数所需的运行时间依然只有其在片外RAM中运行时间的1/4左右; 示例如下:
试验了片内RAM中运行的函数(称为 mf_func1())调用片外RAM中运行的函数(称为mf_func3())情况,另外,还有一个函数:mf_func2(),函数:mf_func1()和mf_func2()基本一样,只是mf_func1()多调用了一个片外RAM运行的函数mf_func3(),此外mf_func1()在片内RAM运行,而mf_func2()在片外RAM运行,具体如下:
void mf_func3(void){
mf_u32 i,j,k;static mf_u32 num[100];for(i=0;i<100;i++){ num[i] = i;}
for(i=0;i<100;i++)for(j=0;j
#pragma arm section code=“MAOL_INTERNCODE”, rodata=“MAOL_INTERN_RO”, rwdata=“MAOL_INTERN_RW”, zidata=“MAOL_INTERN_ZI” void mf_func1(void){
mf_u32 i,j,k;static mf_u32 num[1000];for(i=0;i<1000;i++){ num[i] = i;}
for(i=0;i<1000;i++)for(j=0;j
#pragma arm section code, rodata, rwdata, zidata void mf_func2(void){ mf_u32 i,j,k;static mf_u32 num[1000];for(i=0;i<1000;i++){ num[i] = i;}
for(i=0;i<1000;i++)for(j=0;j
4.在片内RAM上运行的函数,尽量不要使用TRACE打印函数,因为该函数需要调用运行时间较长的串口接口函数,影响了片内RAM方法的使用,确实需要输出运行时间的,可以选择程序运行多次打印一次的方式,如程序运行100次才输出一次运行时间; 2.3.修改ADS编译选项,以期达到提高游戏速度的目的
在MTK6225平台试验了该优化方法,具体修改了optiom.mak文件:
原来:
ifeq($(strip $(PLATFORM)),MT6225)CFLAGS :=-cpu ARM7EJ-S-littleend-O2-zo-fa endif 修改为:
ifeq($(strip $(PLATFORM)),MT6225)CFLAGS :=-cpu ARM7EJ-S-littleend-Otime-zo-fa endif
结果:
修改前:
bin文件大小:13,695,180bytes = 13MB 绘制1帧七龙珠游戏所花时间:79ms 修改后:
bin文件大小:13,896,040bytes = 13.2MB 绘制1帧七龙珠游戏所花时间:69ms 比较修改前、后的结果可知,修改ADS编译选项后,BIN文件大了将近200KB,但游戏刷新速度也提高了10ms左右,实际玩七龙珠游戏时,也感觉快了不少;
所以,在实际的应用中,只要考虑如何在容量和速度之间做选择,如果手机的Flash容量允许,则选择速度较快的编译方法应该是可行的,如果手机的Flash容易不允许,则只能选择普通的编译方法了;
2.4.通过提高MCU时钟频率的方法来提高游戏速度
在MTK6225平台的A600项目上试验了该优化方法,具体步骤是:在游戏的入口处,调用以下函数:
custom_DynamicClockSwitch(MCU_104MHZ);即将系统的MCU时钟频率设置为104MHZ;
在游戏的退出函数调用以下函数:
custom_DynamicClockSwitch(MCU_13MHZ);恢复系统时钟; 进入游戏后,感觉游戏速度跟普通MCU时钟频率的一样,没有变化,TRACE信息也表明:修改MCU时钟频率没有提高游戏速度; 出现这种情况的原因可能是:进入游戏后,虽然MCU时钟频率更快了,但是系统的wait state指令周期并未改变,以及存储器的读、写周期未能相应的提高,所以即使MCU时钟频率更快,也不能发挥其作用; 具体什么原因,还不太清楚,需要找有此经验的牛人来确认;
2.5.优化系统函数gdi_layer_blt()
2.6.优化系统函数gdi_image_draw()
3.优化结论:
针对以上各种优化方法,对七龙珠游戏进行了各种优化尝试,已得出了一些程序优化的试验结果;
对于七龙珠游戏来说,显示游戏的1帧所花的时间主要在2个方面:首先是七龙珠游戏的绘图处理上,显示1帧所占的逻辑处理时间大概是38~50ms,另一方面是GDI多层显示处理,Gdi多层显示占用的时间大概是37ms,另外,Timer函数本身需要消耗一定的时间(一般是该Timer设定的delay值),所以显示1帧七龙珠游戏最快需要大概95ms左右的时间; 3.1.绘图方面的代码跟踪
游戏绘图主要使用了接口函数: gdi_image_draw(),跟踪了该函数的底层调用情况,该函数最后调用了底层的绘图函数:
GDI_RESULT gdi_image_gif_draw_handler(U32 flag, U32 frame_pos, S32 x, S32 y, S32 w, S32 h, U8 *data_ptr, U32 img_size){ }
对于该函数运行一次需要花费多长时间,尝不清楚,需要通过TRACE信息以及编写小工程计算其指令周期来确认所花时间,并找出最花时间的一个子函数,然后对该子函数进行优化,这可作为后续优化的一个方向;
3.2.GDI多层显示的代码跟踪
现在的游戏程序中,使用了多层显示的方式来绘图游戏MMI,主要是2层,分别是;background和foreground层,background层显示底图,为提高游戏的刷新速度,该层一般只显示一次;foreground层主要显示其它所有位置变化的图片,如七龙珠游戏的滚动的小球等,/*****************************2009.3.28 added*************************/ MTK6225支持GDI 4层显示:
//建立GDI 4层 mf_bool {
#if defined(GDI_USING_LAYER)
gdi_layer_multi_layer_enable();gdi_layer_get_base_handle(&hBackground);gdi_layer_set_source_key(MF_TRUE, GDI_COLOR_BLUE);gdi_layer_clear(GDI_COLOR_BLUE);MF_APP_Init()
gdi_layer_create(0, 0, LCD_WIDTH, LCD_HEIGHT, &hForeground);gdi_layer_set_active(hForeground);gdi_layer_set_source_key(MF_TRUE, GDI_COLOR_BLUE);gdi_layer_clear(GDI_COLOR_BLUE);
kal_prompt_trace(MOD_ENG,“MF_APP_Init create layer 2 ok: 4 layer flg = %d”, MF_Get_4_layer_flg());
/************************************************************************************************************************/
/*****************************frank.kang added for the mf games Multi-layer display 2009.3.13****************************/
/************************************************************************************************************************/
if(MF_Get_4_layer_flg())
{
/********************************************************************************************************************/
/****************************************************第3层***********************************************************/
/********************************************************************************************************************/
layer_3rd_gdi_buffer *)mmi_frm_scrmem_alloc(EXTRA_GDI_BUF_SIZE);
//layer_3rd_gdi_buffer =(mf_u8 *)MF_MP_malloc(312*480*2);
=
(mf_u8
kal_prompt_trace(MOD_ENG,“layer_3rd_gdi_buffer = %d”, layer_3rd_gdi_buffer);
if(layer_3rd_gdi_buffer!= NULL)
{
memset(layer_3rd_gdi_buffer, 0, sizeof(layer_3rd_gdi_buffer));
//gdi_result = gdi_layer_create_using_outside_memory(0, 0, 312, 480, &h3rdLayer,(mf_u8 *)layer_3rd_gdi_buffer, 312*480*2);
gdi_result = gdi_layer_create_using_outside_memory(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, &h3rdLayer,(mf_u8 *)layer_3rd_gdi_buffer, EXTRA_GDI_BUF_SIZE);
gdi_layer_set_active(h3rdLayer);
gdi_layer_set_source_key(MF_TRUE, GDI_COLOR_BLUE);
gdi_layer_clear(GDI_COLOR_BLUE);
//gdi_layer_set_opacity(TRUE, 180);
//gdi_layer_set_rotate(GDI_LCD_LAYER_ROTATE_90_MIRROR);
}
/********************************************************************************************************************/
/****************************************************第4层***********************************************************/
/********************************************************************************************************************/
layer_4th_gdi_buffer *)mmi_frm_scrmem_alloc(EXTRA_GDI_BUF_SIZE);
=
(mf_u8
if(layer_4th_gdi_buffer!= NULL)
{
memset(layer_4th_gdi_buffer, 0, sizeof(layer_4th_gdi_buffer));
gdi_result = gdi_layer_create_using_outside_memory(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, &h4thLayer,(mf_u8 *)layer_4th_gdi_buffer, EXTRA_GDI_BUF_SIZE);
gdi_layer_set_active(h4thLayer);
gdi_layer_set_source_key(MF_TRUE, GDI_COLOR_BLUE);
gdi_layer_clear(GDI_COLOR_BLUE);
}
}
/********************************************************************************************************************/
/********************************************frank.kang e.*****************************************************/
/********************************************************************************************************************/
}
//将GDI 4层压缩成1层,并显示到LCD BUFFER mf_bool {
if(MF_Get_4_layer_flg())MF_APP_Update()#endif
added
{
}
else
{
} }
//释放多层BUFFER void MF_Scr_Exit(void){ gdi_layer_blt(hBackground, hForeground, 0, 0, 0, 0, UI_device_width1);gdi_layer_blt(hBackground, hForeground, h3rdLayer, h4thLayer, 0, 0, UI_device_width1);#if defined(GDI_USING_LAYER)
if(hForeground)
{
kal_prompt_trace(MOD_ENG,“gdi_layer_free(hForeground)”);
gdi_layer_free(hForeground);
hForeground = 0;}
//frank.kang added for the mf games Multi-layer display 2009.3.13 kal_prompt_trace(MOD_ENG,“MF_Scr_Exit(),layer
flag
== MF_Get_4_layer_flg());
if(MF_Get_4_layer_flg())
{
if(h3rdLayer)
{
kal_prompt_trace(MOD_ENG,”gdi_layer_free(h3rdLayer)“);
gdi_layer_free(h3rdLayer);
h3rdLayer = 0;}
if(layer_3rd_gdi_buffer)
{ kal_prompt_trace(MOD_ENG,”free layer_3rd_gdi_buffer“);
mmi_frm_scrmem_free(layer_3rd_gdi_buffer);
layer_3rd_gdi_buffer = 0;}
if(h4thLayer)
{ kal_prompt_trace(MOD_ENG,”gdi_layer_free(h4thLayer)“);
%d”,} gdi_layer_free(h4thLayer);h4thLayer = 0;
if(layer_4th_gdi_buffer){ kal_prompt_trace(MOD_ENG,“free layer_4th_gdi_buffer”);
mmi_frm_scrmem_free(layer_4th_gdi_buffer);
MF_Set_4_layer_flg(0);
}
//frank.kang added e.}
gdi_layer_multi_layer_disable();//gdi_layer_set_position(0,0);} layer_4th_gdi_buffer = 0;#endif /* MF_GDI_USING_LAYER */
第三篇:《50个方法》读书心得
《50个方法》读书心得
七年组叶晨
学生的课堂表现是影响学生成绩的关键因素,只有当学生的行为有所改善后,他们的成绩与各方面能力才会相应提高。假期有幸拜读了《改善学生课堂表现的50个方法:小技巧获得大改变》。这本书详细讲述了如何帮助教师提高学生的合作与参与意识,从而提高教学效率,帮助学生最终取得进步和成功!作为一名新晋教师,对于课堂的把控有很多的困惑,包括:想让学生的表现更加优异,想使课堂活动更有效率、氛围更加活跃,想更好地激励学生。通过阅读,发现书里的这些小技巧,都很实用。
对一个教学经验还不是很熟的教师来说,刚接手班级肯定对学生很不熟悉。首先为加深了解一定要热情地打招呼让学生喜欢并愿意接受你,然后才是知识的传授,让学生觉得自己的课堂是有价值的。教师的教育行为要发挥理想的效果,必须摆脱枯燥与乏味的单一说教,从细小之处来影响学生。给学生留下深刻印象的教育片段,常常源自与不经意间的一个细节。一句平常不过的话,一个细小不过的动作。当然,在平时注意和学生谈心,问问他们眼中的老师是什么样子的可以加强师生间的了解;再就是发现学生的问题,及时沟通,让我们师生在一点一滴中共同进步共同发展。古人云:“活到老,学到老”。作为以“传道、授业、解惑”为己任的教师,需要抓住各种学习的机会,不断充实自己的知识,提高自己的素养,促进自己的专业发展。因而,不管参加有组织的学习活动还是自我学习,教师都要管理好自己的行为细节,提高课堂学习的针对性和实效性。当学生做错事时,书中教给我的是,批评和指责都不如一句“你还好吗?”这句话代表我对你的关心,当然学生就更不好意思再犯错了。别让学生难堪,这不仅不利于课堂,还会伤害师生关系。学生不仅会对教师产生厌恶情绪,还会对该门学科失去兴趣。赞扬学生的良好表现有助于建立良好的师生关系,也有助于激发学生的良好表现。所以,要少批评,多点鼓励。的确是小技巧大改变。不要训斥,不要冷漠,用心对待学生。所以要给学生多的鼓励和正面的影响,把学生塑造成积极向上的人。作为一名教师,应当做一个学生心目中快乐的榜样,任何时候都要保持乐观和理性的头脑,控制好自己和学生一起成长。
书中还提到“别再站在桌子或是讲台后面了,走到你的学生中去!”其实我在教学中有尝试并发现,这样带来的好处,就是你可以随时地观察到每个学生的学习的情况。看到小A听写单词没有用统一的听写本,而且也不能够及时的发现自己的问题,反正就是写单词,找个有空白的地方就可以,但是他没有,所以特地告诉了一下。平常小B会随时转头的,但是今天没有,一直在认真记笔记的。
“让课堂上的每个角落都留下你的身影!”我喜欢这句话,也希望自己能够时刻的提醒自己,多走进学生中间,学生在课堂的问题就越来越少。不管你的学生如何,但在你的心里认为他们都是最棒的、最好的,加上你投入自己的爱和心,不久以后你会发现,所有学生都变了,变成了你心里所希望的那样。所以教师在教学过程中,要善于捕捉学生的闪光点从而进行鼓励表扬。
如何让学生变得更有责任感?“承担一点职务可以养成一个负责任的态度!”回忆我教学杂事任务分配时只知道,我有两个课代表,好像所有的事情我都在寄希望于课代表来完成。现在想来,其实我完全可以将要分配的工作分散开来,这样也有其他的学生就可以起到与英语课有息息相关的联系。比如安排学生开电脑、准备白板笔、收发作业、传达老师布置的每日作业等等将职责分配给不同的学生,是否也可以形成对英语课的兴趣。“给你的学生一些职责,这样他们漠不关心的态度就会逐渐消失,学生的行为就会得到进一步改善”。
我们的课堂发生在学校,但后期学习的监督、督促、鼓励等也需要家长的积极配合。因此家长是课堂的隐形成员。老师如能积极调动家长的作用,有效课堂教学任务和质量必将事半功倍。作为教师,我们在与家长的沟通互动中应该积极主动,让他们感受到我们的真心。比如:当您的从未谋面的学生家长在开学前或开学初,收到您的来信。你已经为你们的合作搭建了一个很好的平台,与家长建立了良好的关系。为家校相互配合,同步教育,促进学生健康成长形成一个良好的开端。通过阅读本书我不仅了解到学生的课堂表现是影响学生成绩的关键因素,而且也更懂得了优秀的教师他们是如何通过关心、认可、鼓励学生,让学生不断进步,每天都有更好的表现。愿自己在今后的教学工作中多点智慧、多点爱心、多点耐心,相信改变自己一定能带给学生更多的进步!
最后我想说,你握住的不仅仅是学生的手,你握住的是他的未来,在他的脑海里,你并不仅仅是一名教师,你还触碰了他的心灵,你并不仅仅拭干他的泪水,抚慰他的心灵。你,已经成为他的一部分了。
第四篇:列车时刻表查询小结
列车时刻表查询小结
信息0911-2009822103-刘绘
本章主要讲述的是通过列车时刻表查询程序怎样对Google地图的二次开发,从而在网站上创建功能全面的地图应用
一、Google地图API是一种通过javaScript将Google地图嵌入到网页的API。它提供了很多处理地图的功能和地图添加内容的服务,从而在网站上创建功能全面的地图应用
1.熟练使用地图查找你所要查看的某个具体的地址 2.找到某个地方火车站的经纬度
3.显示某个列车的行走路线,一般是折线图,将坐标点连起来,一般是最短路线 4.叠加层是地图上绑定到经度纬度坐标的对象,会随您拖动或缩放地图而移动。叠加层用于反映您添加到地图上以指明点、线或区域的对象,代码如下
var map;var geocoder;var siteName=[<%=strSiteList%>];var siteLocation = new Array();function initialize(){
var myLatLng = new google.maps.LatLng(31.587074,120.305551);var myOptions = { zoom: 4, center: myLatLng, mapTypeId: google.maps.MapTypeId.ROADMAP };
map = new google.maps.Map(document.getElementById(“map_canvas”), myOptions);
geocoder = new google.maps.Geocoder();for(var i = 0;i < siteName.length;i++){
codeAddress(i);} }
function codeAddress(i){ var address=siteName[i];geocoder.geocode({ 'address': address}, function(results, status){ if(status == google.maps.GeocoderStatus.OK){ //alert(address + “:” +results[0].geometry.location);siteLocation.push(results[0].geometry.location);var marker = new google.maps.Marker({ map: map, position: results[0].geometry.location, title:address });//画线
var flightPath = new google.maps.Polyline({ path: siteLocation, strokeColor: “#FF0000”, strokeOpacity: 1.0, strokeWeight: 2, map:map });
} else { alert(“Geocode was not successful for the following reason: ” + status);} });} function Button1_onclick(){ var message ='this';new window.alert(message);
二、数据库
1、数据库只需要一张表
2、新建系统存储过程Proc_GetStationListByID,Proc_GetTrainDetailByNo,Proc_GetTrainListByFromTo,Proc_GetTrainListByNO,Proc_GetTrainListByStation用以存储数据。其实存储过程就和函数差不多 将常处理的业务写成一个存储过程,要用到是只要调用就可以了,具体可以参照函数理解,什么情况下用?一般在开发中,分工明确的都是数据库程序员写好存储过程,业务程序员要操作数据库时只需调用存储过程,传入相应参数,然后获取返回结果就可以了。
3、Proc_GetTrainListByFromTo的存储过程如下:
set ANSI_NULLS ON set QUOTED_IDENTIFIER ON go
ALTER PROCEDURE [dbo].[Proc_GetTrainListByFromTo]
AS BEGIN select t1.[ID] as 车次,t1.[Type] as 列车类型, t1.Station as 始发站,t1.D_Time as 发车时间, @StartStation varchar(50), @EndStation varchar(50)
t2.Station as 终点站,t2.A_Time as 到站时间, t2.[Day] as 天数,t2.Distance as 里程, t3.Station as 出发站,t3.A_Time as 出发站到站时间, t3.D_Time as 出发站发车时间,t3.[Day] as 出发站天数, t4.Station as 目的站,t4.A_Time as 目的站到站时间, t4.D_Time as 目的站发车时间,t4.[Day] as 目的站天数,--票价
dbo.Fun_GetPriceByFromTo(t1.[ID],t3.S_No,t4.S_No)as 票价 from(select * from train where [ID] in(select distinct t1.id from(select * from train where station like '%'+@StartStation+'%')t1 join(select * from train where station like '%'+@EndStation+'%')t2 on t1.id=t2.id and t1.s_no 三、Train程序编写 1、新建一个调用类Query,用来调用系统存储过程 public static DataTable GetTrainListByID(string id){ DataTable dt = new DataTable();//........SqlParameter[] parms = new SqlParameter[1];parms[0] = new SqlParameter(“@NO”, SqlDbType.VarChar, 50);parms[0].Value = id;DataSet ds = DbHelperSQL.RunProcedure(“Proc_GetTrainListByNO”, parms, “ds”);dt = ds.Tables[0];return dt;} 2、通常我们在程序中需要调用WebService时,都是通过“添加Web引用”,让VS.NET环境来为我们生成服务代理,然后调用对应的Web服务。这样是使工作简单了。 [WebMethod] public DataTable GetTrainListByID(string id){ return Query.GetTrainListByID(id);} [WebMethod] public DataTable GetTrainListByStation(string station){ return Query.GetTrainListByStation(station);} [WebMethod] public DataTable GetTrainListByFromTo(string from, string to){ return Query.GetTrainListByFromTo(from, to);} 两个基本点 1.择重避轻,有所取舍。 核心优先 通常来讲,系统是都是庞大的,不要太完美主义,先抓住重点,理解那些是我们的核心页面,那些页面对我们来说是最重要的,那些页面访问量最高,核心优先。 主要问题在那,抓住瓶颈点。 治病要医本。优化前,需要进行细致的分析,抓住主要瓶颈点,对症下药。优化那么多的方子,别全采用,通常几个就能达到效果 2.简单有效才是硬道理 越是简单的东西越容易控制,越不容易出错,尽量避免将系统设计的过于庞大,过于复杂,记住,这是在做产品,而不是在搞研发。很多看似很蠢的方法,往往越是有效。 新技术,新方法的引用是具备一定的风险的,要评估,要慎重。 Js处理 1.尽量放到页面尾部 Js的加载时阻塞页面的,没下载完毕后面的内容不会出来,所以尽量避免把JS放到页面头部,按照经验估计,整个页面中所用的JS逻辑,90%都是可以放到页面尾部。2.延迟加载(按需加载) 很多的业务逻辑并非每次都使用也不是要立即使用,首次加载过程中仅仅加载那些必须的,只有当必要的条件触发,才去加载请求必要的JS.比如说权限验证通过,加载管理模块。点击发表文章按钮,加载与发表文章有关的验证和处理函数。 如果写过C++的肯定会接触过动态库和静态库,这个与之类似,什么时候需要什么时候再加载,首次打开页面肯定会清净了许多,而且业务逻辑也由此分离开来,管理和维护也会方便很多,毕竟减少了那么多的耦合。 按照BBS项目经验估计,普通页面的所有业务逻辑中需要在首次请求中加载的不到50%,我们的JS又由此砍掉了一半。3.合并JS,减少请求 请求多个小文件的效率远小于请求一个大文件的效率,因为需要多次DNS解析,多次连接,浏览器和server端也需要进行多次开启进程、权限验证和预处理,以及 http请求在数据包传递上的一些问题。 所以尽量避免在页面中加载一堆的js 文件,需要先讲需要的小的JS合并成一个大的JS文件统一输出,页面因此被卡住的时间肯定会减少很多。 为了提高开发效率,合并建议不要每次都手动来进行,导致之后维护成本很大,相信些个XML配置文件,确定合并规则以及依赖关系后,用程序自动合并效率会高很多,后面有我附上的一个配置示例,仅作参考形式不重要 4.JS压缩 此手段属前端特有,毕竟流量意味着速度,意味着金钱。是在降低代码的可读性为前提。但事物的两面性告诉我们,可读性差也意味着安全,而且可读性可以通过保存压缩前的源文件来解决。 所谓的压缩,就是把场的变量名换成短的变量名,去掉没用的空格和换行符,从而节省我们JS程序的长度,不过目前这种处理已经很成熟,通过搜索可以搜出很多相关的工具。不再细说 经验值,能压缩50%以上,视程序与压缩工具而论。 5.尽量少用第三方库 在我的印象中,很多框架都是很庞大20K以上,虽然很强大很方便,但如果不是做企业级应用,不要用,因为我们也许只可能用到其中很少的一部分功能却加载了整个框架。 不过框架中的很多方法是可以提取出来滴,或者精简成一个轻量级的框架,比如说trimPath,完全可以精简到4k.6.合并ajax请求 Ajax请求的数据,如果涉及请求多种数据,尽量考虑到将其合并。 7.合理的使用缓存 缓存视乎是server端的事,但是js中也是经常用的。 一种是缓存在一个全局变量中,一些很复杂的计算和查找操作可以这样做。如果大家在使用模板类trimPath经常是需要对模板进行预处理,这种预处理的结果是可以被缓存的。这种缓存的缺点是页面刷新后数据就会失效。 另外一种是缓存在window.name或cookie里面,经常用来缓存一些AJAX调用的结果,避免反复请求server端,比如一些用户的权限验证信息,就没必要总是调用server端接口,缓存了也就减少了请求,提高了性能,但cookie大家要慎用,存于一些数据比较小的还行,每次http请求他是占用上行带宽的。 还有一种缓存的实现是借助于flash或其他的第三方组件,特点是可以缓存超大的数据,但是适应场景优先,需要特殊的平台支持,不过FLASH目前已经很通用了。 8.能静态化输出,尽量少用JS渲染输出 页面制作 1.素材合并 尽量把页面中的图片合并在一起,利用css sprite切割。这样减少了请求的次数。通常合并成3长大的图片,一张是有固定宽高的(比如说按钮),另外两张是分别横向或纵向平铺的1像素的小图,用来做背景用。2.CSS压缩处理 道理同JS压缩,也是有很多工具实用的可用。 3.图片背景切割与平铺 切图是很有讲究的,很多区域能切成用1像素平铺,尽量用1像素小图平铺,尽量用一个较大的图片设置成背静。4.少用iframe和frameset 首先一点frame会阻塞页面,第二,产生额外的请求,第三,如果涉及交互,增加开发维护成本,第四对搜索引擎优化不好 5.CSS尽量放到页面头部 浏览器只有等CSS下载完毕后,才会真正的显示页面,所以为了让页面尽快有所输出,把CSS放到头部,而且浏览器对CSS的处理时并行的,不会像JS那样会阻塞页面。 Server处理 1.启用gzip压缩,约能压缩70%~80% 2.js,css,图片添加过期头,让浏览器能缓存。能减少1/3以上的请求。3.静态页面、js、css等静态文件单独迁移 第一,可以针对静态文件做专门优化,比如说squid反向代理,nginx代替apache做静态server。 第二,便于管理和维护,以后迁移和拓展方便。 4.js、css、图片等静态文件与当前应用放到不同的域名下。 不再传递那些无必要的cookie,减少传输。 5.图片服务器分多域名。 浏览器对同一域名的只允许使用2个并发,如果页面图片过多,会由于并发排队从而阻塞页面。但域名也不能太多,会消耗DNS解析的时间,建议4个为佳。 附加 1.JS合并配置文件示例 IE Httpwatch Firefox firebug 本文地址 http://user.qzone.qq.com/165162897/blog/1248096280第五篇:前台javascript速度优化总结
2.常见分析与调试工具