很多人都知道使用rand()函數但是怎麼使用可能不是每個人都知道
建立測試表
USE [sss]GOCREATE TABLE RANDTEST(ID INT DEFAULT RAND()*100,NAME NVARCHAR(200) DEFAULT 'nihao')GOCREATE INDEX IX_RANDTEST_ID ON RANDTEST(ID)GOINSERT INTO RANDTEST DEFAULT VALUESGO 2000SELECT * FROM RANDTEST
第一種寫法:大家會想到ORDER BYNEWID()
SET STATISTICS TIME ON SET STATISTICS IO ONSELECT TOP 50 [id] FROM [dbo].[RANDTEST]GROUP BY IDORDER BY NEWID() SET STATISTICS TIME OFFSET STATISTICS IO OFF
這種寫法使用到索引掃描,而且每次select出來的結果都是一樣的,都是50條記錄


第二種寫法:
SET STATISTICS TIME ON SET STATISTICS IO ONSELECT TOP 50 [t1].[ID] FROM [dbo].[RANDTEST] t1 JOIN (SELECT RAND()*100 AS nid) t2 ON [t1].[ID]>[t2].[nid]GROUP BY [t1].[ID]SET STATISTICS TIME OFFSET STATISTICS IO OFF
跟t2這個表做比較,而且每次能夠達到隨機取一條或者N條記錄的效果
每次select出來的行數都是不一樣的


比較一下IO和時間
當兩種寫法select出來的結果條數都是50條的時候,時間和IO都是一樣的,如果第二種寫法select出來的記錄條數不是50條
那么IO肯定比第一種寫法要少
--第一種寫法 select出來50條記錄SQL Server 執行時間: CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。(50 行受影響)表 'RANDTEST'。掃描計數 1,邏輯讀取 5 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。SQL Server 執行時間: CPU 時間 = 0 毫秒,占用時間 = 1 毫秒。--------------------------------------------------------------------------------第二種寫法 select出來37條記錄SQL Server 執行時間: CPU 時間 = 0 毫秒,占用時間 = 0 毫秒。(27 行受影響)表 'RANDTEST'。掃描計數 1,邏輯讀取 4 次,物理讀取 0 次,預讀 0 次,lob 邏輯讀取 0 次,lob 物理讀取 0 次,lob 預讀 0 次。SQL Server 執行時間: CPU 時間 = 0 毫秒,占用時間 = 1 毫秒。
總結
如果第一種寫法寫成下面的樣子,那么每次select出來的結果都是一樣的,而且不會進行排序,在執行計劃里面你看不到排序這個運算符
因為非聚集索引是排好序的,掃描非聚集索引只會得到排好序的結果
SELECT TOP 50 [id] FROM [dbo].[RANDTEST]GROUP BY IDORDER BY RAND()*100


綜上,想從SQLSERVER數據庫中隨機取一條或者N條記錄時,最好把RAND()生成隨機數放在JOIN子查詢中以提高效率。
SELECT TOP n [id] FROM tableGROUP BY IDORDER BY NEWID()
改造成下面這個:
SELECT TOP n [t1].[ID] FROM table t1 JOIN (SELECT RAND()*100 AS nid) t2 ON [t1].[ID]>[t2].[nid]GROUP BY [t1].[ID]
就可以享受在SQL中直接取得隨機數了,不用再在程序中構造一串隨機數去檢索了。
MYSQL也是同樣的原理
CREATE TABLE `t_innodb_random` (`id` INT(10) UNSIGNED NOT NULL,`user` VARCHAR(64) NOT NULL DEFAULT '',KEY `idx_id` (`id`)) ENGINE=INNODB DEFAULT CHARSET=utf8;INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('1','lily');INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('3','tom');INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('5','fancy');INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('6','cici');INSERT INTO `t_innodb_random` (`id`, `user`) VALUES('9','syan');SELECT * FROM t_innodb_random;SELECT id FROM t_innodb_random ORDER BY RAND() LIMIT 5;-- 改造成下面這個:SELECT id FROM t_innodb_random t1 JOIN (SELECT RAND()*10 AS nid) t2 ON t1.id > t2.nid LIMIT 5;
---------------------------------------------------------------------------------------------

如有不對的地方,歡迎大家拍磚o(∩_∩)o
新聞熱點
疑難解答