Заменил ODBC API на ADO - все замедлилось в 10 раз
От: sergey  
Дата: 31.08.01 07:57
Оценка:
Заменил ODBC API на ADO — работа с базой сильно замедлилась. Кто подскажет, почему ?
Re: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: Ростислав Глухов Россия http://www.geocities.com/rg2204/
Дата: 03.09.01 04:50
Оценка:
Здравствуйте sergey, вы писали:

S>Заменил ODBC API на ADO — работа с базой сильно замедлилась. Кто подскажет, почему ?


Наверное, из-за неправильного использования ADO...
Типы курсоров, например,
или CacheSize у RecordSet'a не установил...
- А Вы что курите?
— Минздрав предупреждает
Re[2]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: sergey  
Дата: 03.09.01 11:38
Оценка:
Здравствуйте Ростислав Глухов, вы писали:

РГ>Наверное, из-за неправильного использования ADO...

РГ>Типы курсоров, например,
РГ>или CacheSize у RecordSet'a не установил...

Огромное спасибо за ответ, но пока все равно не очень получается. Типы курсоров пробовал разные и с кэшем игрался, но улучшений не получил. Был ли у вас опыт такого перехода и если да, то отразилось ли это на скорости работы с базой ?
Re[3]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: Ростислав Глухов Россия http://www.geocities.com/rg2204/
Дата: 03.09.01 13:03
Оценка:
Здравствуйте sergey, вы писали:

S>Огромное спасибо за ответ, но пока все равно не очень получается. Типы курсоров пробовал разные и с кэшем игрался, но улучшений не получил. Был ли у вас опыт такого перехода и если да, то отразилось ли это на скорости работы с базой ?


Опыта _перехода_ с ODBC на АДО нет
Есть опыт использования АДО отдельно

Странно, что улучшений нет, я когда оптимизировал CacheSize, получал улучшения в скорости в разы (не помню точно, что -то около 5 крат)

Для разных операций следует использовать разные параметры, напр для Грида CacheSize>10
как-то будет неочень при прогрутке туда-сюда
А для начальной загрузки справочника типа (ID,Name) CacheSize надо поболе

про влияния раздичнах параметров типа типаКурсора, adComText/adCmdTable и пр.
стОит посмотреть mdacsdk, там есть пример с замером скорости. Правда, на ВБ, но показательно...
- А Вы что курите?
— Минздрав предупреждает
Re: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: VladD2 Российская Империя www.nemerle.org
Дата: 03.09.01 19:40
Оценка:
Здравствуйте sergey, вы писали:

S>Заменил ODBC API на ADO — работа с базой сильно замедлилась. Кто подскажет, почему ?


А что за задачи то?
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: WindJammer  
Дата: 04.09.01 07:02
Оценка:
Здравствуйте sergey, вы писали:

S>Заменил ODBC API на ADO — работа с базой сильно замедлилась. Кто подскажет, почему ?


А вы фрагменты кода (того и другого) покажите, может и найдется человек, который скажет, где собака порылась.
Re[2]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: sergey  
Дата: 04.09.01 10:19
Оценка:
Здравствуйте VladD2, вы писали:

VD>Здравствуйте sergey, вы писали:


S>>Заменил ODBC API на ADO — работа с базой сильно замедлилась. Кто подскажет, почему ?


VD>А что за задачи то?


Есть довольно большая (по кол-ву таблиц) база. Раньше для ODBC API были написаны парочка функций для удобного вытаскивания содержимого таблиц в си-шные структурки. Т.е. по структуре базы генерились си-шные файлы с объявлением структур, соответствующих таблицам базы. Потом при запросе (простом) по таблице поля этих структур биндились к запросу и все было хорошо. При переходе на ADO я хотел сохранить эту схему, только ходьбу к базе заменить на ADO-шную. Текст на ODBC API рисовать не буду — больно здоровый, а ADO-шный текст смотрите в нижних сообщениях...
Большое спасибо за участие !
Re[2]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: sergey  
Дата: 04.09.01 10:21
Оценка:
Здравствуйте WindJammer, вы писали:

WJ>Здравствуйте sergey, вы писали:


S>>Заменил ODBC API на ADO — работа с базой сильно замедлилась. Кто подскажет, почему ?


WJ>А вы фрагменты кода (того и другого) покажите, может и найдется человек, который скажет, где собака порылась.


Вот фрагметец ADO-шной реализации класса, который раньше был на ODBC API. Старый печатать не буду — он довольно большой да и вряд ли чем поможет...

Спасибо большое и Вам за то что не прошли мимо !


Statement::Statement()
{
m_pConn = 0;
}

Statement::~Statement()
{
}

void Statement::Connect()
{
if (m_pConn)
return;

m_conn.CreateInstance("ADODB.Connection");
// ................................................................
strcpy (Buf, "");
GetPrivateProfileString("Data source", "DataSourceName", "", Buf, sizeof(Buf), "actmed.ini");
if (!strlen(Buf))
{
::MessageBox (NULL, "ActionMed not properly installed on this computer", "Message", MB_OK);
return;
}
CString conn_str;
conn_str.Format("DSN=%s", Buf);
m_conn->Open(_bstr_t(conn_str), "SQLDBA", "ACTMED", 0);
// ................................................................

m_rs .CreateInstance("ADODB.Recordset");

if (g_ActmedConn.IsConnected())
m_pConn = &g_ActmedConn;

m_FirstRecord = TRUE;
m_Opened = FALSE;
}

RETCODE Statement::ExecDirect(const char * sql_cmd)
{
if (!m_pConn) return SQL_ERROR;

if (m_Opened)
m_rs->Close();


m_Opened = FALSE;
// if (FAILED(m_rs->Open(sql_cmd, (m_pConn->m_pConn).GetInterfacePtr(),
if (FAILED(m_rs->Open(sql_cmd, m_conn.GetInterfacePtr(),
adOpenDynamic,
adLockOptimistic,
adCmdUnknown)))
return SQL_ERROR;

m_rs->CacheSize = 10;

m_flds = m_rs->Fields;

m_Opened = TRUE;
m_FirstRecord = TRUE;

m_BindColumn.RemoveAll();
m_BindPtr .RemoveAll();
m_BindLen .RemoveAll();
m_BindType .RemoveAll();

return SQL_SUCCESS;
}

RETCODE Statement::Fetch()
{
if (m_rs->EndOfFile == VARIANT_TRUE)
return SQL_ERROR;

// ..................................................................
int col, col_num, col_count = m_BindColumn.GetSize();
if (col_count)
{
CString str;
COleVariant val;

for (col = 0; col < col_count; col++)
{
col_num = m_BindColumn[col] — 1;
val = m_flds->Item[COleVariant((long)col_num)]->Value;

switch (m_BindType[col])
{
case SQL_C_DEFAULT:
case SQL_C_CHAR:
str = val.bstrVal;
str.TrimRight();
strcpy(m_BindPtr[col], str);
break;

case SQL_C_LONG:
*(long*)m_BindPtr[col] = val.lVal;
break;
}
}
}
// ..................................................................

// ..................................................................
if (!m_FirstRecord)
m_rs->MoveNext();
else
m_FirstRecord = FALSE;
// ..................................................................

if (m_rs->EndOfFile == VARIANT_TRUE)
return SQL_ERROR;

return SQL_SUCCESS;
}

RETCODE Statement::Bind (unsigned short n, char * buf, int len)
{
m_BindColumn.Add(n);
m_BindPtr .Add(buf);
m_BindLen .Add(len);
m_BindType .Add(SQL_C_DEFAULT);

return SQL_SUCCESS;
}

RETCODE Statement::cBind(unsigned short n, char * buf, int len)
{
m_BindColumn.Add(n);
m_BindPtr .Add(buf);
m_BindLen .Add(len);
m_BindType .Add(SQL_C_CHAR);

return SQL_SUCCESS;
}

RETCODE Statement::lBind(unsigned short n, long * buf, int len)
{
m_BindColumn.Add(n);
m_BindPtr .Add((char *)buf);
m_BindLen .Add(len);
m_BindType .Add(SQL_C_LONG);

return SQL_SUCCESS;
}

RETCODE GetNext(Statement & hs, int type, char * struct_ptr)
{

RETCODE retcode = AdjustRC(hs.Fetch());
if (retcode != SQL_SUCCESS)
return retcode;

CString str;
COleVariant val;

char * p = struct_ptr;
for (int col = 0; col < TF[type].FCount; col ++)
{
val = hs.m_flds->Item[COleVariant((long)col)]->Value;
str = val.bstrVal;
str.TrimRight();
strcpy(p, str);

p += TF[type].Fields[col].FLength;
}

return retcode;
}
Re[3]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: WindJammer  
Дата: 04.09.01 13:42
Оценка:
Здравствуйте sergey, вы писали:


S>Вот фрагметец ADO-шной реализации класса, который раньше был на ODBC API. Старый печатать не буду — он довольно большой да и вряд ли чем поможет...




Возможно, есть проблемы в том, как вы получаете данные (метод Fetch()).
Почему бы не попробовать ADOBinding для получения данных от рекордсета?

А что у вас за источник данных, в смысле какая БД?
Строка Connection как выглядит?
Re[4]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: sergey  
Дата: 04.09.01 15:07
Оценка:
Здравствуйте WindJammer, вы писали:

WJ>Здравствуйте sergey, вы писали:



S>>Вот фрагметец ADO-шной реализации класса, который раньше был на ODBC API. Старый печатать не буду — он довольно большой да и вряд ли чем поможет...




WJ>Возможно, есть проблемы в том, как вы получаете данные (метод Fetch()).

WJ>Почему бы не попробовать ADOBinding для получения данных от рекордсета?

WJ>А что у вас за источник данных, в смысле какая БД?

WJ>Строка Connection как выглядит?


Это, наверное, правильно про ADOBinding. Спасибо, обязательно попробую. Кстати, если есть кусочек текста, проясняющий работу с этим чудом — пришлите, буду очень признателен.
А БД у меня — SQL Server. Подключался и через ODBC DSN и напрямую — большой разницы в скорости не заметил (на глаз не видно).
Re[5]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: WindJammer  
Дата: 04.09.01 16:35
Оценка:
Здравствуйте sergey, вы писали:

S>Это, наверное, правильно про ADOBinding. Спасибо, обязательно попробую. Кстати, если есть кусочек текста, проясняющий работу с этим чудом — пришлите, буду очень признателен.

S>А БД у меня — SQL Server. Подключался и через ODBC DSN и напрямую — большой разницы в скорости не заметил (на глаз не видно).







Соединение через OLEDBSQL должно быть быстрее ODBC (на глаз получается процентов 20-30)



ADOBinding:
Определить класс рекордсета, типа:


// ODRecordset.h: interface for the CODRecordset class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_ODRECORDSET_H__4B172A5B_D6D2_4CB3_937B_16B80FE62B3F__INCLUDED_)
#define AFX_ODRECORDSET_H__4B172A5B_D6D2_4CB3_937B_16B80FE62B3F__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "icrsint.h"

class CODRecordset : public CADORecordBinding
{
BEGIN_ADO_BINDING(CODRecordset)
ADO_FIXED_LENGTH_ENTRY(1,adInteger,m_lID,m_lIDStatus,false) ADO_VARIABLE_LENGTH_ENTRY2(15,adVarChar,m_szDescribe,sizeof(m_szDescribe),m_lDescribeStatus,true)
ADO_FIXED_LENGTH_ENTRY(16,adInteger,m_lArchiveID,m_lArchiveIDStatus,true)
ADO_FIXED_LENGTH_ENTRY(17,adTinyInt,m_lIsFinish,m_lIsFinishStatus,true)
END_ADO_BINDING()
public:
long m_lID;
ULONG m_lIDStatus;
char* m_szDescribe;
ULONG m_lDescribeStatus;

CODRecordset();
virtual ~CODRecordset();

};

#endif // !defined(AFX_ODRECORDSET_H__4B172A5B_D6D2_4CB3_937B_16B80FE62B3F__INCLUDED_)




Далее перед использованием связать с рекордсетом:

CODRecordset rs;
IADORecordBinding *picRs=NULL;
if (FAILED(rset->QueryInterface(__uuidof(IADORecordBinding), (LPVOID *)&picRs)))
_com_issue_error(E_NOINTERFACE);
picRs->BindToRecordset(&rs);
Re[5]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: Ростислав Глухов Россия http://www.geocities.com/rg2204/
Дата: 05.09.01 05:08
Оценка:
В догонку

Ваш Код:

if (FAILED(m_rs->Open(sql_cmd, m_conn.GetInterfacePtr(),
adOpenDynamic,
adLockOptimistic,
adCmdUnknown)))
return SQL_ERROR;

m_rs->CacheSize = 10; // сейчас в кэше только одна запись, 10 будет после movenext


если только для заполнения структур, то наверное, лучше так

m_rs->CacheSize = 10;


if (FAILED(m_rs->Open(sql_cmd, m_conn.GetInterfacePtr(),
adOpenForwardonly, // этот курсор полегче
adLockOptimistic,
adCmdText))) // или adCmdTable
return SQL_ERROR;
- А Вы что курите?
— Минздрав предупреждает
Re[6]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: sergey  
Дата: 05.09.01 10:47
Оценка:
Огромное спасибо за просвещение (всем кто отвечал) !
Думаю, что теперь почти все ясно.
Я провел замеры скорости на едином примере для:
— ODBC API
— ADO через ODBC
— ADO через SQLOLEDB provider
Получил следующее распределение мест:
1. ADO через SQLOLEDB provider ( 85%)
2. ODBC API ( 90%)
3. ADO через ODBC (100%)

SQLOLEDB без ADO не пробовал — не разобрался еще.

Еще раз спасибо !
Успехов !

P.S.
Все ли хорошо у Вас с работой ?
Re[7]: Заменил ODBC API на ADO - все замедлилось в 10 раз
От: WindJammer  
Дата: 05.09.01 11:54
Оценка:
Здравствуйте sergey, вы писали:


S>P.S.

S>Все ли хорошо у Вас с работой ?

В каком контексте?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.