IsolationLevel
交易隔離層級是用來控制「當多個交易同時讀寫資料時,要不要讓他們互相看到對方的變更。要資料「越準確」,就得「越鎖」,要系統「越快」,就得「越鬆」,是在討論競爭條件(Race condition)的議題
💼 READ UNCOMMITTED允許交易去「偷看別人還沒寫完的資料」,這樣雖然速度快,但有風險,因為你讀到的資料可能會「被改回去」或「消失」
不會加共用鎖 (Shared Lock),所以別人正在改資料時,你一樣能讀它。
不會被排他鎖 (Exclusive Lock) 阻擋,所以就算別人正在修改資料、還沒提交,你也能去讀它。
🟢 Shared Lock(共用鎖)是 SQL Server 在「讀資料」時加上的一種鎖,它的作用是我正在看資料,別人在我看完之前不能改它觸發時機:SELECT 查詢(讀資料),可以多個共存 Shared Lock 但會阻擋 Exclusive Lock(別人不能改)
用途:確保你讀的資料在讀取過程中不會被修改
12345BEGIN TRAN;SELECT * FROM Products WHERE Id = 1; -- Shared Lock ...
EFCORE - 關聯載入的海流
潮汐為什麼 Lazy Loading 會造成效能問題?Eager Loading:一次載入所有需要的資料Select 投影(Projection)分段查詢(Split Query)LINQ 查詢中使用 IEnumerable.Contains()非對應類型(Non-Mapped Type)查詢方式的差異Summary這是一份「資料載入的潮汐圖」。我們將從 Lazy 與 Eager 的對比開始,一路探索 N+1 問題的成因、查詢快取的脈動、再航向非對應類型與原生 SQL 的深處…Lazy Loading(延遲載入)是一種「等你真的用到資料時再去撈」的策略
你查出所有英國的客戶(Customers),但還沒看他們的訂單(Orders)。Lazy Loading 的邏輯是:「先不用撈訂單,等你真的要看時再查就好
12var customers = context.Customers.Where(c => c.Country == "UK").ToList();Console.WriteLine(customers.First().Orders.Count);
但實際 ...
Datetime Flow
Flow時間參數化當你對時間欄位動手算,流程就已經反了迴圈實現同一件事反覆發生發現重複運算,其實是在提醒你「邏輯混在一起了」summa所有與時間相關的資料問題,第一步一定是先切出正確的時間工作區,再談任何分析、轉換與計算
在資料查詢與分析中,「流程感」會具體化成這件事 : 先用時間,把資料切成一塊安全、可工作的區間
所以在任何進階操作之前,第一步永遠是時間參數化(所有後續的地基),因此在做下面任何事情之前
格式轉換(YEAR / MONTH / CONVERT / 字串化)
計算邏輯(DATEDIFF、CASE、狀態判斷)
資料聚合(GROUP BY、AVG、SUM)
我們都應該先完成一件事,用「可走索引的時間區間參數」把資料切出來。而這三類操作有一個共通點,它們都會降低索引的價值,甚至直接讓索引失效,因此正確順序不是我要算月報 → GROUP BY MONTH → 再來想效能,而是先用時間縮小資料範圍 → 再隨便你怎麼算任何進階分析、轉換、統計之前,第一件事永遠是:先用「可走索引的時間區間參數」把資料切出一塊安全的工作區
格式轉換(YEAR ...
SQL - 文字列の森
💼 最長欄位SQL Server 在執行 ORDER BY LEN(Video_Introduction) 時,必須對每一筆資料都算一次長度,然後再排序
12345USE InfoDB;SELECT TOP 1 LEN(Video_Introduction),Video_IntroductionFROM Video(NOLOCK)ORDER BY LEN(Video_Introduction) DESC
若僅僅想知道最長,不需要排序!
1SELECT MAX(LEN(Video_Introduction)) FROM Video (NOLOCK);
💼 LIKE ‘%xxx%’ 效能差?索引是一種「字典排序的結構(B-tree)」,想像成一本電話簿(索引)
🔹 有開頭字串的 LIKE你可以很快找到「開頭是 09」的電話,但如果你說「我要找結尾是 1234」的電話,電話簿就得一筆筆翻完才知道
📘 索引是有方向的(從左到右),開頭沒固定的查詢無法用索引來加速
執行策略
說明
效能
Index Seek
透過索引直接找到目標資料列
🚀 快
I ...
Implicit Conversion & Explicit Conversion
關於婚姻與育兒...Implicit ConversionExplicit Conversion先轉型好再 JOIN(避免在 JOIN 內 CAST)誤用 cfn拆出 GroupBy 案例summary生小孩後的夫妻,就像兩個本來型別不同的欄位,一個是「我覺得應該這樣做」的 string,一個是「我以為你希望我這樣做」的 bigint,兩人的期待、習慣、壓力都不一致,但因為忙、因為累、因為怕吵架,沒人敢明確地把自己的需求「顯式轉型」說出來,於是關係裡就開始出現「隱式轉換」
「算了,我先做吧,不然會更麻煩。」
…
「我應該能撐一下,他今天也很累。」
…
「這沒什麼啦,我忍一下就過了。」
看似體貼,能運作,但表面好看,內裡不對等
累 → 生氣生氣 → 委屈委屈 → 無聲無聲 → 彼此以為「沒事」
需要轉型本身並沒有錯誤,資料的來源、格式、責任歸屬、生命周期都跨越多個系統與團隊,此時資料庫遇到 JOIN 或比較時,就會產生轉換需求,重要的是要能有溝通的認知,預防性做好準備
當兩個不同型別的值需要比較時,資料庫必須強制把它們變成「同一種型別」,而這個自動決定的型別若不夠精確,就會導致邏輯錯誤
...
Nested Loop Join & Merge Join & Hash Join
戀愛類型Nested Loop JoinMerge JoinHash Join引擎怎麼做選擇你是什麼樣的戀愛類型呢?
毛吉是那種聞到喜歡的味道就會湊上去確認的類型,因為她他有一開始就設定好標準,只能靠一次次互動中慢慢觀察、逐一比對。透過 Nested Loop 聞到喜歡的屁股就 Join 下去,通常吃幾個巴掌
阿冠比較理性,屬於先驗條件獵人型。他會先用一套邏輯,把自己「Hash」好,然後就靠這組標準去掃描目標對象。這就是 Hash Join,直接把效率拉到極致
最理想的狀況,當然是兩個人都已經「排序」好自己,生活節奏對齊,價值觀同步,見面時幾乎不需要猜測,搭上就能對得很漂亮,就是 Merge Join「外層每一筆資料,都去內層找一筆相對應的資料」,效率完全取決於內層查找是否能快速定位
有兩份名單
Outer Table:10 個學生名字
Inner Table:100 萬筆成績紀錄
要做的事是
「拿出第一個學生 → 去成績表查他的資料」「再拿第二個學生 → 去查他的資料」………
➡️ 所以整個流程非常直覺,有點像是「外層迴圈包內層查詢」
內表能不能快速查到資料?Nested L ...
SQL - Store Procedure
OFFSET 與 FETCH:分頁查詢(Paging)1234567891011-- 第 1 頁:顯示第 1~10 筆SELECT * FROM EmployeesORDER BY EmployeeIDOFFSET 0 ROWSFETCH NEXT 10 ROWS ONLY;-- 第 2 頁:顯示第 11~20 筆SELECT * FROM EmployeesORDER BY EmployeeIDOFFSET 10 ROWSFETCH NEXT 10 ROWS ONLY;
👉 可以想成像 Netflix:「往右滑 10 部影片,再顯示接下來的 10 部。」
在交易中進行分頁 (Paging with Transaction)12345678910111213141516171819SET TRANSACTION ISOLATION LEVEL SNAPSHOT;BEGIN TRANSACTION;DECLARE @StartingRowNumber INT = 1, @RowCountPerPage INT = 3;WHILE (SELECT COUNT(*) F ...
SQL - Store Procedure
盒鬚圖(Box Plot,又稱箱型圖)
TempTable
#temp(Local Temporary Table)##temp(Global Temporary Table)TVP (Table-Valued Parameters)#temp 的本質,是把「一次查不完、邏輯又複雜的中間結果」變成一個可以被優化、重用、逐步加工的暫存資料集,讓 SQL Optimizer 有機會幫你把事情做對
建立與隔離:在 tempdb 中開闢一塊專屬空間,僅限當前連線(Session)存取,確保資料不會跟別人的請求打架
資料灌入:利用 SELECT INTO 或 INSERT INTO 將中間運算結果存入
優化加速:視需求針對 #temp 建立索引(Index),這在處理萬筆以上資料時非常關
多次加工:在同一個連線內,後續的 Stored Procedure 或 SQL 指令可以反覆讀取、更新這份暫存資料。
生命週期終結:當連線關閉時自動銷毀,保持資料庫環境整潔
1234CREATE TABLE #TEMP( NAME CHAR(20), ID CHAR(10))
電商雙 11 促銷結帳想像我們要幫上萬名會員計算購物車折扣
第一步:先撈 ...
在夜裡奔跑的資料,不需要回頭 JOIN
夜に駆ける先別急著 GROUP BYWindow Rank《夜に駆ける》- 不是回頭統計「哪一天最痛」,而是在情緒奔跑的過程中,痛苦自然浮到最前面
MAX + JOIN 的人生像在事後寫失戀報告,假設你用 MAX + GROUP BY + JOIN 來寫這首歌,列出所有相處的日子、快樂指數、痛苦指數、聊天次數,GROUP BY「每一天」並算出「痛苦指數 MAX 的那一天」再回頭 JOIN 那一天的對話、場景、畫面最後下結論「原來是那一天最痛。」
痛苦 = MAX
回憶 = JOIN
情緒 = 被拆成資料再拼回來
這會寫成一篇 Excel 報告,不會是一首歌
而 Window Function 實際在做的是,情緒一路推進,畫面一路疊加,痛苦不斷「排序往前」
「我在跑的時候,就知道逃不掉。」
1234ROW_NUMBER() OVER ( PARTITION BY 這段關係 ORDER BY 情緒崩壞程度 DESC)
MAX => GROUPBY12345678SELECT o.*FROM Orders oJOIN ( SEL ...







