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

SQL 語句效能優化進階:COUNT(*) vs MAX(id) 實測與資料型別對效能的影響分析

     編輯:關於SqlServer

上篇比較 `SELECT COUNT(*)` 與 `SELECT *` 效能,讀者建議補測 `MAX(id)` 取得最大流水號。本文實測發現:相同資料表、不同欄位、不同資料型別下,`MAX()` 效能差異極大,揭示資料型別與索引特性對聚合函數效能的決定性影響。

測試環境

  • 資料表 `T_BasicInformation`、`t_SellLogDetail` (含百萬筆測試資料)。
  • 使用 `DATEDIFF(ms, @start, GETDATE())` 量測毫秒級耗時。

第一輪測試:T_BasicInformation 表

DECLARE @d DATETIME = GETDATE();
SELECT MAX(num) FROM T_BasicInformation;
SELECT DATEDIFF(ms, @d, GETDATE()) AS [耗時ms];

結果: ~20 ms (慢於預期的 `COUNT(*)` ~3 ms)。

第一輪測試結果

第二輪測試:t_SellLogDetail 表 (同表不同欄位)

查詢欄位定義耗時執行計畫特徵
MAX(id)PK, INT, IDENTITY0 msStream Aggregate + Index Seek (極速)
MAX(foodId)INT, 非 PK, 有非叢集索引~15 msIndex Scan + Stream Aggregate
MAX(orderId)VARCHAR(50), 無索引~120 msTable Scan + Stream Aggregate

MAX(id) 0ms

MAX(foodId) 15ms

MAX(orderId) 120ms

欄位資料型別與索引定義

核心發現

  1. 主鍵 + 整數型別 (INT/BIGINT) + IDENTITY:`MAX()` 極速 (0~1 ms),優化器直接讀取 B-tree 邊界頁。
  2. 非主鍵整數 + 有索引:需掃描索引葉層,耗時隨索引大小線性增長。
  3. 字串型別 (VARCHAR/NVARCHAR) 無索引:全表掃描,轉換比較開銷大,最慢。
  4. COUNT(*) vs MAX(PK):`COUNT(*)` 需掃描所有列 (或叢集索引葉層) 計數;`MAX(PK)` 僅讀取最右葉頁,**單筆流水號取得場景 `MAX(PK)` 完勝**。

實務建議

  • 需取得「下一個流水號」:使用 `MAX(PK_IDENTITY)` + 1 (單用戶/低併發) 或 `SEQUENCE` / `IDENTITY` 機制 (高併發)。
  • 統計總筆數:`COUNT(*)` 配合觸發器維護計數表、或 `sys.dm_db_partition_stats` 近似值 (大表)。
  • 聚合查詢優化優先順序:建立適當索引 > 選擇高優先級資料型別 (INT > VARCHAR) > 改寫查詢。
  • 測試必須在目標表、真實資料量、真實索引下進行,勿憑直覺或單一表測試推論全域。

效能優化無銀彈,唯有「理解引擎機制 + 實測驗證 + 持續觀測」才能做出正確選擇。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved