SELECT TOP N * FROM table ORDER BY NEWID() 是最常見的隨機抽樣寫法,但在百萬級以上資料量下,全表掃描加排序會導致效能崩潰。本文提出一種基於 UNIQUEIDENTIFIER 索引鍵的 LIKE 前綴匹配法,實測 300 萬筆資料抽 2000 筆僅耗時約 1 秒,效能提升數量級。
UNIQUEIDENTIFIER 型別的主鍵或索引欄位(GUID 本身具備隨機分佈特性)。LIKE '隨機前綴%' 進行索引範圍掃描,而非全表排序。-- 建立測試環境
USE master;
GO
CREATE TABLE dbo.test (
id UNIQUEIDENTIFIER PRIMARY KEY,
name VARCHAR(100)
);
INSERT INTO dbo.test (id, name)
SELECT NEWID(), name FROM syscolumns; -- 快速產生測試資料
GO
-- 高效隨機抽樣(抽 10 筆示範)
SELECT TOP 10 *
FROM dbo.test
WHERE id LIKE CHAR(48 + ABS(CHECKSUM(NEWID()) % 10)) + '%'
+ CHAR(48 + ABS(CHECKSUM(NEWID()) % 10)) + '%'
+ CHAR(48 + ABS(CHECKSUM(NEWID()) % 10)) + '%'
+ CHAR(48 + ABS(CHECKSUM(NEWID()) % 10)) + '%';
-- 清理環境
DROP TABLE dbo.test;
CHECKSUM(NEWID()) 產生高熵隨機整數,%10 取模得到 0-9,CHAR(48+...) 轉為字元 '0'-'9'。CHAR(...) + '%' 拼接成如 '3%7%1%9%' 的模式,利用索引進行多次前綴篩選,極大縮小掃描範圍。%abc%),將退化為全表掃描。CHAR(CASE WHEN v<10 THEN 48+v ELSE 55+v END)(v 為 0-15 隨機數)。TABLESAMPLE (1000 ROWS) 或 BERNOULLI 取樣,適合統計近似場景,但非嚴格隨機。| 方法 | 300萬資料抽2000筆耗時 | 備註 |
|---|---|---|
| ORDER BY NEWID() | > 60 秒(或逾時) | 全表排序,TempDB 壓力極大 |
| GUID LIKE 前綴法 | ~1 秒 | 索引範圍掃描,CPU/IO 極低 |
| TABLESAMPLE SYSTEM | < 1 秒 | 頁面級取樣,非嚴格隨機,有聚簇偏差 |
結論:擁有 GUID 索引鍵的大表,首選 LIKE 前綴法;無 GUID 索引鍵時,考慮新增計算欄位或改用 TABLESAMPLE 配合業務容忍度。