简体   繁体   中英

Is this a fast method to select random row from a table

I've read a post about how to randomly select a row (with certain conditions) from a SQL table with huge data. They get the max and min of id and generate a random number between them, and get the first row that has a bigger id than that. However, my ids are not distributed evenly, so I didn't get the truly random row. For example if my ids are 1, 100, 101, I'll have little chance to get the two later rows.

But I think of another solution. Instead of getting the max id, I count all the row in my query, get a random number i and select the ith one. The code looks like this

$count_res = $mysqli->query("SELECT COUNT(*) FROM quest WHERE category IN ({$mem['my_cate']})");
$count = $count_res->fetch_array();
$rand_id = rand(0, $count[0] - 1);

$result = $mysqli->query("SELECT * FROM quest WHERE category IN ({$mem['my_cate']}) LIMIT 1 OFFSET $rand_id");

However, i doubt it's effectiveness. Can anyone give me idea about that, or suggest a solution for my case. Thanks.

Alright, I've done some benchmarking. I've created a table with only one column an auto increment id. I then added 1,700,000 records. Since there is only one column I imagine it will be faster than in practice but here is my benchmarking:

Method 1: Select a count of rows and then using PHP to pick a random number and then select based on an offset. (I rigged the offset to be at the end of the table since it would be slower than the beginning fo the table).

Select count: 12ms

Select with offset: 513ms

Total: 525ms

Method 2: Selecting 1 with a RAND() on the whole table.

Total: 2,190ms

WINNER = METHOD 1

Possible Method 3: This is kinda just something I thought up and it wouldn't necessarily work in all cases. So the idea is you get the last auto increment id in the table, generate a random number between 1 and the last auto increment number, then select the first row that is greater than or equal to that id number. You have to do greater than or equal to because it's possible to have missing id numbers.

Select last id: 10.1ms

Select random row: 6.3ms

Total: 16.4ms

It might be quicker to use something like:

$result = $mysqli->query("SELECT * FROM quest WHERE category IN ({$mem['my_cate']}) ORDER BY Rand() LIMIT 1");

Because it is only using one query and you can skip that top bit. You can benchmark it by trying both ways in a loop a few thousand or whatever number you decide times and compare the microtime() before and after the loop.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM