首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> SQL Server 資料庫 >> 關於SqlServer

ADO 連接 SQL Server 避免隱式連接導致效能損耗

     編輯:關於SqlServer

使用 ADO (ActiveX Data Objects) 連接 SQL Server 時,若以 Connection.Execute 方法直接將結果集指派給 Recordset 變數,會觸發隱式連接:每次執行 SQL 陳述式都會在背景建立新的實體連接,嚴重影響效能與連接池複用。

問題重現

Dim cnn As New ADODB.Connection
Dim rs As New ADODB.Recordset

cnn.Open "Provider=SQLOLEDB.1;Data Source=svr;Initial Catalog=freemail;User ID=sa;..."

sql = "SELECT * FROM users"
Set rs = cnn.Execute(sql)   ' 第一次:建立連接 1
Set rs = cnn.Execute(sql)   ' 第二次:建立連接 2 (隱式)
Set rs = cnn.Execute(sql)   ' 第三次:建立連接 3 (隱式)

SQL Server Profiler 會顯示每次 Execute 前都出現 Audit Login 事件,代表建立新連接。且這些隱式連接不會進入連接池,執行完畢即銷毀,極度浪費資源。

根本原因

SQLOLEDB Provider 預設使用 Forward-Only, Read-Only 游標(預設游標類型)。當程式碼將 `Execute` 回傳的 Recordset 指派給變數時,Provider 為了支援同一連接上多個待處理結果集,會自動建立第二個實體連接。此行為由 DBPROP_MULTIPLECONNECTIONS 屬性控制,預設為 True。

參考 Microsoft KB 文件:PRB: Implicit Connections Created by the SQL Server OLE DB Provider (SQLOLEDB) Are Not Pooled

解決方案:指定游標類型

在開啟 Recordset 前明確設定 CursorType 為非預設類型(如 adOpenStatic、adOpenKeyset、adOpenDynamic),即可避免隱式連接:

Dim cn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim rs2 As New ADODB.Recordset

cn.Open "Provider=SQLOLEDB.1;Data Source=svr;Initial Catalog=freemail;User ID=sa;..."

' 正確做法:設定游標類型再開啟
rs.CursorType = adOpenStatic
rs.ActiveConnection = cn
rs.Open "SELECT * FROM users"

rs2.CursorType = adOpenStatic
rs2.ActiveConnection = cn
rs2.Open "SELECT * FROM users"
' 同一連接 cn 可重複使用,無隱式連接產生

游標類型選擇指南

CursorType特性適用場景
adOpenForwardOnly (預設)唯讀、僅能向前捲動、效能最佳單向讀取大量資料、報表產生
adOpenStatic靜態複本、可捲動、不反映他人變更需隨機存取、資料量中等、離線操作
adOpenKeyset鍵集游標、可捲動、反映資料變更、不見新增列需即時看到更新/刪除、中大型資料集
adOpenDynamic動態游標、完整反映所有變更、成本最高高併發環境需即時一致性、小資料集

最佳實務建議

  • 預設情況:若無需捲動或離線操作,維持 adOpenForwardOnly 效能最好,但務必在同一時間只保留一個作用中 Recordset,或在下一次 Execute 前明確 rs.Close。
  • 需多個同時開啟 Recordset:改用 adOpenStatic 並指派 ActiveConnection。
  • 現代開發:建議改用 ADO.NET (SqlClient),SqlDataReader 為前向唯讀,DataAdapter.Fill(DataTable) 自動管理連接池,完全避免此問題。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved