在高效雲平台學生基礎系統重構中,將原本分散在 Service 層的多表 JOIN 查詢下沉到數據庫視圖,實現了「一次定義、多處復用、業務解耷」的架構優化。本文記錄從 ER 關係分析到視圖創建、應用層調用簡化的完整過程。
以 BasicStudentEntities 為主表(駕駛表),關聯表均用 LEFT OUTER JOIN。確保即使關聯數據缺失(如學生未分配宿舍),學生主記錄依然查得出來,避免內連接導致數據「神秘消失」。
CREATE VIEW V_Student_Full_Info AS
SELECT
s.StudentID, s.StudentNo, s.Name, s.UserCode, s.EntryTime, s.Origin,
s.EntryPartyTime, s.Speciality, s.HealthCondition, s.ExamineeNumber,
s.FatherName, s.MotherName, s.FatherPhone, s.MotherPhone,
s.TrainDestination, s.Note, s.Status, s.Operator, s.TimeStamp,
s.CreditCardNo, s.Sex, s.PoliticalStatus, s.PreviousName, s.Email,
s.CellPhoneNumber, s.HomeTelephone, s.BirthPlace, s.HomeAddress,
s.Nation, s.RoomID, s.DirectionID, s.ClassID, s.IsEnabled, s.Image,
c.ClassCode, c.ClassName,
o.OrganizationName, o.OrganizationID,
sl.LevelName,
r.RoomName,
d.DirectionID, d.DirectionName, d.DirectionCode
FROM dbo.BasicStudentEntities s
LEFT OUTER JOIN dbo.BasicDirectionEntities d ON s.DirectionID = d.DirectionID
LEFT OUTER JOIN dbo.BasicClassEntities c ON s.ClassID = c.ClassID
LEFT OUTER JOIN dbo.BasicRoomEntities r ON s.RoomID = r.RoomID
LEFT OUTER JOIN dbo.BasicOrganizationEntities o ON c.OrganizationID = o.OrganizationID
LEFT OUTER JOIN dbo.BasicSchoolLevelEntities sl ON o.SchoolLevelID = sl.SchoolLevelID;
| 維度 | 2.0 版本 | 3.0 版本 (視圖) |
|---|---|---|
| 查詢代碼 | EF 導航屬性 / 手寫 LINQ JOIN 5+ 表 | ctx.V_Student_Full_Info.Where(...) 單表查詢 |
| SQL 生成 | 複雜嵌套子查詢、參數嗅探問題 | 簡單單表掃描/索引查找,優化器易生成最優計劃 |
| 維護成本 | 修改關係需改多處 Service 代碼 | 修改視圖定義,業務代碼零變動 |
| 權限控制 | 表級權限粗放 | 視圖級 GRANT SELECT,列級掩碼(如隱藏身份證號) |
| 統計信息 | 依賴底表統計 | 可單獨創建視圖統計/索引視圖 (物化視圖) |
若查詢極高頻且數據變更相對較少(如報表查詢),可考慮:
CREATE UNIQUE CLUSTERED INDEX idx_v_stu ON V_Student_Full_Info(StudentID),將視圖物化存儲,查詢直接掃描索引,極大提升報表性能。CREATE MATERIALIZED VIEW mv_stu_full REFRESH FAST ON COMMIT AS ...,配合查詢重寫。視圖不僅是「預定義的查詢」,更是**數據庫層面的 API 門面**。將複雜的多表關聯、業務邏輯(如軟刪除過濾 IsEnabled=1、脫敏規則)封裝在視圖內,應用層只見「乾淨、穩定、單一」的實體。此次重構將 200+ 行分散的 JOIN 代碼壓縮為 1 個視圖 + 1 行調用,**核心不在於技術難度,在於「不將就」的工程師思維:主動識別重復、主動下沉邏輯、主動為後人鋪路。**