需求:使用者輸入關鍵字「x」,搜尋使用者姓名(含中英文),結果排序規則:
| 版本 | 核心技術 | 估計成本 | 實測耗時 | 關鍵缺點 |
|---|---|---|---|---|
| v1 | 暫存表 #result + 多次 INSERT + ORDER BY + 函數內部 TABLE 變數 + WHILE 迴圈 + 排序 |
0.0246 | 20+ 秒 | 大量暫存表插入、排序、函數逐字掃描表變數 |
| v2 | 單一函數,利用 COLLATE Chinese_PRC_CI_AS 排序 27 筆基準字,取 ASCII 位置轉字母 |
0.0116 | 10+ 秒 | 每字仍需排序 27 列,CPU 密集 |
| v3 | 將 v1 的表變數改為實體資料表 + 叢集索引 | 0.003 | 4-5 秒 | 仍有索引搜尋開銷 |
| v4 | 純 CASE WHEN 區間判斷,移除所有查詢/排序 | 0 | 1-2 秒 | 程式碼較長但極快 |
| v5 | v4 優化:由大到小排序 CASE WHEN,命中率高的優先判斷 | 0 | 0-1 秒 | 最佳平衡:零 I/O、零排序、CPU 極低 |
CREATE FUNCTION [dbo].[fn_getpy5](@str NVARCHAR(4000))
RETURNS NVARCHAR(4000)
AS
BEGIN
DECLARE @str_len INT = LEN(@str),
@result NVARCHAR(4000) = N'',
@crs NVARCHAR(1);
WHILE @str_len > 0
BEGIN
SET @crs = SUBSTRING(@str, @str_len, 1);
SELECT @str_len = @str_len - 1,
@result = CASE
WHEN @crs >= N'帀' THEN N'Z'
WHEN @crs >= N'丫' THEN N'Y'
WHEN @crs >= N'夕' THEN N'X'
WHEN @crs >= N'屲' THEN N'W'
WHEN @crs >= N'他' THEN N'T'
WHEN @crs >= N'仨' THEN N'S'
WHEN @crs >= N'呥' THEN N'R'
WHEN @crs >= N'七' THEN N'Q'
WHEN @crs >= N'妑' THEN N'P'
WHEN @crs >= N'噢' THEN N'O'
WHEN @crs >= N'拏' THEN N'N'
WHEN @crs >= N'嘸' THEN N'M'
WHEN @crs >= N'垃' THEN N'L'
WHEN @crs >= N'咔' THEN N'K'
WHEN @crs >= N'丌' THEN N'J'
WHEN @crs >= N'铪' THEN N'H'
WHEN @crs >= N'旮' THEN N'G'
WHEN @crs >= N'發' THEN N'F'
WHEN @crs >= N'妸' THEN N'E'
WHEN @crs >= N'咑' THEN N'D'
WHEN @crs >= N'嚓' THEN N'C'
WHEN @crs >= N'八' THEN N'B'
WHEN @crs >= N'吖' THEN N'A'
ELSE @crs
END + @result;
END
RETURN @result;
END
ORDER BY、ROW_NUMBER、TOP 1 ... ORDER BY 皆帶來 O(N log N) 開銷。DECLARE @kw NVARCHAR(50) = N'x';
WITH cte AS (
SELECT name,
CASE
WHEN name LIKE @kw + N'%' THEN 1
WHEN name LIKE N'%' + @kw + N'%' THEN 2
WHEN dbo.fn_getpy5(name) LIKE @kw + N'%' THEN 3
WHEN dbo.fn_getpy5(name) LIKE N'%' + @kw + N'%' THEN 4
ELSE 5
END AS ord,
LEN(name) AS ln
FROM zhuisuos
)
SELECT name
FROM cte
WHERE ord <= 4
ORDER BY ord, ln;
從 20 秒到 0.5 秒,不靠更強硬體,而是回歸簡單:移除不必要的物件、排序、迴圈,用最直觀的邏輯讓 CPU 直接跑完。優化的盡頭,往往是最樸素的代碼。