Fast Retrieval of View Data Using the ViewNavigator Cache - V8.52

Beginning with the R8.52 release of Notes/Domino there is a clear performance winner in the race to enumerate data from a View using the Backend View related classes. Significant performance work has been done on the ViewNavigator class to allow it perform well enough to serve as the underpinnings for XPage screen display. You can gain the benefits of these enhancements for your application whether it is written in Java, LotusScript, or JavaScript.

The Backend ViewNavigator cache reduces the number of server transactions and associated network overhead when navigating and reading ColumnValues information from the Documents and Entries in a View. Performance gains are most profound when accessing a View residing on a server from a client, however retrieval from local Views will also be greatly improved.

The cache does not change any behaviors, i.e. ViewNavigator and ViewEntry methods will behave the same with or without an enabled cache. If what you need is not in the cache, it will be fetched in another transaction. Care should be used in configuring the cache so as not to incur additional costs of reading entries twice.

There are 4 prerequisites to use the ViewNavigator cache for rapid data access:

1. Notes/Domino Release 8.52 or greater
2. View.setAutoUpdate must be False
3. ViewNavigator cache must be enabled
4. ViewNavigator.getNext() (or getPrev) must be used

The AutoUpdate property of View is an instruction to the Backend classes on how to manage updates to a View collection. The AutoUpdate property of View is true by default. This means that the Backend will pay attention to "View collection has changed" signals from the core during method execution. In this case, the method must be restarted, which can be time consuming on a busy View and will negatively impact performance. In these cases, setting AutoUpdate = true is a very worthwhile optimization in its own right.

There are some conditions which must be met before you can set AutoUpdate = false. This is, in effect, saying to the backend "it is safe to ignore updates to my View because the collection order won't change". For example, since ViewNavigator is a sorted View, if it is sorted on date ascending, all new Documents will occur at the end of the collection. Therefore, the collection order is "safe" from those updates. Also, deletions during normal running hours can be marked and deferred to off hours, preserving collection order during high access periods. There is a much more detailed discussion of this here: http://www-10.lotus.com/ldd/ddwiki.nsf/dx/View.AutoUpdate

To utilize the cache, AutoUpdate must be set to false.

To enable the cache, call

ViewNavigator.setBufferMaxEntries( int numentries); (Java shown)

where numentries is an integer between 2 and 400. This is the number of entries tthat will be retrieved whenever the cache is populated. If you intend to read out all ViewEntries in the View, use the maximum of 400. However, if you are just interested in a screenload, as XPages might be, use something like 25. There is no point in buffering more entries than you need. The cache automatically refills itself as needed - tuning the cache for maximum performance is as much art as science, and will depend on the runtime characteristics of your application.

Other optimizations

Depending on exactly what your application needs to do, other optimizations can be made. These are available on the ViewNavigator under the EntryOptions property. This property currently accepts two constants:

VN_ENTRYOPT_NOCOUNTDATA - do not count children (this can be expensive on some Views)
VN_ENTRYOPT_NOCOLUMNVALUES - do not gather ColumnValues data

Example:

ViewNavigator.setEntryOptions(lotus.domino.ViewNavigator.VN_ENTRYOPT_NOCOUNTDATA);

This would tell core services not to bother counting children, which may be faster on Views populated with lots of child Documents. Note that even though the child count is not buffered in the cache, if the program later calls ViewEntry.getCount(), the children will be counted in another transaction, which may be counterproductive.

The same would be true for VN_ENTRYOPT_NOCOLUMNVALUES. Setting this option would cause the ColumnValues data to not be stored in the cache, so any calls to ViewEntry.getColumnValues() would cause another transaction to fetch ColumnValues data. Again, this may or may not be a counterproductive situation. One case where it could be beneficial might be if you are only interested in the ColumnValues of one or two entries in a collection. In that case, it may pay to ignore them for all cached entries.


Examples:
Here is a LotusScript example which uses the cache to pull ColumnValues out of all entries in a View in the fastest possible way: Running against a local Database on R8.52, this script runs many times faster with the cache set to 400 vs the cache set to 1 (cache disabled). Additional gains will be seen running on a remote Database on a busy server.

Dim view As NotesView
	Dim db As NotesDatabase
	Dim s As New NotesSession
	Dim nav As NotesViewNavigator 
	Dim ve As NotesViewEntry
	Set db = s.CurrentDatabase
	
	Set view = db.getView("$All")
	Set nav = view.createViewNav()	
	
	' do not do AutoUpdates
	view.AutoUpdate = False	
	
	' create a ViewNavigator
	Set nav = view.createViewNav()
	
	' enable cache for max buffering
	nav.BufferMaxEntries = 400	
  
	Msgbox  "View: " + view.Name + " 10000 entries, Cache: " + Cstr(nav.BufferMaxEntries)
	
	' if we are not interested in the number of children, we can go a little faster
	nav.EntryOptions = Vn_entryopt_nocountdata
	
'	System.out.println("Start: " + dt);
	tstr = "Start: " + Cstr(Now)
	
	Dim i As Integer
	i = 0
	Set ve = nav.GetFirst
	Dim vstr As String
	
	While (   i< 10000 )  
		vstr = ve.ColumnValues(0)
		Set ve=nav.getNext(ve)
		i = i + 1
	Wend
	
	Msgbox  tstr + "   Finish: " + Cstr(Now)


Below is the same test, written in Java, yielding the same before/after results:

import java.util.*;
import lotus.domino.*;
 
 
public class JavaAgent extends AgentBase {
 
 
	public void NotesMain() {
 
 
		try {
			Session session = getSession();
			AgentContext agentContext = session.getAgentContext();
 
 
			// (Your code goes here) 
			Database db = agentContext.getCurrentDatabase();
			View view = db.getView("$All");
			
			// ignore updates
			view.setAutoUpdate(false);
			
			// create a ViewNavigator
			ViewNavigator nav = view.createViewNav();
			
			// enable cache for max buffering
			nav.setBufferMaxEntries(400);
			System.out.println("view: " + view.getName() + " 10000 entries, Cache: " + nav.getBufferMaxEntries());
			
			// if we are not interested in the number of children, we can go a little faster
			nav.setEntryOptions(ViewNavigator.VN_ENTRYOPT_NOCOUNTDATA);
			Date sdate = new Date();
 
 
			String vstr;
			ViewEntry tmpve;
			ViewEntry ve = nav.getFirst();
					
			for (int i = 0; i < 10000; i++) {
				vstr = ve.getColumnValues().elementAt(0).toString();
//				System.out.println(i + ": " + vstr);
				tmpve = nav.getNext(ve);
				ve.recycle();  	
				ve = tmpve;				
				}
 
 
			Date edate = new Date();
			System.out.println( "Start: " + sdate + "    Finish: " +	edate);		
 
 
		} catch(Exception e) {
			e.printStackTrace();
		}
	}
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值