Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> MySQL

Chọn hàng ngẫu nhiên tồn tại trong bảng MySQL?

Chọn hàng ngẫu nhiên (Random Row) trong MySQL

Sử dụng hàm RAND() trong ORDER BY kết hợp LIMIT 1 để lấy 1 hàng ngẫu nhiên từ bảng.

Cú pháp

SELECT * FROM ten_bang ORDER BY RAND() LIMIT 1;

Ví dụ minh họa

Tạo bảng DemoTable735:

mysql> CREATE TABLE DemoTable735 (Amount INT);
Query OK, 0 rows affected (0.57 sec)

Chèn dữ liệu:

mysql> INSERT INTO DemoTable735 VALUES(984474734);
Query OK, 1 row affected (0.17 sec)
mysql> INSERT INTO DemoTable735 VALUES(489393323);
Query OK, 1 row affected (0.18 sec)
mysql> INSERT INTO DemoTable735 VALUES(23432333);
Query OK, 1 row affected (0.17 sec)
mysql> INSERT INTO DemoTable735 VALUES(8949933);
Query OK, 1 row affected (0.14 sec)

Xem dữ liệu:

mysql> SELECT * FROM DemoTable735;
+-----------+
| Amount    |
+-----------+
| 984474734 |
| 489393323 |
| 23432333  |
| 8949933   |
+-----------+
4 rows in set (0.00 sec)

Chọn 1 hàng ngẫu nhiên:

mysql> SELECT * FROM DemoTable735 ORDER BY RAND() LIMIT 1;

Kết quả (mỗi lần chạy khác nhau):

+-----------+
| Amount    |
+-----------+
| 489393323 |
+-----------+
1 row in set (0.00 sec)

⚠️ Vấn đề hiệu suất với bảng lớn

ORDER BY RAND() buộc MySQL:

  1. Tạo bảng tạm chứa toàn bộ hàng + cột RAND()
  2. Sắp xếp bảng tạm
  3. Lấy 1 hàng đầu

→ O(N log N), rất chậm với bảng > 10k hàng.

Giải pháp tối ưu cho bảng lớn

Cách 1: Lấy ID ngẫu nhiên trong phạm vi (cần ID liên tục, ít xóa)

SELECT * FROM DemoTable735 
WHERE Id >= (SELECT FLOOR(RAND() * (SELECT MAX(Id) FROM DemoTable735))) 
ORDER BY Id LIMIT 1;

Cách 2: 2 truy vấn (Application level)

-- Query 1: Lấy COUNT(*)
SELECT COUNT(*) INTO @cnt FROM DemoTable735;
-- App tính: offset = FLOOR(RAND() * @cnt)
-- Query 2: 
SELECT * FROM DemoTable735 LIMIT @offset, 1;

Cách 3: TABLESAMPLE (MySQL 8.0.23+ - Bernoulli sampling)

SELECT * FROM DemoTable735 TABLESAMPLE BERNOULLI (10) LIMIT 1;

Lấy ~10% bản ghi ngẫu nhiên, sau đó LIMIT 1. Không đảm bảo phân bố đều.

Cách 4: Offset ngẫu nhiên trên Primary Key (khuyên dùng)

SELECT * FROM DemoTable735 
WHERE Id >= (SELECT FLOOR(RAND() * ((SELECT MAX(Id) FROM DemoTable735) - (SELECT MIN(Id) FROM DemoTable735) + 1)) + (SELECT MIN(Id) FROM DemoTable735))
ORDER BY Id LIMIT 1;

Tóm tắt khuyến nghị

Kích thước bảngPhương pháp khuyên dùng
< 1.000 hàngORDER BY RAND() LIMIT 1 (đơn giản, chấp nhận được)
1.000 - 100.000 hàngCách 2 (2 queries) hoặc Generated Column + Index
> 100.000 hàngCách 4 (Random PK range) hoặc Reservoir Sampling ở App