首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

打造高效能 DBGrid:基於 CGridCtrl 虛模式與記憶體對映檔的百萬級資料表格

     編輯:關於VC++

前言

MFC 內建 DBGrid 不僅介面醜陋、文件缺乏,且大量資料載入極慢。本文介紹如何利用 Chris Maunder 的 CGridCtrl 之虛模式,搭配記憶體對映檔,打造支援百萬筆記錄、秒級響應的資料庫表格控件 COdbcDBGridFile。

為什麼選擇 CGridCtrl 虛模式?

傳統 Grid虛模式 Grid
需將所有資料寫入控件僅按需請求可見儲存格資料
十萬筆資料載入需數秒百萬筆資料瞬間顯示
記憶體佔用與筆數成正比記憶體固定,僅存可見區域資料

虛模式核心機制

  1. SetVirtualMode(TRUE) 啟用虛模式
  2. SetRowCount(totalRows) 設定總列數(不實際配置)
  3. 控件滾動時發送 GVN_GETDISPINFO 通知
  4. 處理器依 GV_DISPINFO.item.row/col 即時回傳資料

COdbcDBGridFile 架構設計


class COdbcDBGridFile {
public:
    COdbcDBGridFile(CGridCtrl* pGrid, CDatabase* pDB, CString strSQL, CString strMapFile);
    int InitGrid();           // 初始化:建立對映檔、讀取欄位資訊
    int SetGridText(GV_DISPINFO* pDispInfo); // 外部呼叫:填入儲存格文字
    int Release();            // 釋放資源
private:
    CGridCtrl* m_pGrid;
    CDatabase* m_pDB;
    CString m_strSQL;
    // 記憶體對映檔相關成員...
    // 快取機制:僅預讀可見範圍附近資料
};

關鍵創新:分批載入 + 記憶體對映檔

  • 查詢總筆數 SELECT COUNT(*) 設定 SetRowCount
  • 建立記憶體對映檔 (CreateFileMapping) 儲存資料列
  • 結構體陣列記錄每列在對映檔中的偏移量
  • 滾動時動態預讀:使用者向下滾動時,背景執行緒補充後續資料,避免一次性讀取幾十萬筆造成卡頓

整合步驟(對話框專案)

  1. 專案加入 CGridCtrl 相關檔案與 OdbcDBGridFile.h/.cpp
  2. 對話框放入 Custom Control,Class 設為 MFCGridCtrl,ID 為 IDC_GRIDODBC
  3. 關聯變數 CGridCtrl m_Grid,並在 DoDataExchange 加入 DDX_Control
  4. 成員變數:COdbcDBGridFile* m_pMapFile; CDatabase m_db;
  5. 處理 OnNotify 轉發 GVN_GETDISPINFO 給 m_pMapFile->SetGridText()
  6. 查詢按鈕:開啟資料庫連線 → `new COdbcDBGridFile(&m_Grid, &m_db, m_strSql, _T("c:\\csl.txt"))` → `InitGrid()`
  7. 關閉時呼叫 Release() 釋放對映檔與資料庫連線

核心程式碼片段

OnNotify 轉發


BOOL CDemo2Dlg::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult) {
    if (wParam == (WPARAM)m_Grid.GetDlgCtrlID()) {
        *pResult = 1;
        GV_DISPINFO* pDispInfo = (GV_DISPINFO*)lParam;
        if (GVN_GETDISPINFO == pDispInfo->hdr.code) {
            SetGridItem(pDispInfo);
            return TRUE;
        }
    }
    return CDialog::OnNotify(wParam, lParam, pResult);
}

查詢按鈕


void CDemo2Dlg::OnBtnQuery() {
    Release(); // 釋放舊資源
    UpdateData(TRUE);
    CString strConn;
    strConn.Format(_T("ODBC;DSN=%s;UID=%s;PWD=%s"), m_strSource, m_strUser, m_strPass);
    if (!m_db.Open(strConn)) return;

    m_pMapFile = new COdbcDBGridFile(&m_Grid, &m_db, m_strSql, _T("c:\\csl.txt"));
    m_pMapFile->InitGrid();
}

效能實測

  • 測試表:50 萬筆,30 欄位
  • 初始化耗時:< 1 秒(僅建立對映檔結構、讀取前 100 筆)
  • 滾動響應:無感知延遲(記憶體對映檔隨機存取 + 預讀)
  • 記憶體佔用:約 20 MB(固定,不隨筆數增長)

進階版本:搭配 CMYODBC

若替換 MFC CDatabase/CRecordset 為作者前作 CMYODBC/CODBCSet,可再提升 3-5 倍查詢速度。配套原始碼提供 CMyODBCDBGridFile 實作。

總結

COdbcDBGridFile 以 虛模式 + 記憶體對映檔 + 分批載入 三大技術,徹底解決 MFC 開發大量資料表格的效能痛點。介面僅 4 個公用函式,整合極簡單,是 VC++ 資料庫專案的利器。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved