We have an application that uses ODBC through CDatabase / CRecordset in MFC (VS2010). We have two backends. MSSQL and MySQL.
Now that we use MSSQL (with Native Client 10.0), retrieving records using SELECT is significantly slower using slow links (like VPN). The MySQL ODBC driver does not exhibit this unpleasant behavior.
For example:
CRecordset r(&m_db); r.Open(CRecordset::snapshot, L"SELECT a.something, b.sthelse FROM TableA AS a LEFT JOIN TableB AS b ON a.ID=b.Ref"); r.MoveFirst(); while(!r.IsEOF()) { // Retrieve CString strData; crs.GetFieldValue(L"a.something", strData); crs.MoveNext(); }
Now, with the MySQL driver, everything works as it should. The request is returned, and everything is lightning fast. However, with the help of the MSSQL native client, the situation slows down, since on each MoveNext () the driver interacts with the server.
I think this is due to server cursors, but I have not found a way to disable them. I tried using:
::SQLSetConnectAttr(m_db.m_hdbc, SQL_ATTR_ODBC_CURSORS, SQL_CUR_USE_ODBC, SQL_IS_INTEGER);
But that didn't help either. SQL Profiler still has a lengthy exec for sp_cursorfetch () and others. I also tried a small help project with SQLAPI and bulk sampling, but it also freezes in FetchNext () for a long time (even if there is only one entry in the result set). However, this only happens with queries with LEFT JOINS, table functions, etc. Please note that the query does not require much time - the execution of the same SQL through SQL Studio via the same connection returns in a reasonable amount of time.
Question1: Is it possible to somehow make the local client localize the local cursor in "cache" locally just as does the MySQL driver?
This may not be the right approach, but I'm not sure how to do it.
All we want is to immediately extract all the data from SELECT, and then never talk to the server until the next query. We do not care about record set updates, deletion, etc. Or any of these nonsense. We only want to get the data. We take this set of records, get all the data and delete it.
Question2: Is there a more efficient way to just get data in MFC using ODBC?