不少人都知道使用rand()函數可是怎麼使用可能不是每一個人都知道數據庫
創建測試表dom
USE [sss] GO CREATE TABLE RANDTEST(ID INT DEFAULT RAND()*100,NAME NVARCHAR(200) DEFAULT 'nihao') GO CREATE INDEX IX_RANDTEST_ID ON RANDTEST(ID) GO INSERT INTO RANDTEST DEFAULT VALUES GO 2000 SELECT * FROM RANDTEST
第一種寫法:你們會想到ORDER BY NEWID() 函數
SET STATISTICS TIME ON SET STATISTICS IO ON SELECT TOP 50 [id] FROM [dbo].[RANDTEST] GROUP BY ID ORDER BY NEWID() SET STATISTICS TIME OFF SET STATISTICS IO OFF
這種寫法使用到索引掃描,並且每次select出來的結果都是同樣的,都是50條記錄測試
第二種寫法:spa
SET STATISTICS TIME ON SET STATISTICS IO ON SELECT TOP 50 [t1].[ID] FROM [dbo].[RANDTEST] t1 INNER JOIN (SELECT RAND()*100 AS nid) t2 ON [t1].[ID]>[t2].[nid] GROUP BY [t1].[ID] SET STATISTICS TIME OFF SET STATISTICS IO OFF
跟t2這個表作比較,並且每次可以達到隨機取一條或者N條記錄的效果3d
每次select出來的行數都是不同的code
比較一下IO和時間blog
當兩種寫法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 ID ORDER BY RAND()*100
綜上,想從SQLSERVER數據庫中隨機取一條或者N條記錄時,最好把RAND()生成隨機數放在JOIN子查詢中以提升效率。
SELECT TOP n [id] FROM table GROUP BY ID ORDER 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 INNER JOIN (SELECT RAND()*10 AS nid) t2 ON t1.id > t2.nid LIMIT 5;
---------------------------------------------------------------------------------------------
若有不對的地方,歡迎你們拍磚o(∩_∩)o