论文部分内容阅读
中大型网站开发设计中,网站性能绝对处于非常重要的位置。笔者有多年开发大中型网站及ASP.Net教学培训的经验,影响ASP.Net网站性能有许多方法,其中数据库性能优化尤为重要,下面就着重讲解如何从数据库方面提升ASP.Net网站性能。
1 数据操作
1.1 及时关闭数据库连接
对数据库连接的使用始终遵循的一条原则是:尽可能晚打开数据库连接,尽可能早关闭数据库连接。ASP.Net中提供了连接池(Connection Pool)改善打开和关闭数据库对性能的影响。连接池的大小是有限的,如果在连接池达到最大限度后仍要求创建连接,必然大大影响性能。因此,在建立數据库连接后只有在真正需要操作时才打开连接,使用完毕后马上关闭,从而尽量减少数据库连接打开的时间,避免出现超出连接限制的情况。代码实现:
Using(SqlConnection Conn=new SqlConnection
(connstr)){}
1.2 尽量使用存储过程
存储过程具有对数据库立即访问的功能,信息处理极为迅速。使用存储过程可以避免对命令的多次编译,在执行一次后其执行规划就驻留在高速缓存中,以后需要时只需直接调用缓存中的二进制代码即可。另外,存储过程在服务器端运行,独立于ASP.Net程序,便于修改,最重要的是它可以减少数据库操作语句在网络中的传输。
1.3 只读数据访问用DataReader,不要使用DataSet
DataReader对象是一个读取行的只读流的方式,绑定数据时比使用DataSet数据集方式性能更高。DataSet作为一个功能强大的、支持离线的数据集,其对性能的开销也相对较大。
DataReader优点:读取数据非常快。如果对返回的数据不需做大量处理的情况下,建议使用DataReader。缺点:直到数据读完才可调用它的Close()方法关闭,并且还应该关闭与之相关的Connection对象。
DataSet是把数据读出,缓存在内存中。优点:只需连接一次就可关闭数据库的连接。缺点:对内存的占用较高。如果对返回的数据需做大量的处理用DataSet比较好些,可以减少对数据库的连接操作。
1.4 返回多个结果集
无论DataReader还是DataSet,返回多个结果集,然后用rd.NextResult()或ds.Tables[i]来分别处理数据,减少重复连接数据库的次数。同时尽量用比较高效的SQL代替后续复杂的DataSet二次加工。
2 数据库字段的建立
2.1 尽量不要在查询语句中使用跨表查询
在数据库操作中,查询是比较频繁的操作,提升查询操作的一个基本的原则是尽量减少跨表查询,也就是Join、Union和子查询等。例如,A表中其中一个字段是B表的外键,查询时往往需要同时将A表中的数据全部查询出来,同时再把匹配A表外键的字段查询出来,这样就会大大增加查询的成本。这里以文章系统为例,一般表结构为:
Article(Id,Title,Content,ClassId,Hits,AddDate) Class(ClassId,ClassTitle)
这样的表结构肯定就需要使用两次查询或者连接查询等方法来取得两张表的数据。如果统计一个分类下的文章数量,还需要Select Count(*) From Article来进行全表扫描来完成,这样就会在性能上受到严重影响。
2.2 排序问题
例如AddDate字段,一般情况下以它排序的情况较多,这种DateTime类型字段在排序时会进行计算,它的排序比Int类型要慢得多,因此还可以考虑新增加一个DNum(int)字段来储存日期。比如AddDate为2012-03-20,那么插入到DNum可以是20120320这个数字,这样在排序时可以通过Order By DNum Desc来减少排序的时间。当然如果AddDate默认是Getdate(),并且排序只有一个按时间排序的话,可以Order By ID Desc来完成。
对于排序,数据库在查询出满足Where所有条件的数据后,然后再进行排序;如果没有必要,不要使用复杂的排序,可以根据实际情况考虑是否添加OrderNum来减少相关的排序。
2.3 尽量不用外键
实际的网站开发中,外键会导致调试程序的复杂,并且会在一定程度上降低SQL执行的效率,因为数据在插入前引擎会对数据的合法性进行校验,这样在一定程度上也会降低数据库的性能,另外对于外键数据在删除情况下查询主表数据可能会发生不可预料的异常。
3 索引的建立
在网站设计开发前要确定实际项目中哪些可能会频繁进行查询,以一个文章系统为例,可能会有时间、分类和关键字这几种查询比较频繁。那么必要时要建立索引,一般情况下需要对其各自建立索引,比如实际的表结构如下:
Article (Id,Title,Content,ClassId,ClassName,Hits,AddDate,CommentNum)
假设以分类和时间排序来进行查询十分频繁,那么需要各自建立ClassId和AddDate索引;如果这个查询属于复杂查询,如果SQL语句如下:
Select * From Article Where ClassId=1 Order By AddDate Desc,CommentNum desc
那么可以建立多个字段的复合索引,这里可以将ClassId、AddDate建立复合索引,如有必要可以将CommentNum也包括在内。
4 查询的优化
尽量使用优化过的SQL语句以减少执行时间,尽量只返回有用的数据、字段,充分利用索引等。查询优化最核心的内容就是减少Scan,尽量做到Seek;Scan代表全表扫描,Seek代表定位到某一行。使用Count、Not、!=、In、Like等都会引起全表扫描,如果这张表数据足够多,那么性能影响是非常大的。
以上表为例,ASP.Net程序最常使用的DAL功能是根据某一编号取数据然后存储到对象中,语句为:
Select * From Article Where Id=10
这样即使在查询到需要的数据后,它仍会执行剩余数据的查询进行全表扫描,这样就浪费了大量的资源和程序时间。可以使用Top 1来进行条件限制:Select Top 1 * From Article Where Id=10。假设有100万条数据,实际中Id=10,只有一条数据,那么就节约了查询999 999
条数据的时间。
除了上文提到的优化方法之外,还可以通过使用更好的算法来提高程序性能。尽管优化的方法各异,但目的只有一个:尽最大可能在满足程序要求的情况下提高性能。
参考文献
[1]余昭辉.构建高性能可扩展ASP.NET网站[M].北京:人民教育出版社,2011.
[2]朱印宏.ASP.NET 3.5 SQL Server网站模块化开发[M].北京:清华大学出版社,2009.
[3]房大伟,等.ASP.NET开发实战1200例:1-2卷[M].北京:清华大学出版社,2011.
(作者单位:广东省东莞市长安职业高级中学)
1 数据操作
1.1 及时关闭数据库连接
对数据库连接的使用始终遵循的一条原则是:尽可能晚打开数据库连接,尽可能早关闭数据库连接。ASP.Net中提供了连接池(Connection Pool)改善打开和关闭数据库对性能的影响。连接池的大小是有限的,如果在连接池达到最大限度后仍要求创建连接,必然大大影响性能。因此,在建立數据库连接后只有在真正需要操作时才打开连接,使用完毕后马上关闭,从而尽量减少数据库连接打开的时间,避免出现超出连接限制的情况。代码实现:
Using(SqlConnection Conn=new SqlConnection
(connstr)){}
1.2 尽量使用存储过程
存储过程具有对数据库立即访问的功能,信息处理极为迅速。使用存储过程可以避免对命令的多次编译,在执行一次后其执行规划就驻留在高速缓存中,以后需要时只需直接调用缓存中的二进制代码即可。另外,存储过程在服务器端运行,独立于ASP.Net程序,便于修改,最重要的是它可以减少数据库操作语句在网络中的传输。
1.3 只读数据访问用DataReader,不要使用DataSet
DataReader对象是一个读取行的只读流的方式,绑定数据时比使用DataSet数据集方式性能更高。DataSet作为一个功能强大的、支持离线的数据集,其对性能的开销也相对较大。
DataReader优点:读取数据非常快。如果对返回的数据不需做大量处理的情况下,建议使用DataReader。缺点:直到数据读完才可调用它的Close()方法关闭,并且还应该关闭与之相关的Connection对象。
DataSet是把数据读出,缓存在内存中。优点:只需连接一次就可关闭数据库的连接。缺点:对内存的占用较高。如果对返回的数据需做大量的处理用DataSet比较好些,可以减少对数据库的连接操作。
1.4 返回多个结果集
无论DataReader还是DataSet,返回多个结果集,然后用rd.NextResult()或ds.Tables[i]来分别处理数据,减少重复连接数据库的次数。同时尽量用比较高效的SQL代替后续复杂的DataSet二次加工。
2 数据库字段的建立
2.1 尽量不要在查询语句中使用跨表查询
在数据库操作中,查询是比较频繁的操作,提升查询操作的一个基本的原则是尽量减少跨表查询,也就是Join、Union和子查询等。例如,A表中其中一个字段是B表的外键,查询时往往需要同时将A表中的数据全部查询出来,同时再把匹配A表外键的字段查询出来,这样就会大大增加查询的成本。这里以文章系统为例,一般表结构为:
Article(Id,Title,Content,ClassId,Hits,AddDate) Class(ClassId,ClassTitle)
这样的表结构肯定就需要使用两次查询或者连接查询等方法来取得两张表的数据。如果统计一个分类下的文章数量,还需要Select Count(*) From Article来进行全表扫描来完成,这样就会在性能上受到严重影响。
2.2 排序问题
例如AddDate字段,一般情况下以它排序的情况较多,这种DateTime类型字段在排序时会进行计算,它的排序比Int类型要慢得多,因此还可以考虑新增加一个DNum(int)字段来储存日期。比如AddDate为2012-03-20,那么插入到DNum可以是20120320这个数字,这样在排序时可以通过Order By DNum Desc来减少排序的时间。当然如果AddDate默认是Getdate(),并且排序只有一个按时间排序的话,可以Order By ID Desc来完成。
对于排序,数据库在查询出满足Where所有条件的数据后,然后再进行排序;如果没有必要,不要使用复杂的排序,可以根据实际情况考虑是否添加OrderNum来减少相关的排序。
2.3 尽量不用外键
实际的网站开发中,外键会导致调试程序的复杂,并且会在一定程度上降低SQL执行的效率,因为数据在插入前引擎会对数据的合法性进行校验,这样在一定程度上也会降低数据库的性能,另外对于外键数据在删除情况下查询主表数据可能会发生不可预料的异常。
3 索引的建立
在网站设计开发前要确定实际项目中哪些可能会频繁进行查询,以一个文章系统为例,可能会有时间、分类和关键字这几种查询比较频繁。那么必要时要建立索引,一般情况下需要对其各自建立索引,比如实际的表结构如下:
Article (Id,Title,Content,ClassId,ClassName,Hits,AddDate,CommentNum)
假设以分类和时间排序来进行查询十分频繁,那么需要各自建立ClassId和AddDate索引;如果这个查询属于复杂查询,如果SQL语句如下:
Select * From Article Where ClassId=1 Order By AddDate Desc,CommentNum desc
那么可以建立多个字段的复合索引,这里可以将ClassId、AddDate建立复合索引,如有必要可以将CommentNum也包括在内。
4 查询的优化
尽量使用优化过的SQL语句以减少执行时间,尽量只返回有用的数据、字段,充分利用索引等。查询优化最核心的内容就是减少Scan,尽量做到Seek;Scan代表全表扫描,Seek代表定位到某一行。使用Count、Not、!=、In、Like等都会引起全表扫描,如果这张表数据足够多,那么性能影响是非常大的。
以上表为例,ASP.Net程序最常使用的DAL功能是根据某一编号取数据然后存储到对象中,语句为:
Select * From Article Where Id=10
这样即使在查询到需要的数据后,它仍会执行剩余数据的查询进行全表扫描,这样就浪费了大量的资源和程序时间。可以使用Top 1来进行条件限制:Select Top 1 * From Article Where Id=10。假设有100万条数据,实际中Id=10,只有一条数据,那么就节约了查询999 999
条数据的时间。
除了上文提到的优化方法之外,还可以通过使用更好的算法来提高程序性能。尽管优化的方法各异,但目的只有一个:尽最大可能在满足程序要求的情况下提高性能。
参考文献
[1]余昭辉.构建高性能可扩展ASP.NET网站[M].北京:人民教育出版社,2011.
[2]朱印宏.ASP.NET 3.5 SQL Server网站模块化开发[M].北京:清华大学出版社,2009.
[3]房大伟,等.ASP.NET开发实战1200例:1-2卷[M].北京:清华大学出版社,2011.
(作者单位:广东省东莞市长安职业高级中学)