ODAC獲取數據的效率比較高,在Web程序中希望能夠更快獲取第一頁的數據時,可以有幾種方式:
1、在數據庫中進行分頁處理;
2、獲取所有數據,只是快速返回第一頁數據。
第一種方案對應用服務器資源消耗最小,對數據庫消耗略大,在客戶需要對全數據進行靈活過濾、查找、統計時就有些不夠用了,另外對耗時較大的SQL查詢就不如第二種方案速度快,對數據庫壓力也要大些,並且需要編寫程序來完成。在Delphi下我考慮使用第二種方案,尤其是在使用uniGUI+ODAC配合使用時。第二種方案對應於服務器內存壓力略大,並且要求快速獲取第一頁數據,為此做了個實驗:
1、單表中有24萬條記錄
2、使用一次性獲取全部記錄,並放在服務器內存中,由uniGUI的網格進行自動分頁處理。
3、非一次性獲取全部記錄時,需要快速獲取第一頁數據,將TOraQuery組件的FetchRows設置與TUniDBGrid組件的WebOptions.PageSize一致(不是必須的,只是覺得這樣對顯示第一頁更有效率些),再通過啟動一個線程,在后台通過TOraQuery組件的FetchAll屬性設為True來獲取全部數據。TOraQuery的數據量發生變化后,在TUniDBGrid組件中滾動任意記錄都會觸發記錄數與分頁數的自動更新,所以不需要在獲取全部數據后刷新網格。
代碼如下:
procedure TMainForm.UniButton11Click(Sender: TObject); var d : DWORD; begin //計時 d := GetTickCount; //每個數據包獲取的記錄數,建議與網格的每頁數保持一致 UniMainModule.OraQuery7.FetchRows := UniDBGrid7.WebOptions.PageSize; //是否一次性獲取 UniMainModule.OraQuery7.FetchAll := UniCheckBox7.Checked; //開啟表,如果是非一次性獲取,則中獲得了第一個數據包的記錄數 UniMainModule.OraQuery7.Open; //花費時間 UniLabel17.Caption := Format('%d ms', [GetTickCount - d]); //開啟線程獲取 if not UniCheckBox7.Checked then TFetchThread.Create(UniMainModule.OraQuery7); end;
UniCheckBox7.Checked決定了是否采用一次性獲取的選項,實驗顯示:
1、一次性獲取數據模式,顯示第一頁花費了3000ms左右時間,內存占用約180M,關閉數據集后內存減少為10M左右,說明內存釋放非常干凈。
2、非一次性獲取數據模式,顯示第一頁花費了約20ms左右時間,后台讀取數據沒有影響前端數據的展示、滾動等操作,最終內存占用與關閉后釋放同一次性獲取模式。
后台獲取數據的線程代碼如下:
TFetchThread = class(TThread) private FDataSet : TOraQuery; public procedure Execute; override; constructor Create(ADataSet : TOraQuery); end;
{ TFetchThread } constructor TFetchThread.Create(ADataSet: TOraQuery); begin FDataSet := ADataSet; FreeOnTerminate := True; inherited Create; end; procedure TFetchThread.Execute; begin inherited; if Assigned(FDataSet) then begin FDataSet.FetchAll := True; while not FDataSet.Fetched do Sleep(10); MainForm.Caption := 'refresh'; end; end;
效果基本滿意