[adsense id=”0514458240″ width=”468″ height=”60″]
I have seen lots of requests for ways of returning a set of random rows from a table. Based on the analysis performed by Akinas where he analyzed the performance impact of obtaining random rows using a variety of methods, their conclusion was that performing the request using two requests delivered the best overall performance.
Using this method we have come up with some code for a stored procedure which takes two parameters:
- A table name
- Number of rows to be returned
Here is the code for the stored procedure which is called sp_random(table, rows).
DROP PROCEDURE IF EXISTS sp_random; DELIMITER $$ CREATE PROCEDURE sp_random(IN pTableName VARCHAR(64), IN pLimit SMALLINT UNSIGNED) NOT DETERMINISTIC SQL SECURITY INVOKER COMMENT 'A procedure that returns a random set of rows from a table' BEGIN DECLARE lCount INT UNSIGNED; SET @uQuery := CONCAT('SELECT COUNT(1) INTO @uCount FROM ', pTableName); PREPARE stmt FROM @uQuery; EXECUTE stmt; IF @uCount <= pLimit THEN -- Return all values SET @query := CONCAT('SELECT * FROM ', pTableName); ELSE -- Return limited number of entries SET @offset := ROUND((@uCount - pLimit) * RAND(),0); SET @query := CONCAT('SELECT * FROM ', pTableName, ' LIMIT ', @offset, ',', pLimit); END IF; PREPARE stmt FROM @query; EXECUTE stmt; DEALLOCATE PREPARE stmt; END; $$ DELIMITER ;
Viewing this in action we have a table with countries defined and we will have a look at returning random rows:
mysql> select * from countries; +----+-------------+ | id | country | +----+-------------+ | 1 | Spain | | 2 | Ireland | | 3 | Andorra | | 4 | Italy | | 5 | Belgium | | 6 | France | | 7 | Germany | | 8 | Netherlands | | 9 | Luxembourg | | 10 | Poland | | 11 | Finland | | 12 | Sweden | | 13 | Norway | | 14 | Denmark | +----+-------------+ 14 rows in set (0.00 sec) mysql> call sp_random('countries',3); +----+---------+ | id | country | +----+---------+ | 10 | Poland | | 11 | Finland | | 12 | Sweden | +----+---------+ 3 rows in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call sp_random('countries',3); +----+---------+ | id | country | +----+---------+ | 11 | Finland | | 12 | Sweden | | 13 | Norway | +----+---------+ 3 rows in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call sp_random('countries',3); +----+---------+ | id | country | +----+---------+ | 12 | Sweden | | 13 | Norway | | 14 | Denmark | +----+---------+ 3 rows in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call sp_random('countries',3); +----+---------+ | id | country | +----+---------+ | 3 | Andorra | | 4 | Italy | | 5 | Belgium | +----+---------+ 3 rows in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call sp_random('countries',3); +----+---------+ | id | country | +----+---------+ | 11 | Finland | | 12 | Sweden | | 13 | Norway | +----+---------+ 3 rows in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call sp_random('countries',3); +----+---------+ | id | country | +----+---------+ | 1 | Spain | | 2 | Ireland | | 3 | Andorra | +----+---------+ 3 rows in set (0.00 sec) Query OK, 0 rows affected (0.00 sec) mysql> call sp_random('countries',3); +----+---------+ | id | country | +----+---------+ | 5 | Belgium | | 6 | France | | 7 | Germany | +----+---------+ 3 rows in set (0.00 sec) Query OK, 0 rows affected (0.00 sec)