Kỹ thuật lấy n bản ghi ngẫu nhiên

Kỹ thuật lấy n bản ghi ngẫu nhiên

Giả sử cần lấy 10 bản ghi ngẫu nhiên để hiển thị thành 1 page trên website:

Sử dụng các câu truy vấn có sẵn

SQL SERVER

SELECT TOP 10 column FROM table
ORDER BY NEWID()

MySQL

SELECT column FROM table
ORDER BY RAND()
LIMIT 10

Oracle

SELECT column FROM
( SELECT column FROM table
ORDER BY dbms_random.value )
WHERE rownum <= 10

DB2

SELECT column, RAND() as IDX 
FROM table 
ORDER BY IDX FETCH FIRST 10 ROWS ONLY

PostgreSQL

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 10

MongoDb

var count = db.coll.count();
var result = new Array();
for (var i=0; i<10; i++) {
	var idx = parseInt(Math.random() * count);
	var item = db.coll.find().skip(idx).limit(1).toArray()[0];
	result.push(item);
}
printjson(result);

Tự cài đặt để lấy ngẫu nhiên

Với các câu lệnh SQL trên, ta thấy đều phải sử dụng sắp xếp theo một phần tử ngẫu nhiên rồi lấy top 10 bản ghi đầu. Việc sắp xếp này thường tốn kém nhiều tài nguyên – thường là O(nlog(n)) – nên nếu thực hiện nhiều có thể ảnh hưởng đến hiệu năng hệ thống. Ta có thể cài đặt việc lấy ngẫu nhiên như sau giúp việc tìm ngẫu nhiên 10 phần tử nhanh hơn:
- Bước 1: cứ khi thêm một phần tử, ta chèn thêm một số nguyên là idx được lấy tăng dần (trong sql là trường identity(1,1), trong oracle dùng sequence, mongodb thì sử dụng một collection để lưu trữ giá trị idx hiện tại này)
- Bước 2: đánh index trên trường idx này (giúp tìm kiếm nhanh hơn)
- Bước 3: tạo ra mảng 10 số ngẫu nhiên nằm trong khoảng [0, IDX)
- Bước 4: truy vấn ra các bản ghi có idx bằng các số trong mảng trên.

RDBMS: Sql Server, MySql, Oracle …

SELECT column FROM table
WHERE idx in (r1, r2, r3, r4, r5, r6, r7, r8, r9, r10)

MongoDb

var IDX = db.coll.count();
var randomArray = new Array();
for (var i=0; i<10; i++)
	randomArray.push(parseInt(Math.random() * IDX));
var result = db.coll.find({idx: {$in: randomArray}});
printjson(result.toArray());

Với cách này, độ phức tạp chỉ là log(n).

Lưu ý:
Cách trên có thể khi chạy không ra đúng 10 kết quả nếu trong 10 số ngẫu nhiên rơi vào idx của bản ghi bị xóa. Do vậy kỹ thuật trên tốt đối với các bản ghi không bị xóa.

Khi trích dẫn bài viết từ tek.eten.vn, xin vui lòng ghi rõ nguồn. Chúng tôi sẽ rất cảm ơn bạn!