【发布时间】:2016-02-19 02:12:36
【问题描述】:
我有一个 C/C++ DLL,它连接到 SQL 并在循环中快速发出大量 ODBC 查询。唯一的问题是,使用 ODBC DLL 比在 Management Studio 中从 T-SQL 运行查询要慢得多。慢很多数量级。
起初我以为这可能是查询本身,但后来我将其简化为一个简单的“select NULL”,仍然得到相同的结果。
我想知道这是否是预期的,或者是否有一些我丢失或出错的 ODBC 设置?
首先我像这样连接(为简洁起见,我省略了所有错误检查,但是,retcode 在所有情况下都返回 SQL_SUCCESS):
char *connString = "Driver={SQL Server};Server=.\\ENT2012;uid=myuser;pwd=mypwd";
...
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_UINTEGER);
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (void*)5, 0);
retcode = SQLDriverConnect(
hdbc,
0,
(SQLTCHAR*) connString,
SQL_NTS,
connStringOut,
MAX_PATH,
(SQLSMALLINT*)&connLen,
SQL_DRIVER_COMPLETE);
然后我准备语句,绑定一个参数(在本例中未使用),并像这样绑定一个列:
char queryString = "select NULL;";
SQLLEN g_int32 = 4;
SQLLEN bytesRead = 0;
...
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt)
retcode = SQLPrepare(hstmt, queryString, SQL_NTS);
retcode = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT,
SQL_C_LONG, SQL_INTEGER, sizeof(int), 0, spid, 0, (SQLLEN*)&g_int32))
retcode = SQLBindCol(hstmt, 1, SQL_C_CHAR, col_1, 32, &bytesRead);
最后,我在这样的循环中重复调用查询(例如,10000 次):
retcode = SQLExecute(hstmt);
retcode = SQLFetch(hstmt);
SQLCloseCursor(hstmt);
在 ODBC DLL 中运行 10000 次大约需要 90 秒。在运行 SQL 2012 x64 的 4 核 Windows 2008 R2 Server 上进行测试。
另一方面,如果我在 Management Studio 中运行,在我看来是一个等效的测试,它只需要不到一秒钟的时间:
declare @sql varchar(128), @repeat int;
set @repeat = 10000;
set @sql = 'select NULL;';
while @repeat > 0 begin
exec(@sql);
set @repeat = @repeat - 1;
end;
有人能指出我忽略的东西吗?我的逻辑有问题?
谢谢。
尼尔·韦彻
【问题讨论】:
-
你的循环是包含连接还是只包含执行?
-
在上下文中,您正在测量使用 ODBC 的 C++ DLL 大约 9 毫秒的开销——几个额外的代码层。这并不必然看起来不合理,尽管我希望会更小一些。这个问题可能更适合 dba.stackexchange.com。
-
@RemusRusanu - 循环只包括执行。连接和准备在开始时完成一次。
-
@GordonLinoff - 你会建议我删除问题并将其移到那里吗?
-
顺便说一句 - Driver={SQL Server} 的选择与它有什么关系吗?
标签: c++ sql sql-server performance odbc