分析 ODBC 驅動程式效能資料 - 記錄長時間執行的查詢
適用於: SQL Server Azure SQL 資料庫 Azure SQL 受控執行個體 Azure Synapse Analytics Analytics Platform System (PDW)
此範例顯示記錄長時間執行查詢的 SQL Server ODBC 驅動程式特定選項。 執行時,此範例會建立 Odbcqry.log,其中包含執行超過應用程式所設定間隔的查詢清單。 IA64 不支援此範例。 此範例是針對 ODBC 3.0 版或更新版本所開發。
重要
盡可能使用 Windows 驗證。 如果無法使用 Windows 驗證,請提示使用者在執行階段輸入認證。 請避免將認證儲存在檔案中。 如果您必須保存認證,則應該用 Win32 crypto API 加密這些認證。
使用 ODBC 系統管理員記錄長時間執行的查詢
在 控制台 中,按兩下 [系統管理工具],然後按兩下 [資料源] [ODBC]。 (或者,您可以從命令提示字元執行odbcad32.exe。
按兩下 [ 使用者 DSN]、 [系統 DSN] 或 [檔案 DSN ] 索引標籤。
按兩下要記錄長時間執行查詢的數據來源。
按一下 [設定] 。
在 [Microsoft SQL Server 設定 DSN 精靈] 中,流覽至頁面,並將 長時間執行的查詢儲存至記錄檔。
選取 [ 將長時間執行的查詢儲存至記錄檔]。 在方塊中,放置應該記錄長時間執行查詢的檔名。 或者,按下 [ 瀏覽 ] 以瀏覽查詢記錄檔的檔案系統。
在 [長查詢時間(毫秒)] 方塊中,以毫秒為單位設定查詢逾時間隔。
以程式設計方式記錄長時間執行的查詢數據
使用 SQL_COPT_SS_PERF_QUERY_LOG呼叫 SQLSetConnectAttr ,以及長時間執行查詢記錄檔的完整路徑和檔名。 例如:
C:\\Odbcqry.log
使用 SQL_COPT_SS_PERF_QUERY_INTERVAL呼叫 SQLSetConnectAttr ,並以毫秒為單位設定為超時時間間隔。
使用 SQL_COPT_SS_PERF_QUERY 和 SQL_PERF_START 呼叫 SQLSetConnectAttr ,以開始記錄長時間執行的查詢。
使用 SQL_COPT_SS_PERF_QUERY 和 SQL_PERF_STOP 呼叫 SQLSetConnectAttr ,以停止記錄長時間執行的查詢。
範例
您將需要名為 AdventureWorks 的 ODBC 數據源,其預設資料庫是 AdventureWorks 範例資料庫。 (您可以從 下載 AdventureWorks 範例資料庫 Microsoft SQL Server 範例和社群專案 首頁。)此數據源必須以操作系統提供的 ODBC 驅動程式為基礎(驅動程式名稱為 “SQL Server” )。 如果您要在 64 位作業系統上建置並執行此範例做為 32 位應用程式,您必須在 %windir%\SysWOW64\odbcad32.exe 中使用 ODBC 系統管理員建立 ODBC 數據源。
此範例會連線到計算機的預設 SQL Server 實例。 若要連線到具名實例,請變更 ODBC 數據源的定義,以使用下列格式指定實例:server\namedinstance。 根據預設,SQL Server Express 會安裝至具名執行個體。
使用 odbc32.lib 編譯。
// compile with: odbc32.lib
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <sql.h>
#include <sqlext.h>
#include <odbcss.h>
SQLHENV henv = SQL_NULL_HENV;
SQLHDBC hdbc1 = SQL_NULL_HDBC;
SQLHSTMT hstmt1 = SQL_NULL_HSTMT;
void Cleanup() {
if (hstmt1 != SQL_NULL_HSTMT)
SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
if (hdbc1 != SQL_NULL_HDBC) {
SQLDisconnect(hdbc1);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
}
if (henv != SQL_NULL_HENV)
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
int main() {
RETCODE retcode;
// Allocate the ODBC environment and save handle.
retcode = SQLAllocHandle (SQL_HANDLE_ENV, NULL, &henv);
if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
printf("SQLAllocHandle(Env) Failed\n\n");
Cleanup();
return(9);
}
// Notify ODBC that this is an ODBC 3.0 app.
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER) SQL_OV_ODBC3, SQL_IS_INTEGER);
if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
printf("SQLSetEnvAttr(ODBC version) Failed\n\n");
Cleanup();
return(9);
}
// Allocate ODBC connection handle and connect.
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc1);
if ( (retcode != SQL_SUCCESS_WITH_INFO) && (retcode != SQL_SUCCESS)) {
printf("SQLAllocHandle(hdbc1) Failed\n\n");
Cleanup();
return(9);
}
// sample uses Integrated Security, create SQL Server DSN using the Windows NT authentication.
retcode = SQLConnect(hdbc1, (UCHAR*)"AdventureWorks", SQL_NTS, (UCHAR*)"",SQL_NTS, (UCHAR*)"", SQL_NTS);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLConnect() Failed\n\n");
Cleanup();
return(9);
}
// Set options to log long-running queries, including the file to use for the log.
retcode = SQLSetConnectAttr( hdbc1, SQL_COPT_SS_PERF_QUERY_LOG, &"odbcqry.log", SQL_NTS);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLSetConnectAttr Failed\n\n");
Cleanup();
return(9);
}
// Set the long-running query interval (in milliseconds). Note that for version 2.50 and 2.65
// drivers, this value is specified in seconds, not milliseconds.
retcode =
SQLSetConnectAttr( hdbc1, SQL_COPT_SS_PERF_QUERY_INTERVAL, (SQLPOINTER)3000, SQL_IS_UINTEGER);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLSetConnectAttr Failed\n\n");
Cleanup();
return(9);
}
// Start the long-running query log.
retcode =
SQLSetConnectAttr( hdbc1, SQL_COPT_SS_PERF_QUERY, (SQLPOINTER)SQL_PERF_START, SQL_IS_UINTEGER);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLSetConnectAttr Failed\n\n");
Cleanup();
return(9);
}
// Allocate statement handle then execute commands.
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc1, &hstmt1);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLAllocHandle(hstmt1) Failed\n\n");
Cleanup();
return(9);
}
retcode = SQLExecDirect(hstmt1, (UCHAR*)"SELECT * FROM Purchasing.Vendor", SQL_NTS);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLExecDirect Failed\n\n");
Cleanup();
return(9);
}
// Clear any result sets generated.
while ( ( retcode = SQLMoreResults(hstmt1) ) != SQL_NO_DATA ) {
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLMoreResults Failed\n\n");
Cleanup();
return(9);
}
}
retcode = SQLExecDirect(hstmt1, (UCHAR*)"SELECT * FROM Sales.Store", SQL_NTS);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLExecDirect Failed\n\n");
Cleanup();
return(9);
}
// Clear any result sets generated.
while ( ( retcode = SQLMoreResults(hstmt1) ) != SQL_NO_DATA ) {
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLMoreResults Failed\n\n");
Cleanup();
return(9);
}
}
// Generate a long-running query.
retcode = SQLExecDirect(hstmt1, (UCHAR*)"waitfor delay '00:00:04' ", SQL_NTS);
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLExecDirect Failed\n\n");
Cleanup();
return(9);
}
// Clear any result sets generated.
while ( ( retcode = SQLMoreResults(hstmt1) ) != SQL_NO_DATA ) {
if ( (retcode != SQL_SUCCESS) && (retcode != SQL_SUCCESS_WITH_INFO) ) {
printf("SQLMoreResults Failed\n\n");
Cleanup();
return(9);
}
}
// Cleanup
SQLFreeHandle(SQL_HANDLE_STMT, hstmt1);
SQLDisconnect(hdbc1);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc1);
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}