帆软报表优化总结
date: 2019/1/24 11:17:16
前言
之前在做報表時沒有注意那么多細節,上次給甲方公司做他們總公司匯總,明細報表,這種報表動輒幾十萬上百萬的數據量,明細表還好使用控件進行分批查詢的策略可以解決問題,但是匯總,統計的報表沒辦法進行分批或者限制查詢量進行處理,因為那樣處理必定導致統計結果和表達運算不夠準確。因此找到了帆軟官方中對于報表性能優化的多個文章,進行仔細查看和對SQL優化處理,最后達到還算滿意的查詢速度。
文章內容來源自帆軟官方多篇文章:如需閱讀官方教程,可自行忽略本文內容,地址如下
http://help.finereport.com/category-view-230.html
一 報表執行過程
帆軟報表的執行過程大致分為兩步: 1、報表計算 2、頁面轉換
**報表計算過程:**先讀取我們的sql語句,將完整的sql語句傳至數據庫服務器,由數據庫返回數據給報表服務器,報表服務器進行數據列的擴展、匯總、關聯、公式運算等計算,最終生成報表結果。
**頁面轉換過程:**報表計算完成后生成xml頁面,需要轉換為html頁面才能在瀏覽器中查看。
帆軟通過log日志進行監控這一執行過程
二 優化報表取數
1、描述
報表的核心是數據,數據集是否合理決定了報表的質量
1、每一張表都應該有一個主數據集,為了降低維護工作量,盡量將所有字段置于主數據集下。
2、在制作報表之前,盡量考慮到所有需要展示的數據字段,在數據庫軟件中,合理編寫sql語句,大數據情況盡量對sql做優化,以及添加索引
2、取數原理
設計器拼出最終的SQL,將SQL語句傳給數據庫,數據庫執行,將數據返回給設計器。
由于計算過程首先要通過SQL語句從數據庫中取數據,我們可以通過控制數據量的大小和對數據的提前預處理來提高報表的性能。
3、優化SQL
1、SQL中取用具體的字段
2、SQL中直接分組代替報表中分組
3、SQL中直接排序代替報表中排序
4、SQL中直接過濾代替報表中過濾
報表計算過程中很多時候并不需要對表中的所有記錄進行操作,而只是需要對部分滿足條件的記錄進行操作,雖然可以在報表設計器中對數據過濾,不過我們建議在SQL中對數據提前過濾,這樣數據庫返回的數據就減少了,既加快了取數速度,也加快了報表的運算速度
4、使用視圖、存出過程
視圖是由SELECT語句組成的查詢定義的虛擬表,由一張或多張數據庫實際的表中的數據組成的,從數據庫系統外部來看,視圖就如同一張表一樣。
存儲過程通過流控制與SQL語句,可以對數據進行強大的運算與處理,對于業務比較復雜的應用,常常需要將原始數據通過存儲過程處理后再供報表使用。另外存儲過程運行前,數據庫會對其進行語法和句法的分析,并進行優化,這種已經編譯好的存儲過程極大地改善SQL語句的性能。在報表端也只需要書寫較短的調用語句來獲得結果,從而降低網絡的通信量。
所以表與表的連接、復雜的SQL盡量在數據庫中使用視圖或者存儲過程直接進行,這樣將復雜的SQL語句直接保存于數據庫服務器端(數據庫本身會對SQL語句進行語法分析并進行優化),在報表設計器端就不需要寫大段的SQL語句而是直接調用視圖或存儲過程了,一方面減少網絡傳輸量,減輕數據庫的壓力,另一方面加快了報表的運算速度
5、優化示例
1、count(*) 比count(1)稍快
2、in和exists使用
在許多基于基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率SELECT * FROM EMP WHERE EMPNO > 0 AND EXISTS (SELECT ‘X’ FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB’)3、EXISTS替換DISTINCT
當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X’ FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO)4、用>=替代>
--如果DEPTNO上有一個索引 --高效: SELECT * FROM EMP WHERE DEPTNO >=4 --低效: SELECT * FROM EMP WHERE DEPTNO >3 兩者的區別在于, 前者DBMS將直接跳到第一個DEPT等于4的記錄而后者將首先定位到DEPTNO=3的記錄并且向前掃描到第一個DEPT大于3的記錄.5、應避免在 where 中使用!=或<>操作符
將導致引擎放棄使用索引而進行全表掃描。優化器將無法通過索引來確定將要命中的行數,因此需要搜索該表的所有行。6、應避免在 where 子句中使用 or 連接!
否則將導致引擎放棄使用索引而進行全表掃描,如:select id from t where num=10 or num=20可以這樣查詢:select id from t where num=10 union all select id from t where num=207、 in 和 not in 也要慎用!
因為IN會使系統無法使用索引,而只能直接搜索表中的數據。如:select id from t where num in(1,2,3)對于連續的數值,能用 between 就不要用 in 了:select id from t where num between 1 and 38、充分利用連接條件!
在某種情況下,兩個表之間可能不只一個的連接條件,這時在 WHERE 子句中將連接條件完整的寫上,有可能大大提高查詢速度。例:SELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NOSELECT SUM(A.AMOUNT) FROM ACCOUNT A,CARD B WHERE A.CARD_NO = B.CARD_NO AND A.ACCOUNT_NO=B.ACCOUNT_NO第二句將比第一句執行快得多。9、能用GROUP BY的就不用DISTINCT
10、能用UNION ALL就不要用UNION!
UNION ALL不執行SELECT DISTINCT函數,這樣就會減少很多不必要的資源三 優化報表就算時間
1、較少冗余單元格
2、慎用隱藏行列
3、慎用合并單元格
4、相同效果的條件屬性
同一行(列)中的單元格需要設置相同效果的條件屬性時,只需在該行(列)中的某個單元格設置一下條件屬性便可,這樣能夠加快報表的運算速度
5、 相同效果的數據列基本屬性設置
報表制作過程中,我們將數據集中的字段拖入單元格時,數據列>基本>數據設置,(分組、列表、匯總)中計算最快的是列表。如制作明細表時有兩種設置方法,結果是一樣的。
設置方式一:訂單ID列數據設置為列表,后面其他跟隨其擴展的數據列的數據設置還是采用默認的設置(即分組普通)。
設置方式二:訂單ID列數據設置為列表,后面其他跟隨其擴展的數據列的數據設置也修改為列表。
上面兩種設計方式的數據展示結果是一樣的,不過報表的計算速度卻不一樣;第二種方式的報表計算速度明顯會比第一種快。
這是因為數據列設為分組時,報表會將取出的數據進行一次分組聚集的計算,而不管數據有沒有重復。因此,對于可實現相同效果的應優先設置其數據列屬性為列表。
6、父格設置
FR中設計報表的最重要的思想,就是數據列的擴展,而跟隨哪一個單元格擴展是必須要注意的問題。所以父格的設置是很重要的,父格設置不恰當會影響報表的計算速度,甚至導致結果錯誤。另外,父子格層次樹高度,對報表性能也有影響,所以盡量減少父子格層次樹高度。如對下圖模板:
設置方式一:是否已付父格為運貨費,運貨費父格為運貨商,運貨商父格為到貨日期,到貨日期父格為訂購日期,訂購日期父格為客戶ID,客戶ID父
格為訂單ID,父子格層次樹為6層。
設置方式二:是否已付、運貨費、運貨商、到貨日期、訂購日期、客戶ID的父格都為訂單ID,父子格層次為1層。
上面兩種設計方式的數據展示結果是一樣的,不過報表的計算速度卻不一樣;第二種方式的報表計算速度明顯會比第一種快。
7、 取消自動調整行高或列寬
在右側列表中選擇單元格屬性表-其他屬性,設置為不自動調整
8、優化過濾條件
查看模板中是否重復設置了過濾條件,刪除多余的過濾條件,即若數據列來自相同的數據集,只需在最左父格設置過濾條件并勾選將父格子作為過濾條件(默認是勾選的)即可。
四 動態參數注入
原理:動態參數注入,是通過注入的值對數據庫中的數據進行操作的,只是取對應的數據,所以會提高報表的性能。
注:動態參數注入功能適用于大數據量報表,能夠明顯的體現出速度優勢
五 相鄰連續分組
相鄰連續分組的操作,是將數據集中連在一起的相同數據才進行合并的。尤其是,在配合SQL中已排好序的列,對其實現的分組時,使用此分組方式其性能比普通分組快些。如下簡單示例,查看其報表執行數據信息,可看出其分組方式比普通分組方式更能提高其報表的性能。
六 數據集緩存與共享
1、描述
對于大數據量報表,若每次直接從數據庫中查詢數據,不僅增加數據庫服務器的壓力,也極大的影響了取數的速度從而降低了報表的執行速度,為此FineReport提供了數據集緩存與共享功能。
FineReport可先將其數據集查詢的結果緩存下來,對于緩存下來的數據,再次使用到相同數據集時,無需再次連接數據庫重新查詢數據,直接使用緩存下來的結果,即使用FineReport的數據集共享機制,達到資源復用,減少取數時間從而提高了報表的展現速度。
2、數據集緩存
緩存分為緩存至內存和緩存至磁盤。
3、數據集共享屬性設置
瀏覽器中輸入http://localhost:8075/webroot/decision,進入FR平臺,選擇管理系統>系統管理>緩存
七 啟用行式引擎執行層式報表
適用場景描述
這樣一種報表:報表形式非常簡單,只是簡單的單數據源明細報表,但是數據量非常大,百萬、千萬甚至更多。報表取數及計算時間相當長。
希望能夠提高報表展示速度,對于用戶來說,查詢報表不會有滯后的感覺。
思路
1、解決方案
對于單數據源明細報表,可以啟用行引擎來執行報表,提高報表展示速度,優化用戶體驗。
2、原理
普通報表:取出全部數據后再執行報表,最后返回整體的報表結果給瀏覽器,用戶訪問到看到結果的時間=報表取數時間+報表執行時間;
行引擎報表:邊取數邊執行報表,執行到哪頁用戶就可以看到哪頁,用戶訪問到看到結果的時間=首頁數據讀取時間+首頁計算時間。
2、注意事項
行引擎報表注重的是性能,由原理我們可以想象,對于行引擎報表,每頁的計算必須是獨立的,即報表不能有單元格關聯的復雜運算,類似,為了提高行引擎報表的性能,FR舍棄了一些復雜的功能:
行引擎報表只適用于單數據源、即單元格過濾不能使用,且必須是簡單明細表,同時也不支持計算、條件屬性等復雜報表功能。
實現步驟
1、模板引擎設置
選擇模板>報表引擎屬性,勾選用行式的引擎來執行報表,再勾選下面的使用按頁運算分段執行報表,每頁記錄數使用默認值30,如下圖:
行式引擎按頁取數只適用于Oracle,mysql,hsql和sqlserver2012及以上數據庫,其他數據庫,如sqlite,access,sqlserver2005等必須手動編寫分頁sql,才能實現按頁取數,對于需要編寫分頁sql的數據庫,請參考單數據集分頁SQL實現層式報表章節。注:sqlserver2012及以上是支持行式引擎的的,但是sql中一定要寫order by。行式引擎只適用于單數據源報表,對于多數據集報表,行式引擎無法實現對其進行分頁顯示,多數據源的層式報表的實現請查看多數據集實現層式報表。總結
- 上一篇: 【密码专栏】动手计算双线性对(上)
- 下一篇: 戴尔创业节丨高效编程利器Vostro低至