2017-02-24 3 views
0

Je me connecte à une base de données en utilisant ADO (C++), je lis une table d'environ 5m enregistrements, et je veux limiter l'utilisation de la mémoire du côté client. Actuellement, l'itération à travers les enregistrements entraîne une augmentation de la mémoire de 1 Go sur le processus, et je veux réduire cela de manière significative.Limitation de l'utilisation de la mémoire du jeu d'enregistrements ADO

Le code est très standard C++ ADO (modifié pour une meilleure lisibilité):

ADODB::_ConnectionPtr m_pConnection; 
m_pConnection.CreateInstance(__uuidof(ADODB::Connection)); 
m_pConnection->Open(_bstr_t(strConnect), m_strDBUserName, m_strDBPassword, -1); 

ADODB::_RecordsetPtr pRecordSet; 
pRecordSet.CreateInstance(__uuidof(ADODB::Recordset)); 

pRecordSet->putref_ActiveConnection(pConnection); 
pRecordSet->Open(_variant_t(bstrQuery), vNull, ADODB::adOpenForwardOnly, ADODB::adLockOptimistic, ADODB::adCmdText); 

pRecordSet->MoveFirst(); 
while(!pRecordSet->EOF) 
{ 
    CString cardNum = (LPCWSTR)(pRecordSet->Fields->GetItem("CARD_NUM")->Value.bstrVal); 
    int nSeqNum = pRecordSet->Fields->GetItem("SEQ_NUM")->Value.intVal; 

    // process data 

    pRecordSet->MoveNext(); 
} 

Ce que je constate est, comme il parcourt les dossiers, augmentation de l'utilisation de la mémoire de façon linéaire, à environ 200 Mo par million d'enregistrements. Ce que je voudrais faire est: pendant le traitement, dire à l'ensemble d'enregistrements de libérer la mémoire des enregistrements déjà traités, afin que l'utilisation de la mémoire soit maintenue basse. Y a-t-il une fonction pour le faire? Si ce n'est pas le cas, est-ce que je peux prendre une approche manuelle pour partitionner les données avec plusieurs ensembles d'enregistrements, en les libérant au fur et à mesure?

Répondre

0

Ma solution à ceci était de libérer manuellement les données. Chaque enregistrement N, je ferme l'ensemble d'enregistrements et j'effectue une nouvelle requête en commençant à l'enregistrement suivant. Il a fallu quelques changements à mes questions ...

int partitionSize = 100000, nRecordIndex = 0; 
CString query("select CARD_NUM, SEQ_NUM from CMS_CARD order by CARD_NUM, SEQ_NUM"); 
DoSelect(theCWIDatabaseManager.GetConnection(), pRecordSet, query); 
pRecordSet->MoveFirst(); 

while(!pRecordSet->EOF) 
{ 
    // process data 

    nRecordIndex++; 
    if(nRecordIndex % partitionSize == 0) 
    { 
     pRecordSet->Close(); 
     query.Format("select CARD_NUM, SEQ_NUM from CMS_CARD where CARD_NUM = '%s' and SEQ_NUM > '%s' union select CARD_NUM, SEQ_NUM from CMS_CARD where CARD_NUM > '%s' order by CARD_NUM, SEQ_NUM", lastCardNum, lastSeqNum, lastCardNum); 
     DoSelect(theCWIDatabaseManager.GetConnection(), pRecordSet, query); 
     pRecordSet->MoveFirst(); 
    } 
} 

pas aussi élégant que si l'enregistrement ensemble libéré la mémoire, mais semble fonctionner.