欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

ASP 3.0高级编程(四十三)

程序员文章站 2024-01-28 17:27:52
9.3.5 数据高速缓存        首先需要注意的是,数据高速缓存与记录集高速缓存虽然都用于改善性能,但两者是无关的。数据高...
9.3.5 数据高速缓存
       首先需要注意的是,数据高速缓存与记录集高速缓存虽然都用于改善性能,但两者是无关的。数据高速缓存是临时的数据存储区,允许使用高速缓存中的数据,而不是重新生成新的数据。这只适用于那些不经常改动但多次被访问的数据。
       在asp中一个最简单的缓存数据的方法是使用application和session范围的变量。例如,假设有一些需要选择书类型的网页。正常情况下,可能会创建一个含有以下函数的包含文件。
<%
function booktypes()

  dim rsbooktypes
  dim strquote

  strquote = chr(34)

  set rsbooktypes = server.createobject ("adodb.recordset")

   get the book types
  rsbooktypes.open "usp_booktypes", strconn

  response.write "<select name=" & strquote & lstbooktype & strquote & ">"
  while not rsbooktypes.eof
    response.write & "<option>" & rsbooktypes("type") & "</option>"
    rsbooktypes.movenext
  wend
  response.write & "</select>"

  rsbooktypes.close
  set rsbooktypes = nothing

end function
%>
这仅仅是调用一个存储过程,从而得到书的类型,同时创建一个select列表。上述代码的缺点在于每次调用该函数都必须访问。因此,重新修改这个函数。
<%
function booktypes()

  dim rsbooktypes
  dim strquote
  dim strlist

   see if the list is in the cache
  strlist = application("booktypes")
  if strlist = "" then
     not cached, so build up list and cache it
    strquote = chr(34)

    set rsbooktypes = server.createobject ("adodb.recordset")

     get the book types
    rsbooktypes.open "usp_booktypes", strconn

    strlist = "<select name=" & strquote & lstbooktype & strquote & ">"
    while not rsbooktypes.eof
      strlist = strlist & "<option>" & rsbooktypes("type") & "</option>"
      rsbooktypes.movenext
    wend
    strlist = strlist & "</select>"

    rsbooktypes.close
    set rsbooktypes = nothing

     check the list
    application("booktypes") = strlist
  end if

  booktypes = strlist

end function
%>
这段代码不只是打开记录集,它检查application变量booktype的值是否为空。如果不为空,则使用该变量的内容。如果为空,则像以前一样打开记录集。显然,一旦第一个人运行了这一例程,便缓存了数据,因此这只对那些不常变化的数据是有用的。
如果想在用户基础上缓存数据,可以使用session范围的变量,但这里必须注意session存在有效期。过期后会话层变量将和会话一起取消,代码便有可能终止运行。
利用web application stress(was)工具,得到了表9-4的分析结果:
表9-4  利用was工具得到的分析结果
方 法
页面点击次数

没有高速缓存
190

有高速缓存
11000

很明显性能有所改善。但不要采用上述方法缓存一切内容。毕竟,这种方法只适用于那些已经格式化后用于显示的数据。除此之外,还要考虑到如果web服务器只为特定的一个人服务,那几乎不是一个典型的web服务器的用法。使用was可以在一个服务器上模拟多个用户,这样可以更实际地测试应用程序。
通过模拟一定数量的用户,web application stress工具可以对web页面进行承受力测试。该工具有一个简单的图形界面,使用起来非常容易。可以从https://homer.rte.microsoft.com/获得更多的信息,也可以下载该工具。
高速缓存对象
若要缓存未格式化过的数据该怎么办?可以在不同地方以不同的方式使用吗?当然,也可以用application或session变量这样做。考虑一下书标题的情况。你或许希望在多个页面中使用这个标题,也许在一个表格中显示所有的标题,或在一个列表框中显示供用户选择等等。你可能会想到可以缓存记录集本身而无需缓存含有标签的html文本。
可以在application或session变量中缓存对象,但有两个主要的问题需要注意:
· 存放在application变量中的对象必须支持*线程,因此必须是*线程对象或双线程对象。这意味着无法在application变量中缓存由vb创建的。
· 在session状态中存放单元线程对象意味着创建该对象的线程是唯一允许访问它的线程。因此iis无法较好地完成线程管理,因为任何试图访问这个对象的页面都必须等待原有线程服务于该页面。这将扼杀扩展应用程序的任何机会。
对于线程问题的讨论参见第15章。
默认情况下,ado作为单元线程对象装载,这主要是因为部分ole db提供者并非是线程安全的。在ado安装目录中有一个注册表文件,可将ado转换成双线程模型,由此使ado对象可以安全地存放在application和session对象中。
你也许会认为所有的问题都解决了,可以通过使用各种类型的对象获得显著的速度提升,但这并不一定。许多人已经认识到既然连接到数据库是一个相对昂贵的操作,那么缓存connection对象可在再次连接时节省大量的时间。的确如此,但缓存connection对象意味着该连接永远不会关闭,因此连接缓存池的工作效率比较低。连接缓存池隐含的一个思想实际上是减少服务器上使用的资源,而缓存asp状态中的对象显然不能减少资源的使用。事实上还增加了对它们的占用,因为每缓存一个对象便要占用服务器的资源,对于一个繁忙的站点而言,这将极大地降低web服务器的效率。
所以不应存储connection对象,但对于recordset对象,特别是断开连接的记录集呢?假定ado已从单元线程变成了双线程,就没有什么理由不这么做了,只要确切知道自己在做什么。不要认为这会自动地改善asp页的性能。每一个缓存的记录集都在内存和asp管理方面占用服务器的资源,因此不要缓存大的记录集。
另一个技巧是使用记录集的getrows方法,将记录集转换成一个数组。因为数组并不像recordset对象那样受线程问题的影响,因此非常适合用于会话层的变量。然而它同样也占用服务器资源,还必须考虑处理数组的时间。
构建自己的应用程序,缓存技巧并非是必要的。

9.4 数据整形
数据整形或分层的记录集能显示一个树状结构或相关记录集。这通过在记录集的字段中包含一个记录集来实现,可以展现数据库的关系,而且多个记录集能在一次调用中返回。有两个理由可以解释它为什么是有用的:
· 性能:当正确使用时,数据整形可以改善性能。
· 便利:在数据整形中非常容易映射父子关系。
要知道数据整形涉及到哪些内容,最简单的方法是看图9-8所示的内容:

图9-8  数据整形涉及的内容
图9-8显示了pubs数据库中表publishers、titles及sales的层次关系。
值得注意的一点是每个子记录集都不是独立的记录集。因此,图9-8中只有三个记录集,而不是六个。这是怎么来的呢?在层次关系中每一层都有一个记录集,分别是publishers、title和sales。在publishers表中引用标题时,实际上是引用了titles记录集,但ado过滤了titles,所以只显示那些与被选择的出版社对应的记录。这就容易使人误以为每个子元素有一个独立的记录集。

9.4.1 使用数据整形
应用数据整形必须:
· 使用msdatashape oledb提供者。
· 使用一种特殊的整形语言,它是sql的一种扩充,允许构造层次。
尽管使用新的提供者,连接字符串的实际改变不会太大。这是因为仍然需要从某处获取数据。因此,可以这么做:
provider=msdatashape; data provider=sqloledb; data source=...
这里用msdatashape作为提供者,而正常的provider变为data provider,而连接字符串的剩余部分保持不变。
为数据整形创建连接字符串的简便方法是从创建正规的连接字符串开始,然后附加到数据整形块的最后。例如,考虑以下正规的连接字符串。
strconn = "provider=sqloledb; data source=kanga; " & _
              " initial catalog=pubs; user id=sa; password="
可以像下面这样为数据整形提供者创建连接字符串。
strconn = "provider=msdatashape; data " & strconn
这将提供者设置为msdatasha