How to quickly SELECT 3 random records from a 30k MySQL table with a where filter by a single query?

后端 未结 6 1884
生来不讨喜
生来不讨喜 2020-12-14 02:38

Well, this is a very old question never gotten real solution. We want 3 random rows from a table with about 30k records. The table is not so big in point of view MySQL, but

6条回答
  •  伪装坚强ぢ
    2020-12-14 03:27

    I've been testing the following bunch of SQLs on a 10M-record, poorly designed database.

    SELECT COUNT(ID)
    INTO @count
    FROM Products
    WHERE HasImages = 1;
    
    PREPARE random_records FROM
    '(
        SELECT * FROM Products WHERE HasImages = 1 LIMIT ?, 1
    ) UNION (
        SELECT * FROM Products WHERE HasImages = 1 LIMIT ?, 1
    ) UNION (
        SELECT * FROM Products WHERE HasImages = 1 LIMIT ?, 1
    )';
    
    SET @l1 = ROUND(RAND() * @count);
    SET @l2 = ROUND(RAND() * @count);
    SET @l3 = ROUND(RAND() * @count);
    
    EXECUTE random_records USING @l1
        , @l2
        , @l3;
    DEALLOCATE PREPARE random_records;
    

    It took almost 7 minutes to get the three results. But I'm sure its performance will be much better in your case. Yet if you are looking for a better performance I suggest the following ones as they took less than 30 seconds for me to get the job done (on the same database).

    SELECT COUNT(ID)
    INTO @count
    FROM Products
    WHERE HasImages = 1;
    
    PREPARE random_records FROM
    'SELECT * FROM Products WHERE HasImages = 1 LIMIT ?, 1';
    
    SET @l1 = ROUND(RAND() * @count);
    SET @l2 = ROUND(RAND() * @count);
    SET @l3 = ROUND(RAND() * @count);
    
    EXECUTE random_records USING @l1;
    EXECUTE random_records USING @l2;
    EXECUTE random_records USING @l3;
    
    DEALLOCATE PREPARE random_records;
    

    Bear in mind that both these commands require MySQLi driver in PHP if you want to execute them in one go. And their only difference is that the later one requires calling MySQLi's next_result method to retrieve all three results.

    My personal belief is that this is the fastest way to do this.

提交回复
热议问题