文章出處
文章列表
從SQLSERVER/MYSQL數據庫中隨機取一條或者N條記錄
很多人都知道使用rand()函數但是怎麼使用可能不是每個人都知道
建立測試表
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條記錄
第二種寫法:
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條記錄的效果
每次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 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
文章列表
全站熱搜