從SQLSERVER/MYSQL數據庫中隨機取一條或者N條記錄

從SQLSERVER/MYSQL數據庫中隨機取一條或者N條記錄

不少人都知道使用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 

相關文章
相關標籤/搜索