SQL语句在ODBC中比在T-SQL中慢得多
SQL statement much slower from ODBC than in T-SQL
我有一个C/c++ DLL,它连接到SQL并在循环中快速发出大量ODBC查询。唯一的问题是,从ODBC DLL运行查询比在Management Studio中从T-SQL运行查询要慢得多。慢了很多数量级。
起初我认为这可能是查询本身,但后来我剥离它到一个简单的"选择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秒。在4核Windows 2008 R2服务器上运行SQL 2012 x64.
另一方面,如果我在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;
谁能指出一些我忽略的东西?我的逻辑有缺陷吗?
谢谢。Neil Weicher
www.netlib.com这个注释太长了
declare @sql varchar(128), @repeat int;
set @repeat = 10000;
set @sql = 'select NULL;';
while @repeat > 0 begin
exec(@sql);
set @repeat = @repeat - 1;
end;
并不能真实地模拟10000个远程调用。exec
绕过一个批次的内部建立一个请求。要在SSMS中模拟10000次调用,请执行以下操作:
select NULL;
go 10000
和措施。输出为文本可能应该使用,以避免围绕SSMS网格显示计时。
我不是很熟悉T-SQL的东西,但这里有一些事情需要考虑。
您的ODBC驱动程序必须通过您的网络传输数据,我怀疑T-SQL执行没有。除了磁盘IO之外,在网络上传输数据是ODBC驱动程序必须做的最慢的事情之一。您可能会发现驱动程序花费了相当多的时间等待数据传输或从线路上清除数据。
另外,我不清楚你的T-SQL示例实际上移动和数据,但你的ODBC示例在调用SQLFetch时确实移动和数据。T-SQL可能只是执行查询而不获取任何数据。因此,将SQLFetch从循环中移除可能是一个更公平的比较。
要查看数据传输是否是您的限制因素,请估计使用ODBC获取的所有记录中将包含多少数据,并尝试使用FTP之类的东西在两台机器之间移动这些数据。ODBC驱动程序获取数据的速度永远不会超过简单的原始数据传输。我看到你只是在你的结果集中抓取NULL所以不是很多,但是驱动程序和数据库仍然在它们之间传输数据以服务于此请求。每次执行可能需要几百字节fetch
我也面临同样的问题。我通过将ODBC驱动程序的DSN的"游标默认模式"设置(通过ODBC管理员工具)从"READ_ONLY"更改为"READ_ONLY_STREAMING"来解决它。仅这一点就将我的应用程序(查询数据并将其写入文件)的速度从使用32位Java的260秒提高到51秒,使用c++的从1234秒提高到11秒。请看这篇文章:http://www.etl-tools.com/forum/visual-importer/1587-question-about-data-transformation-memory-usage?start=6
- 为 Sql 服务器实现 odbc 包装器.将数据库数据读取为字符或要求驱动程序将数据转换为 C 类型
- SQL Server 2017 C++ ODBC 连接在 Linux 上不起作用
- SQL 空返回 "stops" 使用 odbc 的 c++ 返回
- C++ ODBC SQL - 插入到表中不起作用
- 通过 ODBC C++将带有日期时间的记录插入 SQL Server 2014 的问题
- MFC 使用 ODBC 连接到 SQL Server
- ODBC 错误"String data, right truncation State code: 22001"与 SQL Server 数据库
- 在C++中通过SOCI/ODBC实现SQL Server存储过程
- 如何在ODBC本机客户端中获取SQL Server DateTime字段
- Poco C++与使用ODBC的MS SQL
- visual C++ ODBC SQL Server 2008 Connection
- 通过ODBC将SQL结果集作为blob返回
- C++SQL ODBC:从表中获取行
- SQL Server-使用C++ODBC调用存储过程
- Poco ODBC and while SQL loop
- SQL语句在ODBC中比在T-SQL中慢得多
- 非常长的查询执行使用c++, Sql Server和ODBC连接
- 如何使用ODBC API读取SQL Server列排序元数据
- SQL Server的批量复制(C API)和ODBC驱动程序
- ODBC连接到sql server数据库c++