隨機抽樣:TABLESAMPLE vs NEWID()
-- 方法 1: NEWID() 全表排序 (精確隨機、大表極慢)
SELECT TOP 5 *
FROM Person.Address
ORDER BY NEWID();
-- 方法 2: TABLESAMPLE (頁級採樣、極快、非嚴格隨機)
SELECT *
FROM Person.Address
TABLESAMPLE (10 PERCENT) -- 或 (100 ROWS)
REPEATABLE (42); -- 固定種子可復現
分頁查詢:OFFSET/FETCH (SQL 2012+) vs ROW_NUMBER()
-- 標準語法 (SQL 2012+ 推薦)
SELECT *
FROM Person.Address
ORDER BY City
OFFSET 49 ROWS FETCH NEXT 151 ROWS ONLY; -- 第 50-200 行
-- 兼容寫法 (SQL 2005/2008/R2)
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY City) AS RowNum
FROM Person.Address
) AS t
WHERE t.RowNum BETWEEN 50 AND 200;
性能對比與選擇指南
| 場景 | 推薦方案 | 理由 |
| 小表 (<1萬行) 隨機抽樣 | ORDER BY NEWID() | 簡單精確 |
| 大表 隨機抽樣 | TABLESAMPLE / BERNOULLI | 避免全表排序 |
| 分頁查詢 (SQL 2012+) | OFFSET/FETCH | 語法清晰、優化器友好 |
| 分頁查詢 (舊版本) | ROW_NUMBER() CTE | 標準兼容 |
| 深分頁 (第 10萬頁) | Keyset Pagination (Seek 法) | 避免掃描大量前置行 |
Keyset Pagination (游標分頁) 高性能模式
-- 首頁
SELECT TOP 50 * FROM Person.Address ORDER BY City, AddressID;
-- 後續頁 (記住上一頁最後一行的排序鍵值)
DECLARE @LastCity NVARCHAR(30) = '...', @LastID INT = ...;
SELECT TOP 50 *
FROM Person.Address
WHERE City > @LastCity OR (City = @LastCity AND AddressID > @LastID)
ORDER BY City, AddressID;
總結
NEWID() 適合小數據集精確隨機
TABLESAMPLE 適合大表統計抽樣
- 分頁優先用
OFFSET/FETCH,深分頁必須用 Keyset 分頁
- 所有排序列必須有確定順序 (加唯一鍵防抖動)