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

SQL Server 查詢結果隨機排序技巧:NEWID() 函數優於 RAND() 的應用

     編輯:關於SqlServer

隨機排序與抽樣的正確姿勢

錯誤示範:RAND()

SELECT * FROM Sales.Orders ORDER BY RAND(); -- 錯誤!

原因:`RAND()` 在單一查詢執行期間**僅計算一次**,所有資料列獲得相同的隨機值,`ORDER BY` 失去排序意義,結果順序不定 (通常維持原序)。

正確作法:NEWID()

-- 1. 全表隨機排序
SELECT * FROM Sales.Orders ORDER BY NEWID();

-- 2. 隨機抽樣 TOP N 筆
SELECT TOP (10) * FROM Sales.Orders ORDER BY NEWID();

-- 3. 百分比抽樣 (TABLESAMPLE 替代方案, SQL 2005+)
SELECT * FROM Sales.Orders TABLESAMPLE (10 PERCENT); -- 頁面層級抽樣,非逐列隨機,效能極佳但統計特性不同

原理比較

函數回傳型別計算頻率唯一性適用場景
RAND([seed])FLOAT (0~1)每查詢一次全表相同產生單一隨機數、模擬資料、填充測試資料
NEWID()UNIQUEIDENTIFIER (GUID)每資料列一次極高 (128-bit)隨機排序、隨機抽樣、分散式主鍵生成
CRYPT_GEN_RANDOM(n) (2008+)VARBINARY每呼叫一次加密級高熵隨機位元組、安全性 Token、鹽值

效能考量

  • `ORDER BY NEWID()` 需為每列計算 GUID 並排序,**複雜度 O(N log N)**,大表 (百萬列+) 會消耗大量 CPU/記憶體/TempDB。
  • 大表抽樣優化:
    • TABLESAMPLE (n PERCENT/ROWS):頁面層級抽樣,不掃描全表,**極快**,但非逐列獨立隨機,同一頁面全選或全不選。
    • WHERE RAND(CHECKSUM(*)) < 0.01:利用 `CHECKSUM(*)` 行雜湊值配合 `RAND(seed)` 產生確定性偽隨機,可配合索引 (若有計算欄位) 或全表掃描但避免排序開銷。
    • 應用層抽樣:先 `SELECT COUNT(*)`,應用程式產生隨機 OFFSET/FETCH 或主鍵清單,再 `WHERE ID IN (...)`。

實務範例:A/B 測試分桶

-- 將使用者以 1% 機率分入實驗組
SELECT UserID, 'Experiment' AS Bucket
FROM dbo.Users
WHERE ABS(CHECKSUM(NEWID())) % 100 < 1; -- 0~99 隨機分布,<1 即 1%
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved