這份白皮書闡述對 IBM Lotus Notes 和 Domino 應用程序的性能形成巨大影響的最重要因素。它的主要目的是幫助 Notes 客戶端應用程序開發人員識別問題,而後針對問題提供解決方案,從而實現最佳的性能。
在這裏,假設您已經知道如何建立 Notes 設計元素,以及知道如何對錶單、字段、視圖和列等組件設置選項。這份白皮書爲各個級別的開發人員提供了學習材料。
在 Lotus Notes 中開發簡單的應用程序很是容易,而且在用戶和文檔的數量不多時,通常不會遇到性能問題。然而,只要應用程序是成功的,用戶和數據的數量就會逐漸增多。若是在設計時沒有考慮到性能問題,那麼您的應用程序此時將會變得異常緩慢。
這份白皮書討論影響 Notes/Domino® 應用程序的性能的主要因素,而且解釋開發人員如何才能得到最佳的性能。這並非一份詳盡的指南;相反,咱們主要關注最多見、最嚴重的設計問題。
這份白皮書的主要目的是幫助您識別 Notes 客戶端應用程序的問題,並指導您找到解決辦法。Web 應用程序也存在相似的設計問題,但它們的問題主要在另外兩篇文章中解答,即 Appendices Group C of the IBM Redbooks 出版物 Performance Considerations
for Domino Applications 和 IBM Business Partner 文檔 Performance Engineering Notes/
Domino Applications。
通常而言,如下因素對應用程序的性能影響最大:
- 視圖的數量及其複雜性。刪除不使用的視圖或合併類似的視圖。對於包含相同文檔但使用不一樣排序的視圖,使用一個可從新排序的列合併它們。刪除不須要的列,並簡化選擇和視圖列公式。檢查是否存在您不能訪問的「服務器私有」視圖或其餘視圖。
- 在視圖選擇公式或列選擇公式中使用 _cnnew1@Today 和 @Now。儘可能避免這種狀況。參見 IBM Support Web 站點技術文檔 Time/Date views in Notes: What are the
options?;並閱讀本文下面的視圖小節。
- 文檔數量。文檔越多打開的速度就越慢。能夠考慮壓縮舊文檔或將主文檔合併爲單一文檔。例如,若是您的主文檔是一個「訂單」,那麼將訂單上的每一個「排列項」放到獨立的文檔中就是一個糟糕的作法。Lotus Notes 不是關係數據庫,而是面向文檔的數據庫。
- 儲存在文檔中的摘要字段的數量。不屬於富文本的字段稱爲「摘要」字段(儘管這個稱呼過於簡單化)。文檔包含的摘要字段越多,將其編入到視圖索引中所需的時間就越長(若是存在幾百個字段,那麼所需的時間將增長 30%)。只要字段存在,即便不在視圖中使用它們,也會形成同樣的結果。有時使用更少的文檔卻須要更多的字段,反之亦然;必須仔細考慮才能爲提高性能作出正確的選擇。
- 表單的複雜性。嘗試將表單的數量限制爲與實際須要的字段相等。表單越長,打開、刷新和保存它們所需的時間就會大大延長(而且視圖索引器須要處理的字段也會增多)。
- 修改文檔。對文檔進行沒必要要的修改會增長索引器的負擔,從而下降了視圖索引的速度,而且還會影響複製和全文本索引的速度。
- 刪除文檔的數量。當刪除一個文檔時,就會留下一個稱爲「刪除存根」的標記。複製程序須要根據這個標記決定是否從其餘副本中刪除相同的文檔,或將「缺失」的文檔複製到該副本。刪除存根最終會過時(默認爲 90 至 120 天),所以只要數據庫保持正常的刪除文檔數量,就不會形成問題。
然而,咱們見過一些應用程序包含的刪除存根要比文檔多好幾倍。若是使用代理程序在夜間執行文檔刪除,而後從其餘外部數據源建立新的文檔,那麼一般會出現這種狀況。不要使用這種方法。您可使用更高級的算法比較文檔和源數據,從而肯定應該更新或刪除哪些文檔。參見 Lotus Sandbox download 瞭解更多信息。
- Reader 字段。若是有必要使用 Reader 字段,那麼必須使用它 —— 沒有其餘方法可以提供它所提供的安全性。但要注意它對視圖的性能形成的影響,尤爲是用戶僅訪問大量文檔中的一小部分文檔時。這份白皮書的視圖小節講述了一些減少該字段的影響的技巧,另外 developerWorks 文章 Lotus Notes/Domino 7 application performance: Part 2: Optimizing database views 也討論了相似的主題。
- 用戶數量。若是服務器上存在大量用戶,那麼將會影響應用程序和服務器的性能。當應用程序的性能已經處於臨界狀態時,添加新的用戶會致使性能惡化。改良設計會有所幫助,但您還須要在其餘服務器上建立副本(尤爲是集羣服務器),或鼓勵用戶建立更 快的本地副本。
參考 Domino Designer 幫助文檔「Properties that improve database performance」的數據庫選項列表,您能夠利用它調試性能。在不少狀況下,這些選項經過削弱性能來得到其餘功能;所以,對於特定應用程序不須要的功能,能夠禁用它。
對性能有巨大影響的選項包括:
- Don't maintain unread marks。
- Don't maintain the "Accessed (In this file)" document property。若是「不進行維護」,您就不知道最後一次讀取文檔的時間。對長時間不讀取的文檔進行歸檔時,這個信息很是有幫助。
- Disable specialized response hierarchy information。若是禁用該項選,就不能使用 NotesDocument.Responses 屬性,也不能使用 @AllDescendants 或 @AllResponses,它們偶爾用於視圖選擇公式和複製公式。
- Disable transaction logging。這個選項對性能的影響取決於管理員如何在服務器上設置它,以及用戶的數量。若是用戶不少,使用事務日誌能獲得更佳的性能。嘗試啓用和禁用該選項形成的影響。事務日誌用於恢復。
- Optimize Document Table Map。若是應用程序包含的各類類型的文檔大體相等,而且大多數視圖僅顯示一個類型(例如,SELECT Form = 「xyz」 & ...),這個選項就很是有用。若是視圖選擇公式都採用這種方式,而且先對錶單進行檢查,那麼視圖索引就會變快,由於這能當即排除不使用該表單的文檔。
使用 NSFDB2(在 DB2® 數據庫中存儲 Domino 數據)並不能提高性能,事實上,使用傳統的 NSF 文件還會更快一些。NSFDB2 的目標是添加功能,而不是提高性能。
全文本索引可能會佔據大量的磁盤空間,但這一般是物有所值的。您能夠利用全文本索引在代理中執行更快速的搜索,若是沒有這個索引,用戶必須使用更慢的搜索方法,這將致使長時間佔用服務器,從而形成性能降低。
注意:在 8.0 版本的 Notes 中,一個新數據庫屬性使您能夠關閉非全文本索引數據庫的「全文本」搜索。通常而言,即便您擁有全文本索引,該選項也是頗有用的;它確保索引被意外刪除以後,用戶會看到一條消息,而不只是以爲性能平白無故忽然降低。
對於數據庫,除了屬性對話框以外,您還能夠設置的另外一個地方是 ACL 對話框。限制用戶建立視圖和文件夾可以減小服務器的負載(見圖 1)。
若是您取消選擇「Create personal folders/views」,用戶仍然可以建立私有視圖,但建立的視圖必須儲存在本地的桌面文件中,而不是存儲在服務器上。所以不會對應用程序的性能形成太大的影響。
桌面私有視圖確定會對性能形成影響,由於索引它們時用戶必須從服務器實時提取數據。所以過多地使用桌面私有視圖還會使服務器陷入困境。因此要避免爲啓用「Private on first use」選項的用戶自動建立我的視圖。(下面會對此進行詳細闡述)。
大部分 @ 函數都是至關快的,但有一小部分比較慢。所以要謹慎地使用它們:
- @Contains 的開銷還不是十分大,一般用於測試列表是否包含某個值,這是一種低效的方法。例如,若是 Cities 包含值「East Lansing」,則表達式 @Contains(Cities; 「Lansing」) 返回 True。若是這正是您須要的,固然很好;但若是您查找的是包含「Lansing」值的條目,那麼應該使用 =、*= 或 @IsMember。這些函數更加快,由於若是第一個字符不匹配,它們就再也不掃描整個字符串。
- @For 和 @While 一般能夠被更高效的 @Transform 代替,或被其餘對整個列表進行一次性操做的函數代替。
- @Unique 必須將列表中的每一個值與其餘值進行比較,所以執行時間與列表中的項數的平方成正比。對於其中的各個值都具備唯一性的列表,這個函數的表現會更好。後面還將對此進行討論。
- @NameLookup 相似於 @DbLookup,但它僅用於目錄信息。
- @DbLookup 和 @DbColumn。過分使用和錯誤使用這些函數是形成表單延遲的主要緣由。下面將對此進行詳細討論。
咱們一般沒必要要地使用了宏語言中的循環函數。
儘管沒有在這個
Domino
Designer 幫助文檔中闡述宏函數,但幾乎全部接受字符串參數的宏函數均可以對列表進行操做。例如,@Left(x; 「,」),其中
x 是一個列表,它返回一個全部元素都被「左置」的列表。
注意:在之前,
@UserRoles 和
@UserNamesList 函數都會形成嚴重的性能問題,但從 Lotus Notes 6.0 開始,這些函數的結果都將被緩存。
影響 @DbLookup 和 @DbColumn 的性能的 3 個主要因素是:
使用緩存
許多開發人員過分地使用「NoCache」選項,尤爲是在關鍵字公式中。這種現象很容易觀察到,由於在開發和首次測試期間須要常常編輯關鍵字,所以NoCache(不使用緩存)是「正確的選擇」。
而後,在應用程序投入使用以後,就不會常常編輯關鍵詞。在出現新值時,遲一些再提供給用戶能夠獲得更好的性能,這種代價是能夠接受的。務必在必要時才使用「NoCache」選項。
有 3 個緩存選項:
- 「Cache」(默認)僅對在應用程序會話期間對視圖的首次查詢起做用,它會記住該查找結果供之後使用,直到您退出應用程序。
- 「NoCache」繞過緩存直接指向視圖。若是存在同一查找的緩存值,將不更新緩存。
- 「ReCache」是一個容易忽略的選項,它一般直接指向視圖,但它也使用查找值更新緩存。經過使用 ReCache,您能夠在特定時間更新緩存,好比在保存查找所引用的文檔時。在其餘時候也可使用緩存值,由於您知道對於用戶輸入的信息而言,這個值至少是最新的。
爲查找選擇正確的視圖
有時對 @Db 函數最高效的視圖並非最好的。例如,@U nique(@DbColumn(「」:「NoCache」; 「」:「」; 「InvoicesByCompany」; 1)) 存在幾個問題:
- 它在這裏不該該使用 NoCache。您並非天天都添加一個公司,即便添加,也能夠在 Invoice 表單的 Postsave 中使用「ReCache」選項,讓新添加的名字當即可用。
- 當前的數據庫是用表達式 「」:「」 指定的。相反,應該使用 「」,由於 「」:「」 不只帶有更多容易混淆的標點,並且它的計算速度也要慢一些。
- 不要查找帶有重複值的列表,而後再使用 @Unique 刪除重複內容。相反,您應該查找其值具備唯一性的視圖列,由於它們來自一個已分類的列。
最後一點特別重要,由於使用 100 個測試數據文檔時可以很好工做的列查找,在實際使用中性能就會急劇降低,所以此時應用程序面對的是數千個文檔。尤爲是在服務器上使用該應用程序時,須要經過網絡將視圖列的完整內容發送給用戶工做站,這是須要時間的。從視圖讀取已經存在的唯一值要快得多。
注意:在獲取唯一值列表時,彷佛可使用「Generate unique keys in index」選項代替已分類的列,但實際上它存在一些缺點,所以不適合該用途。
查找須要花很長時間索引的視圖也是不明智的,尤爲是在選擇公式或列公式中使用@Today 或 @Now 的視圖。若是您僅需查找特定日期的文檔,那麼能夠對僅包含這些文檔的視圖使用 @DbColumn,對包含全部按日期排序的文檔的視圖使用 @DbLookup,並提供日期做爲查找鍵。
避免重複查找
沒必要要地使用 @Db 函數的方式有好幾種。這裏給出一些常見的方式:
在公式中重複
@If(@IsError(@DbLookup(「」: 「NoCache」; 「」; 「SomeView」; CustID; 3); 「」
@DbLooku p(「」: 「NoCache」; 「」; 「SomeView」; CustI D; 3))
|
這個公式不只使用了不須要的 NoCache,而且進行了兩次查找(實際上一次查找就能夠了)。下面是兩個修改後的公式:
_tmp := @DbLookup(「」; 「」; 「SomeView」; CustID; 3); @If(@IsError(_tmp); 「」; _tmp)
|
或
@DbLookup(「」; 「」; 「SomeView」; CustID; 3; [FailSilent])
|
在讀模式中使用沒必要要的關鍵字查找
當打開文檔進行查看時,對於某些類型的關鍵字字段,Notes 客戶端不須要知道選擇列表。但複選框和單選按鈕字段除外,在其中甚至以讀模式顯示全部選項,而且全部使用關鍵字的內容都是同義詞(「Display text|value」),由於文檔僅儲存「value」,而表單必須顯示「Display text」。
可是在其餘狀況中,須要編寫該關鍵字公式來延遲查找,直到您實際須要選擇列表爲止:
_t := @If(@IsDocBeingEdited; @DbColumn(""; ""; "Customers"; 1); @Return(@Unavailable));
@If(@IsError(_t); ""; _t)
|
經過在文檔的讀模式下返回 @Unavailable,公式會再次通知表單,讓它詢問隨後是否須要選擇列表。這將在用戶切換到編輯模式而且指針點擊該字段時發生。
所以,在用戶僅查看文檔時,您不只要避免進行查找,而且要分散編輯文檔時的延遲;8 個半秒延遲確定沒有一個 4 秒延遲那麼煩人。若是用戶的指針沒有指向該字段,那麼他們根本不須要進行查找。
在只需一個查找的位置使用多個查找
假設您將一個客戶 ID 儲存在「invoice」文檔中,並想經過這個 ID 查找和顯示客戶的名稱、地址和購買聯繫人姓名。這樣,表單上就有幾個 Computed for Display 字段,每一個字段包含一個使用 @DbLookup(「」; 「」; 「CompanyByID」; CustID;
x) 的公式,其中
x 是列號或字段名。
使用一個列來包含您須要的全部值會更高效,您能夠從中找出每一個字段值。所以這個列公式應該爲:
CustName : StreetAddress : (City + 「 」 + State + 「 」 + Zip) : PurchasingContact
|
在您的表單上,添加一個隱藏的 Computed for Display 字段,名爲 CustDetails,以下所示:
@DbLookup(「」; 「」; 「CompanyByID」; CustID; 4)
|
(假設合併的列爲列 4)。而後,您就能夠在須要顯示名稱的地方使用公式:
在刷新時重複查找
假設您在組建表單時須要在計算字段中查找客戶的經理的名字,以下所示:
@DbLookup(「」; 「VOLE 1」: 「EmpData. nsf」; 「EmpByName」; @Name([CN]; @Username); 「Manager」)
|
每次刷新表單時,都從新計算已計算的字段。許多表單須要常常刷新(由於您啓用根據關鍵字字段的變化刷新字段的選項),所以這會嚴重影響速度。將字段設置爲「Computed when Composed」會更好。
若是不須要將字段儲存在文檔中(記住,不要儲存不須要存儲的字段!),而後對它使用Computed for Display,但這個例子中,須要按照如下步驟避免在刷新時重複查找:
@If(@IsDocBeingLoaded;
@DbLookup(「」; 「VOLE 1」: 「EmpData. nsf」; 「EmpByName」; @Name([CN]; @Username); 「Manager」);
@ThisValue)
|
使用 @DbColumn 分配序列號
這是一個常常犯的錯誤。當設計人員必須爲每一個文檔建立一個唯一的 ID 時,他們一般向最新的現有文檔的編號加「1」。所以他們的公式以下所示:
tmp := @DbColumn(「」:「NoCache」; 「」; 「RequestsByNumber」; 1);
nextNumber := @If(tmp = 「」;
1;
@ToNumber(@Subset(tmp; -1)) + 1);
@Right(「000000」 + @Text(nextNumber); 7)
|
這是一個很是糟糕的主意。隨着文檔數量的增加,@DbColumn 的執行時間會愈來愈長。此外,當應用程序有多個用戶時,它不能保證 ID 是唯一的,尤爲是存在多個副本時。
若是在文檔保存以後再給它分配序列號,那麼序列號在此以前是不可用的,這很不方便。不過,若是在建立文檔時就給它分配序列號,這將留有充足的時間讓其餘人使用相同的序列號建立並保存文檔。
您可能須要從新考慮本身的需求。有時應用程序實際上僅須要唯一的非數字
標識符,而咱們卻老是要求使用序列號。仔細查看 @Unique 函數,它生成一個很短但基本上是唯一的值(經過一些額外的工做就能夠保證唯一性,例如爲每位用戶添加一個唯一的「前綴」,一般是他們的名稱的首字母)。
在這個小節中,咱們將解決一下值得關注的問題。
由於存儲字段通常都會使應用程序變慢,因此若是可以在須要時輕鬆地計算這些值,就應該避免存儲值。這裏有一個折中;當文檔以讀模式打開時,不會計算 Computed 字段,所以若是它是一個很慢的公式,則最好儲存值,這樣可以改善讀模式的性能(另外一方面,這還意味着它會過時)。
但必定不要使用 Computed 字段從新顯示另外一個字段的值 —— 這樣會存儲相同信息的兩個副本。
在一個表單中使用大量字段的最多見緣由是,一個表有多個行和列的信息,而且每一個單元格有一個字段,超出了支持的行數。這是一種棘手的狀況,由於到目前爲止使用表單是最簡單的辦法。
不過,還有其餘辦法能夠管理表的值。最多見的辦法是將表放到一個富文本字段中,而後讓用戶根據須要進行填充(在富文本字段的默認公式中使用 @GetProfileField 從配置文件文檔讀取一個「starter」表)。這樣作的缺點是用戶在填寫表格時不能得到幫助,要是存在私有字段的話,就能夠提供關鍵字列表、轉換和驗證。不過,有時這也是一種可接受的辦法。
如今已經發布一些工具和技術,能夠在對話框中每次僅編輯表的一行,而後在表中顯示結果。例如,Lotus Sandbox 中的 Domino Design Library Examples 包含一組設計元素,可用於在表中編輯和顯示數據,而不要求每一個單元格必須有一個字段。在名爲「Table Editor」的數據庫文檔中,將詳細描述這個系統。須要付諸必定的努力才能實現它,但它對性能很是有幫助。
有時,咱們在大部分文檔中能夠看到包含許多空字段的表單。例如,大約 5% 的文檔須要一個包含 50 個字段的「Regulatory Approval」部分。而其他 95% 的文檔則存儲了這些空字段,這不只浪費空間,並且還形成糟糕的性能
對於這種狀況,使用兩個不一樣的表單可能更好 —— 一個包含必需字段的主表單,和一個分開的「Regulatory Approval」表單,它多是對原始文檔的響應,或者僅在須要時建立。在這裏,能夠經過使用額外的文檔來避免使用更多的字段。
不要忘記多值字段。除了經過 5 個字段讓用戶輸入 5 個不一樣的值以外,還可使用一個能夠輸入多個值的字段。對條目的數量沒有任何限制(除非您選擇必須使用一個),而且生成的值在視圖和公式中
更容易 使用。
注意:若是應用程序已經由於字段過多而變慢,僅編輯設計元素是於事無補的;您必須編寫代理程序遍歷現有文檔,並從中刪除多餘的條目。已經出現一些業務合做產品能夠簡化這個過程。不過,若是您的更改是一個重大的重組,好比將一些字段移動到特定的響應文檔中,那麼代理程序的編寫是至關複雜的。設計時從長遠考慮,爭取第一次就把事情作好,這能節省不少時間。
有些表單無節制地使用圖像,對背景使用大型位圖以及使用許多其餘圖像修飾。大圖像須要更長的加載時間、佔用設計元素的緩存,而且查看錶單時須要更長的圖像呈現時間。建立表單時稍加註意就能夠獲得比較專業的外觀,而且不會對性能形成太大的影響。下面是一些技巧:
- 不要將圖像複製粘貼到表單上;相反,要麼使用圖像資源設計元素,要麼導入圖像。若是您計劃在多個表單中使用同一個圖像,那麼可使用圖像資源,由於它容許客戶端將圖像與表單設計分離,而後再緩存它。即便您不打算 在多個表單中使用同一個圖像,將圖像做爲資源也是一個不錯的主意,由於之後其餘人可能須要使用該圖像建立另外一個表單。
- 將圖像放到表單上以後,不要隨意縮小它的尺寸。使用圖像編輯器(好比,GIMP)將原始圖像縮小爲您所需的尺寸 —— 即便您須要的是同一圖像的多個大小不一樣的圖像資源,也必須這麼作。
若是圖像的格式爲 JPEG,那麼能夠嘗試不一樣的壓縮設置,看看能不能減少它的體積。JPEG 壓縮是「有損耗」的,所以壓縮後圖像可能會失真,但若是您在不影響視覺效果的狀況下最大限度地壓縮圖像,能夠加快表單的加載速度。您能夠購買圖像工具,它們能幫助您找到一個平衡點。
- 對圖像使用正確的文件格式。若是圖像使用有限的調色板(就像大部分徽標),GIF 格式的圖像文件多是最小的。若是使用全色照片或繪畫,JPEG 多是更好的選擇。不要使用 BMP 格式的文件,由於它們的壓縮比很小。
- 呈現表單元格和圖像單元格的背景須要必定的時間。隱藏單元格邊框的表單比顯示邊框的表單的呈現速度快,尤爲是使用 3-D 效果的邊框。與嵌套在其餘表內部的表相比,使用合併單元格的表的呈現速度更快。
不要使用存儲表單。
通常不要使用表單選項「Automatically refresh fields」。這個選項會在編輯表單時頻繁刷新它,從新計算已計算字段和輸入轉換公式,從而形成延遲。使用字段級別的選項「Refresh on keyword change」或字段事件 Onchange 或 Onblur 會更好,它們只在須要時進行刷新。
表單能夠從其餘設計元素獲取信息,好比圖像資源、共享字段、共享操做、子表單、摘要、樣式表和腳本庫。打開一個文檔可能會從除表單以外的許多其餘設計元素讀取信息,讀取過程是須要時間的。共享設計元素的優勢是使應用程序的維護更加容易,而它的不足之處是訪問多個元素須要更長的加載時間。
Lotus Notes 緩存設計信息,所以不須要每次都從原始設計元素讀取設計信息;然而,首次加載多是個問題。緩存意味着使用共享設計元素能夠提高性能,若是須要在許多不一樣的表單中使用相同的子表單或圖像的話。
共享操做不會損害性能,由於僅有一個設計元素包含共享操做,因此多添加幾個共享操做與使用一個共享操做所需的開銷是同樣的。共享視圖列也不會影響性能。
因爲共享設計元素有利於維護,因此除非採起各類措施仍然不能獲得能夠接受的性能,不然不推薦取消設計元素共享。
因爲如下緣由,低效和沒必要要的視圖會形成延遲:
- 打開視圖時須要時間更新索引。
- 當在 @Db 函數中使用視圖時,須要時間獲取信息。
- 服務器上的更新任務會按期檢查每一個視圖,看看是否須要使用最近修改的文檔更新它們。所以視圖越多(或越複雜),就越長時間地佔用服務器,致使全部應用程序變慢。
視圖打開緩慢的另外一個常見緣由是數據庫中存在大量文檔。當您打開視圖時,Lotus Notes 將檢查在最後一次視圖索引更新以後是否修改了某些文檔。您擁有的文檔越多,檢查所需的時間就越長,即便最終結果是「沒有最近修改的文檔」。
已經有許多文章介紹在不使用 @Today 或 @Now 時如何提供基於日期/時間的視圖。其中的一個例子就是 IBM Support Web 站點技術文檔 Time/Date views in Notes: What are the options?,它提供一些建立基於日期/時間的視圖的方法。
如今咱們對其餘幾個方面進行討論。首先,常常建議使用的@TextToTime(「Today」) 是不完整的。如今它僅適用於第一天。您必須修改它,讓它可以正確地工做。
爲何?通常狀況下,當您打開一個視圖時,Lotus Notes 就會查看「視圖索引」 —— 視圖中存儲的文檔和行值的列表 —— 並僅檢查自索引最後一次更新以後建立或修改的文檔,以決定是否將它們添加到視圖,或刪除它們,或從新計算它們的列值。若是自從最後一次使用視圖以後沒有修改任何文檔,這個過程就會很快。
不過,若是您使用 @Today,舊的視圖索引就沒有用了。例如,假設選擇公式爲:
SELECT Status = 「Processing」 & DueDate <= @Today
|
能夠將文檔添加到該視圖,
即便這些文檔並無改變,由於自從上一次使用視圖以後,@Today 的值就改變了。所以您每次使用這個視圖時,Lotus Notes 都會丟棄舊的視圖索引,並查看
數據庫中的每一個文檔,以決定這些文檔是否屬於該視圖,或從新計算列值。
假設您有一個列,若是「請求」文檔在3個小時以後仍然打開的話,它將顯示一個紅色的感嘆號(使用 @Now 測試它)。這種狀況會發生變化,即便在5秒鐘以前還在使用該視圖。然而使用 @Today 時,下降視圖索引的更新頻率可能更好。
您可使用視圖屬性對話框中的視圖索引選項實現這個目的。在 Advanced options 選項卡上,您能夠將視圖更新指定爲「Auto, at most every x hours」,其中 x 是您指定的值。這樣作的優勢是大大加快了視圖的打開,但同時也存在缺點,那就是視圖不會當即顯示文檔更改,
即使文檔已更改。用戶必須手動刷新視圖才能看到最新的數據。
另外一個流行的代替辦法就是建立一個在夜間運行的調度代理程序,它經過更新視圖選擇公式(使用 NotesView.SelectionFormula 方法)來包含當天的選擇公式。例如,代理程序可能包含如下語句:
view.SelectionFormula = {SELECT Status=「Processing」 & DueDate=[} & Today & {]}
|
不過,它也有一些缺點:
- 在全部副本顯示正確的文檔以前,必須在全部地方複製視圖設計更改。
- 服務器管理員可能不信任更改產品應用程序的設計的代理程序。
- 次日早上打開視圖的第一位用戶仍然須要等待索引視圖。您能夠將視圖索引選項設置爲「Automatic」,或讓代理程序刷新視圖,這樣就可以避免這個問題。
- 若是數據庫從模板獲取設計,您的視圖將被模板覆蓋。爲了不這個問題,您可讓代理程序在夜間設計刷新以後再運行,或將更改應用到模板。
另外一個辦法就是在用戶界面上作出讓步。例如,您能夠對視圖使用 「open requests by due date 」而不是「open requests that are overdue」,以在視圖的頂部對延遲的請求進行排序。它們很容易實現,實現以後視圖的打開會快得多。
在一些狀況下,適合使用文件夾根據日期條件顯示一組文檔。在夜間運行的代理程序可使用知足該日期需求的文檔填充這個文件夾,而且文件夾上的訪問設置能夠阻止用戶手動更改其內容。若是在白天編輯文檔時須要更改文件夾的內容,這就不是一個好選擇(雖然比較繁瑣,但您還可使用定製代碼進行管理)。
許多應用程序很慢,由於它們包含太多視圖,刪除一部分視圖將有所幫助。性能影響通常出如今服務器上,而不是特定的應用程序。
注意:數據庫的設計器不必定要訪問每一個視圖。用戶的「Server private」視圖和其餘帶有讀者列表的視圖是不可見的,但它們仍然會影響性能。服務器管理員能夠在「Full access administration」模式下查看這些視圖。
默認的視圖刷新設置(Auto after first use, Discard index after 45 days)意味着超過 45 天后不使用的視圖索引將被丟棄,而且服務器不會再刷新它們。在這點上,它們對服務器性能的影響是很小的。然而,在摘要中使用視圖可能會致使用戶在搜索所需視圖時意外地使用它們。
所以,經過僅包含必要的視圖(用於完成用戶的特定任務,其命名方式便於用戶辨認),您不但能夠改善性能,並且還提供更好的用戶體驗。
一般須要爲某個目的建立一次性使用的視圖,而且沒有程序記錄誰須要它們,誰使用它們,以及什麼時候可以安全地刪除它們。它們經常是「Server private」視圖,僅對它們的建立者是可見的,但它們仍然會影響性能。限制建立此類視圖可以保持更好的性能(若是您想看看有哪些私有視圖,服務器管理員可使用「Full access administration」模式列出它們)。
咱們推薦對視圖使用 Comment 字段,用於描述視圖的任務、使用者和超過該日期就能夠刪除視圖的「過時」日期(若是知道的話)。這樣,若是您對是否有必要使用視圖存在疑問,您至少知道應該問誰。若是您想刪除一個視圖,看看是否有人反對,能夠將其複製粘貼到另外一個未包含有文檔的數據庫,這樣您就能夠在須要時找到它。
一般,應用程序包含的視圖僅是排列方式不一樣而已。這些視圖應該使用可從新排序的列合併到一個視圖中。儘管添加劇新排序列的成本很高,但這要比擁有第二個視圖的成本低。
若是您在 Lotus Notes 8.0 中使用新的列選項「Defer index creation until first use」,那麼就更應該這樣作了。這個選項延遲爲從新排序建立索引,直到用戶請求它。這會給首位請求用戶形成很長的延遲,但若是沒有人請求的話,你們都能享受到更好的性能。
當您查找不須要的視圖時,要記住,開發人員不必定可以查看應用程序中的全部視圖。若是用戶在服務器上存儲了私有視圖,或者共享視圖的訪問列表沒包含您的名字,那麼您就不能在設計器中查看這些視圖 —— 但它們仍然會影響性能。使用「Full access administration」模式的服務器管理員能夠繞過訪問控制得到全部視圖的列表(並刪除任意視圖)。
由於服務器必須經過額外工做才能在請求時執行交替視圖排序,因此除非有必要,不然不要啓用從新排序。升序和降序計數是兩種不一樣的從新排序,所以除非實際須要,不然不要同時啓用它們。在 Lotus Notes 8.0 中,若是您不肯定是否使用了從新排序,那麼能夠啓用該列上的「Defer index creation until first use」選項。
注意,您還能夠選擇經過單擊列的頭部,將用戶導航到已由該列完成排序的不一樣視圖,這樣您就能夠爲從新排序提供便利,而且省去額外的工做(若是另外一個視圖已經存在)。
咱們傾向於爲每一個字段建立一個列,但應該避免這樣作。僅在視圖中包含用戶實際須要查看的信息便可;這樣屏幕就不會那麼擁擠,而且應用程序的速度會更快,佔用的存儲空間會更少。
若是視圖列公式或選擇公式使用了循環函數(@For、@While和@Transform),或除註釋以外超過 200 個字符,那麼就須要簡化它。若是不能簡化它,那麼考慮將公式移動到表單的計算字段,讓視圖僅引用字段名。對於在多個視圖中使用的公式,這尤爲有用。
即便您不使用計算字段,對於較長的公式,稍微思考一下就能簡化它。考慮使用 @Select 或 @Replace 代替較長的 @If 語句,並檢查邏輯,看看是否可以經過不一樣的順序簡化測試。
要注意對列表的全部成員執行操做的運算符和 @Functions。沒有必要爲字符串列表上的許多簡單操做編寫循環;例如,要獲取每一個元素的前三個字符,可使用 @Left(
listfieldname; 3) 來實現。
咱們還有一些「組合操做符」,好比 *=,可用於比較來自兩個列表的組合元素,而且也能幫助您編寫更加緊湊的公式。
若是您使用其餘語言編寫程序,您可能對邏輯運算符比較熟悉,它們僅對可以決定鏈接值的表達式進行計算。例如,您可能但願獲得這樣的表達式:
Form = 「Report」 & ( Sections = 「Financials」 | Total > 10000)
|
首先檢查 Form 是否是 Report,當這個條件爲真時,才測試表達式的其他部分。在宏語言(和 LotusScript)中,邏輯運算符不是這樣工做的。表達式的兩部分都要計算。因此,若是計算第二部分的開銷比較大,您能夠選擇以下所示的「懶惰邏輯」公式:
@If(Form = 「Report」; Sections = 「Financials」 | Total > 10000; @False)
|
@If 函數的執行時間比 & 運算符長,但若是可以經過它避免執行一些沒必要要的大開銷函數,您就領先一步了。
分類是很是有用的。它們容許在同一視圖的多個標題下列出某個文檔。但不要過分使用它,由於在一個視圖任務中兩次列出某個文檔所需的時間幾乎翻了一倍。若是每一個文檔分別列出在 50 個類別中,再乘以文檔數就得出總行數,那麼服務器須要存儲和計算多少個行?這會給服務器帶來很大的壓力。
即便您不使用
多個 分類,通過分類的視圖仍然比使用簡單排序的視圖慢。所需的時間取決於行數,而不是文檔數,而且每一個文檔和類別標題都是一個行。
視圖屬性對話框包含一組控制視圖索引的選項。這些選項不多用到,但選擇正確的索引選項可以大大提高性能。
例如,假設數據庫包含特定的關鍵字文檔,您須要頻繁查找它們以填充表單上的關鍵字列表。關鍵字文檔是不多更改的,但應用程序中的其餘文檔則須要常常更改。
在討論 @DbLookup 時咱們已經知道對這種查找使用緩存是最好的,但第一次必須直接訪問視圖,由於還不存在緩存值。當您執行這個過程時,Lotus Notes 發如今最後一次使用視圖以後文檔被更改了,而後將花時間查找被更改的文檔,並發現它們並不在視圖中。
對於在關鍵詞值 @DbLookup 中使用的視圖,不須要在每次使用時都進行從新索引。對於這種視圖,使用索引選項「Auto, at most every
x hours」比較合適(見圖 2)。
若是沒有人使用這些視圖,服務器仍然會更新它們,但時間間隔要長些。偶爾可能會有不幸運的用戶刷新索引。但這會致使平均查找時間更短,而且同一個用戶在複雜表單的每一個查找中都碰到刷新的機會不大,所以使用該選項後表單的打開速度會更快。
若是僅在每一個季度的季度審覈時才使用視圖,那麼將索引保留 45 天沒有任何意義。將其設置爲在 2 天以後丟棄,這樣可以減輕服務器的工做。
在其餘狀況下,選擇適當的索引選項可以改善性能。想辦法肯定您的視圖應該使用什麼設置是值得的。
注意:能夠經過程序在當前的副本中刷新索引,好比使用 NotesView.Refresh 方法。假設一個索引在正常狀況下不多更新,但當您保存某個向視圖提供數據的表單時,則必須更新視圖,以在查找中使用新的數據。在表單的 Postsave 代碼中,對視圖使用 Refresh 方法。同時,您可使用帶有 ReCache 的 @Db 函數,將特定查找的緩存更新到視圖。
當您須要 Reader 字段時,沒有什麼東西能夠代替它,但它可能會大大損害視圖性能。當您打開包含帶有 Reader 字段的文檔時,Lotus Notes 會對行進行掃描,查找您能夠訪問的行。當行的數量填滿屏幕時,將中止查找。若是您僅能訪問一個文檔,它必須查看視圖中的每一個行進行確認,這可能須要花很長時間。
對此,您能夠:
- 使用比較短的 Reader 字段值。在單一角色中檢查成員關係要比根據一個長長的訪問名稱列表比較它們快(使用角色還便於維護)。
- 避免在這種應用程序中使用視圖。若是用戶僅能訪問一兩個文檔,您能夠提供其餘訪問方式,例如,向他們發送包含有這些文檔連接的電子郵件。
- 使用嵌入式單類別視圖,這種視圖僅顯示包含「它們的」文檔的類別。
- 使用設置爲顯示空類別(即未包含文檔的類別)的分類視圖。固然,這樣作使得用戶查找文檔更加困難,除非您爲用戶提供導航,所以您應該將該功能和 @SetViewInfo 結合使用,以僅顯示用戶所需的類別。
注意:使用分類視圖存在安全問題;即您在文檔中向用戶顯示了一個字段(類別),他們原本是不能夠訪問該字段的。要確保使用這種辦法是可行的!
- 鼓勵用戶使用本地副本。由於本地副本僅包含用戶可以訪問的文檔,所以不須要花功夫隔離他們不能訪問的文檔。
不要單獨使用 Reader 字段做爲導航幫助;例如,這是一種幫助用戶方便地查找所需文檔的方法,由於它們是用戶可以在視圖中看到的全部文檔。若是文檔中的信息不是隱私的,還有其餘更好的方法能夠幫助用戶找到所需的文檔,如前一小節和下一小節所述。
在共享視圖的選擇或列公式中使用 @UserName 和 @UserRoles 時,不能獲得滿意的結果。這是開發人員建立僅顯示「My Documents」的「Private on first use」視圖的常見緣由。這些視圖可能存儲在服務器上(將從整體上影響應用程序的性能),或者存儲在用戶的本地「桌面」文件中。
桌面視圖不會直接影響服務器的性能,但當打開其中一個視圖時,將像其餘視圖同樣進行從新索引,以顯示最近的更改。這意味着用戶工做站必須向服務器請求自從最後一次使用以後修改的全部文檔。這個過程可能形成用戶等待,若是許多用戶執行該操做,服務器還可能會由於大量發送數據請求而陷入困境。
注意,視圖索引僅使用
摘要 數據,所以大型的富文本字段和文件附件在這裏不構成問題。
除了性能問題以外,私有視圖還面臨維護方面的問題,由於開發人員沒有簡單的方法更新用戶私有副本的設計。在這種狀況下,共享列也不起做用,由於要在視圖中更新共享列,執行更新的人員必須可以訪問該視圖。
一般可使用 Notes 視圖的「single category」功能避免「Private on first use」。例如,若是您正在顯示「My Documents」,您可使用根據全部者分類的視圖,而後要麼使用「single category」公式將該視圖嵌入到表單或頁面中,要麼在視圖中的 Postopen 事件中使用 @SetViewInfo,僅對當前用戶進行顯示。由於只有一個共享視圖,因此整體索引開銷降至最低,而且私有用戶沒必要像在桌面私有視圖中那樣等待,由於索引幾乎老是最新的。
當您開始編寫 LotusScript 或 JavaTM 代碼時,您可能就開始逐步損害性能。在這裏,咱們討論一些常見的問題。
使用 NotesDocumentCollection.GetNthDocument 遍歷集合是很是慢的;應該改用GetFirstDocument 和 GetNextDocument。對於某些類型的集合使用 GetNthDocument 也同樣高效,但不使用它事情更好辦。
若是表單、視圖或文件夾有許多操做,您就須要在設計元素中爲每一個操做編寫代碼(使用共享操做也是如此),這樣就存儲了許多代碼,每次使用設計元素時都必須將它們加載到內存中。
在大部分時間,僅用到許多操做中的其中一兩個,所以您須要等待加載全部操做。若是操做出如今多個地方,您就在設計緩存中屢次緩存了相同的代碼,從而佔用應該用於其餘用途的內存。
能夠考慮將一些操做移動到代理程序中。這樣,當有人請求運行操做時,僅在內存中加載一個代碼副本。能夠用宏語言編寫操做按鈕,以使用 @Command([RunAgent]) 調用代理程序,這能大大減小隨設計元素一塊兒加載的代碼。
若是您容許用戶建立私有視圖或文件夾時,這尤其重要,由於他們的文件夾將屢次複製操做代碼,這不只佔用空間,並且還不能進行更新,除非用戶手動刪除私有視圖。
加載多個腳本庫所需的時間並非線性增加的。即加載 10 個腳本庫所需的時間比加載 5 個腳本庫所需的時間的 2 倍還要多,腳本庫使用了其餘庫時尤爲如此。
這在將來可能會獲得改變,儘管如此,也存在一個平衡點;訪問兩個設計元素比訪問一個包含相同數量代碼的設計元素所需的時間長。將常常一塊兒使用的腳本庫合併起來可以節省加載時間,儘管有時會加入不須要在特定代理程序中調用的代碼。
NotesDocument 的 ComputeWithForm 方法是在文檔中更新計算字段但不復制代碼的便捷方法。不幸的是,這比「手動」計算和分配新字段值更慢。若是您的代理程序很慢而且使用了 ComputeWithForm,向 ComputeWithForm 添加幾行用於爲特定字段賦值的代碼就可以大大加快程序的速度。
默認狀況下,使用 NotesView 對象時,它將爲視圖實現常規的索引刷新屬性。例如,假設您更新一組「Vegetable」文檔,做爲這個過程的一部分,您必須在同一數據庫下的「Pests」視圖中查找破壞該植物的害蟲。可是當您保存了一個 Vegetable 文檔時,另外一個文檔又被更改了。
當您處理下一個文檔,並查找「Pests」視圖時,Lotus Notes 就知道視圖索引已通過期,而後刷新它。您所作的更改不會影響 Pests 視圖,但在檢查已更改的文檔以前,Lotus Notes 並不知道這點。
對於這個例子,使用 NotesView 的 AutoUpdate 屬性告訴 Lotus Notes 沒必要更新視圖索引是個不錯的主意,除非您使用 Refresh 方法顯式地請求它。這可以大大提高速度。
即便您所作的更改影響到 NotesView 的內容,也可使用這種方法,只要您的更改對本身正在作的事情沒有影響便可。例如,您知道更新將從視圖刪除文檔,但這沒有關係,由於您已開始處理下一個文檔。
NotesDocumentCollection 類有一些以「All」結尾的方法,它們可以處理集合中的全部文檔。您應該瞭解這些方法,由於它們比遍歷集合和操做每一個文檔快得多。(除非您須要對每一個文檔執行多個操做;不然遍歷會更快,每一個文檔僅需保存一次)。
內置類中的某些方法和屬性很是慢。若是不須要,就避免使用這些函數,這能讓代碼的運行更快。例如,假設您處理一個文檔集合,必須使用每一個文檔的一個字段做爲查找值,以從其餘視圖獲取信息:
Dim view As NotesView
Set docCur = coll.GetFirstDocument
Do Until docCur Is Nothing
Set view = db.GetView(「CustomersByID」) 'oops! Don't do this in the loop!
Set docCust = view.GetDocumentByKey(docCur. CustI D(0), True)
...
Set docCur = coll.GetNextDocu ment(docCur)
Loop
|
在這段樣例代碼中,若是
coll 包含 1000 個文檔,咱們將調用開銷很大的 GetView 方法
1000 次。若是調換
Do
Until 和
Set view 代碼行的位置,代碼的運行就會快得多,由於
GetView 僅被調用一次。
使用代理程序探查器查找這類東西是個不錯的方法。developerWorks Lotus 文章 Troubleshooting application performance: Part 1: Troubleshooting techniques and code tips 和 Troubleshooting application performance: Part 2: New tools in Lotus Notes/Domino 7 將對此進行描述。
還記得嗎,影響性能的因素之一就是修改文檔的頻率。當您編寫處理文檔的代理程序時,應該避免沒必要要地保存文檔更改。在爲每一個項賦值時,檢查它是否已經擁有該值。若是最終沒有修改任何東西,就不要調用 Save 方法。一般,您可使用搜索方法從文檔集合中過濾出不須要處理的文檔。
若是您老是檢查各個項以肯定是否更改它們,代理程序的運行可能慢些。但也可能不變慢,由於保存文檔比在內存中比較信息須要更多時間。若是老是執行檢查,應用程序的其餘部分會更高效,好比複製、視圖索引和全文本索引。
避免沒必要要的保存也能夠減小複製衝突。複製使用
項 修改時間;它並不將整個文檔發送給其餘副本,而是僅發送修改的項。因此,即便最終須要保存文檔,若是隻修改須要新值的項,那麼就能減小複製時間。使用本地副本的用戶將受益不淺。
大部分代理程序必須作的一件事情是查找一組須要處理的文檔。有不少查找文檔的方法,但不一樣的方法適用於不一樣的狀況。
developerWorks Lotus 文章 Lotus Notes/Domino 7 application performance: Part 1: Database properties and document collections 討論搜索和處理文檔集的不一樣方法。下面歸納地介紹一下:
- 若是視圖包含您須要的文檔,而且以有用的方式進行排序,那麼從視圖讀取文檔就會更快,例如使用 GetAllDocumentsByKey 方法。
- 對於包含大量文檔的數據庫,FTSearch 方法比 NotesDatabase.Search 方法要快,前提是數據庫必須是全文本索引的。注意,您也能夠經過在代理程序的 Document Selection 事件中輸入全文本搜索來執行它。
在這兩種狀況中,利用服務器事先完成的索引工做能夠節省時間。與必須檢查每一個文檔的 NotesDatabase.Search 相比,FTSearch 節省了一些運行時工做。
全文本搜索的文檔過濾級別不如 NotesDatabase.Search 細,但它節省了大量時間,您徹底能夠利用一部分時間遍歷結果並忽略不適用的部分。在 Notes Client 幫助(不是 Designer 幫助)中的文章「Refining a search query using operators」介紹了完整的全文本查詢語法。您將發現它的用途比您想象的要多。
注意:取決於本身的需求,有時您能夠結合公式搜索的威力和全文本搜索的性能,在使用基於公式選擇條件的視圖中進行全文本搜索。
在早期的 Lotus Notes 版本中,使用完 NotesDocument 對象以後,可使用 Delete語句從內存中刪除它們。而後,從 6.0 版本開始,不再須要這樣作了。(若是您已經知道是怎麼回事,就不要再使用它。若是不知道,也不用擔憂)。
出於其餘非性能方面的緣由,您可能還在使用 Delete,例如,您認爲其餘進程修改了文檔,由於您最終打開它,並確保本身看到的是最新數據。
有一些文章比較了「for」循環和「while」循環、全局變量和堆棧變量等的性能。然而,除非您的應用程序屬於計算密集型的,不然難以利用這些比較得到性能改善。
大部分腳本花在打開文檔和視圖的時間遠比處理變量值多。避免沒必要要的數組引用能夠節省百萬分之一秒;然而,打開沒必要要的視圖可能要花費數秒鐘。若是想經過節省時間來提升性能,那麼應該先考慮佔用時間多的項。
瞭解不一樣 LotusScript 表達式和語句的性能特色可能很是有用,但養成良好的代碼編寫習慣更有用;回過頭來修改不穩當的地方經常是得不償失的。
關於這個方面的有價值技巧是:
- 不要使用 GetNthDocument(如前所述)
- 顯式地聲明變量,避免使用默認的變量類型。這樣作不只可以提供更好的性能,而且有助於在編譯期間查找錯誤。對於自動將 Option Declare 語句插入到您的 LotusScript 代碼中的編程面板屬性,應該使用這個選項。
若是將 LC LSX 與外部關係數據庫或數據文件整合起來,它一般比內置的 ODBC 類快。
IBM Redbooks Implementing IBM Lotus Enterprise Integrator 6 包含了大量信息,討論如何使用這個 API 進行編程,以及如何最大限度地提高性能。
這份白皮書在開始時已經提到,不少優秀的小程序在數據和用戶的數量比較少時表現很是出色,但當用戶和數據很是多時,它們就陷入困境了。使用大量文檔測試設計是明智的。測試 50 人同時使用應用程序時有什麼反應(您可能很難找到 50 位朋友抽時間參與測試,但可使用可以模擬該場景的自動化測試工具)。
此外,編寫包含少許樣例數據的代理程序也不是很難,而後經過爲選擇字段分配隨機值增長數據的數量,使文檔多達數千個。若是您使用代理選項建立新文檔的話(在代理程序編輯屏幕的右下角),這些工做還能夠經過公式代理程序完成。
警告:若是您測試已投入生產的應用程序,務必在非生產服務器的數據庫拷貝(
不是 副本)上進行測試,而且最好使用不用於複製生產服務器的服務器。這樣,就不用擔憂破壞生產服務器上的數據,或阻礙使用該服務器的人員的工做。
配置文件文檔是高效地儲存和獲取不常常改變的信息的好辦法。由於文檔在首次使用時就被完整地緩存起來,因此使用它保存定製關鍵字列表是很是高效的。這不會影響視圖索引,也不用擔憂控制緩存。它們的複製和普通文檔是同樣的(但使用複製選擇公式的用戶不會意外地破壞應用程序,這比普通的關鍵字文檔要好)。它們既有趣又簡單,您能夠嘗試使用!