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

SQL Server 2005+ CLR 使用者定義型別 (UDT) 實戰:將查閱表載入記憶體加速 JOIN 查詢

     編輯:關於SqlServer

情境

Table1 (500 萬列) 需依 Col1, Col2 關聯 Table2 (4 萬列) 取得 Col3。Table2 為靜態查閱表,更新極少。傳統 JOIN 即使有索引,仍需重複 B-Tree 搜尋,CPU/IO 成本高。

優化演進

方案做法耗時 (500萬 × 4萬)
1. 獨立索引Col1、Col2 各建非叢集索引106 秒
2. 複合索引(Col1, Col2) 複合索引—
3. 包含索引(Col1, Col2) INCLUDE (Col3)45 秒
4. CLR UDT 記憶體快取啟動時將 Table2 全量載入 static Dictionary33 秒

CLR 實作核心碼 (C#)

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using System.Collections.Generic;

public partial class UserDefinedFunctions
{
    // 靜態字典:Key = "Col1+Col2",Value = Col3
    private static readonly Dictionary Cache = new Dictionary();

    // 靜態建構式:SQL Server 服務啟動時自動執行一次
    static UserDefinedFunctions()
    {
        LoadCache();
    }

    private static void LoadCache()
    {
        using (var conn = new SqlConnection("context connection=true"))
        using (var cmd = new SqlCommand("SELECT Col1, Col2, Col3 FROM dbo.LookupTable ORDER BY Col1, Col2", conn))
        {
            conn.Open();
            using (var rd = cmd.ExecuteReader())
            {
                while (rd.Read())
                {
                    string key = rd.GetString(0) + "+" + rd.GetString(1);
                    if (!Cache.ContainsKey(key))
                        Cache.Add(key, rd.GetString(2));
                }
            }
        }
    }

    [SqlFunction(DataAccess = DataAccessKind.Read)]
    public static SqlString LookupValue(string col1, string col2)
    {
        string key = col1 + "+" + col2;
        string val;
        return Cache.TryGetValue(key, out val) ? new SqlString(val) : SqlString.Null;
    }
}

部署步驟

  1. VS 建立 SQL Server Database Project,加入上述類別
  2. 專案屬性 → Database → 目標框架 .NET 3.5、權限 SAFE
  3. 建置 → 在 SSMS 執行產生的 CREATE ASSEMBLY / CREATE FUNCTION 腳本
  4. 啟用 CLR:EXEC sp_configure 'clr enabled', 1; RECONFIGURE

呼叫方式對比

-- 傳統 JOIN (包含索引)
SELECT @rc = Col3 FROM LookupTable WHERE Col1 = @val1 AND Col2 = @val2

-- CLR 函數
SELECT @rc = dbo.LookupValue(@val1, @val2)

優缺點總結

優點缺點/限制
記憶體 O(1) 查找,效能最佳Table2 更新需重新部署組件或重啟服務
封裝複雜邏輯 (字串處理、加密等)Key 衝突風險:Col1+Col2 必須唯一,否則需改用 List/實體
程式碼加密,提高安全性部署/維護成本較高 (需 VS、DLL 管理)

解決更新問題

  • 在 LookupTable 建立 AFTER INSERT/UPDATE/DELETE TRIGGER,呼叫 sp_refreshsqlmodule 重新載入組件 (或重啟服務)
  • 或改用 Memory-Optimized Table (SQL 2014+) 原生支援記憶體優化
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved