Programing

MySQL은 600K 행에서 10 개의 무작위 행을 빠르게 선택합니다.

lottogame 2020. 2. 18. 22:34
반응형

MySQL은 600K 행에서 10 개의 무작위 행을 빠르게 선택합니다.


총 600k에서 무작위로 10 개의 행을 선택하는 쿼리를 작성하는 방법은 무엇입니까?


간결한 간격에서 불균일 한 간격에 이르기까지 여러 사례를 처리하는 훌륭한 포스트입니다.

http://jan.kneschke.de/projects/mysql/order-by-rand/

가장 일반적인 경우는 다음과 같습니다.

SELECT name
  FROM random AS r1 JOIN
       (SELECT CEIL(RAND() *
                     (SELECT MAX(id)
                        FROM random)) AS id)
        AS r2
 WHERE r1.id >= r2.id
 ORDER BY r1.id ASC
 LIMIT 1

이것은 id의 분포가 같고 id 목록에 간격이있을 수 있다고 가정합니다. 고급 예제는 기사를 참조하십시오.


SELECT column FROM table
ORDER BY RAND()
LIMIT 10

효율적인 솔루션은 아니지만 작동


나는 무엇입니까 빠른 쿼리 로 (약 0.5 초) 속도가 느린 CPU 400K 등록 MySQL 데이터베이스 캐시되지 않은 2 기가 바이트 크기의 10 개 임의의 행을 선택. 내 코드를 참조하십시오 : MySQL에서 임의의 행을 빠르게 선택 하십시오.

<?php
$time= microtime_float();

$sql='SELECT COUNT(*) FROM pages';
$rquery= BD_Ejecutar($sql);
list($num_records)=mysql_fetch_row($rquery);
mysql_free_result($rquery);

$sql="SELECT id FROM pages WHERE RAND()*$num_records<20
   ORDER BY RAND() LIMIT 0,10";
$rquery= BD_Ejecutar($sql);
while(list($id)=mysql_fetch_row($rquery)){
    if($id_in) $id_in.=",$id";
    else $id_in="$id";
}
mysql_free_result($rquery);

$sql="SELECT id,url FROM pages WHERE id IN($id_in)";
$rquery= BD_Ejecutar($sql);
while(list($id,$url)=mysql_fetch_row($rquery)){
    logger("$id, $url",1);
}
mysql_free_result($rquery);

$time= microtime_float()-$time;

logger("num_records=$num_records",1);
logger("$id_in",1);
logger("Time elapsed: <b>$time segundos</b>",1);
?>

매우 간단하고 한 줄로 된 쿼리입니다.

SELECT * FROM Table_Name ORDER BY RAND() LIMIT 0,10;

성능우수한 간단한 쿼리 (간격이있는 경우) :

SELECT * FROM tbl WHERE id IN 
    (SELECT id FROM (SELECT id FROM tbl ORDER BY RAND() LIMIT 10) t)

MySQL은 아직 처음부터 LIMIT를 지원하지 않기 때문에 두 개의 중첩 된 하위 쿼리가 사용됩니다.

정렬 단계는 색인화 된 ID 열만 사용하므로 빠릅니다.

가중치 버전 : https://stackoverflow.com/a/41577458/893432


책에서 :

오프셋을 사용하여 임의의 행을 선택하십시오.

이전 대안에서 발견 된 문제점을 피하는 또 다른 기술은 데이터 세트의 행을 계산하고 0과 수 사이의 난수를 리턴하는 것입니다. 그런 다음 데이터 세트를 쿼리 할 때이 숫자를 오프셋으로 사용하십시오.

<?php
$rand = "SELECT ROUND(RAND() * (SELECT COUNT(*) FROM Bugs))";
$offset = $pdo->query($rand)->fetch(PDO::FETCH_ASSOC);
$sql = "SELECT * FROM Bugs LIMIT 1 OFFSET :offset";
$stmt = $pdo->prepare($sql);
$stmt->execute( $offset );
$rand_bug = $stmt->fetch();

연속 키 값을 가정 할 수없고 각 행에 고른 기회가 있는지 확인해야 할 때이 솔루션을 사용하십시오.


테이블에서 임의의 행을 선택하는 방법 :

여기에서 : MySQL에서 임의의 행을 선택 하십시오.

"테이블 스캔"보다 빠른 개선은 인덱스를 사용하여 임의의 ID를 선택하는 것입니다.

SELECT *
FROM random, (
        SELECT id AS sid
        FROM random
        ORDER BY RAND( )
        LIMIT 10
    ) tmp
WHERE random.id = tmp.sid;

키에 틈이없고 모두 숫자이면 임의의 숫자를 계산하고 해당 줄을 선택할 수 있습니다. 그러나 이것은 아마도 그렇지 않을 것입니다.

따라서 한 가지 해결책은 다음과 같습니다.

SELECT * FROM table WHERE key >= FLOOR(RAND()*MAX(id)) LIMIT 1

기본적으로 키 범위에서 임의의 숫자를 얻은 다음 다음 중 가장 큰 것을 선택합니다. 이것을 10 번해야합니다.

그러나 키가 균등하게 배포되지 않을 가능성이 있기 때문에 이것은 실제로 무작위가 아닙니다.

실제로 큰 문제이며 모든 요구 사항을 충족시키기가 쉽지 않습니다. MySQL의 rand ()는 10 개의 임의 행을 원할 때 얻을 수있는 최선입니다.

그러나 다른 솔루션은 빠르지 만 무작위성에 관해서는 트레이드 오프가 있지만 더 잘 맞을 수 있습니다. 여기에서 읽으십시오 : MySQL의 ORDER BY RAND () 함수를 어떻게 최적화 할 수 있습니까?

질문은 당신이 얼마나 랜덤해야 하는가입니다.

좀 더 설명해 주시면 좋은 해결책을 드릴 수 있습니다.

예를 들어, 내가 함께 일한 회사는 절대 무작위성이 매우 빠른 솔루션을 가지고있었습니다. 결과적으로 내림차순으로 선택한 임의의 값으로 데이터베이스를 미리 채우고 나중에 다른 임의의 값으로 설정했습니다.

거의 업데이트하지 않으면 증분 ID를 채울 수 있으므로 간격이 없으며 선택하기 전에 임의의 키를 계산할 수 있습니다 ... 사용 사례에 따라 다릅니다!


Riedsio가 게시 한이 http://jan.kneschke.de/projects/mysql/order-by-rand/를 사용했습니다 (하나 이상의 임의의 값을 반환하는 저장 프로 시저의 경우를 사용했습니다).

   DROP TEMPORARY TABLE IF EXISTS rands;
      CREATE TEMPORARY TABLE rands ( rand_id INT );

    loop_me: LOOP
        IF cnt < 1 THEN
          LEAVE loop_me;
        END IF;

        INSERT INTO rands
           SELECT r1.id
             FROM random AS r1 JOIN
                  (SELECT (RAND() *
                                (SELECT MAX(id)
                                   FROM random)) AS id)
                   AS r2
            WHERE r1.id >= r2.id
            ORDER BY r1.id ASC
            LIMIT 1;

        SET cnt = cnt - 1;
      END LOOP loop_me;

이 기사에서 그는 테이블을 유지함으로써 트리거 결과 등무작위로 생성하지 않는 id 의 간격 문제를 해결 합니다 (트리거 등을 사용하여 기사 참조). 1부터 시작하여 연속적인 숫자로 채워진 다른 열을 테이블에 추가하여 문제를 해결하고 있습니다 ( 편집 : 이 열은 런타임시 하위 쿼리에 의해 생성 된 임시 테이블에 추가되며 영구 테이블에는 영향을 미치지 않습니다).

   DROP TEMPORARY TABLE IF EXISTS rands;
      CREATE TEMPORARY TABLE rands ( rand_id INT );

    loop_me: LOOP
        IF cnt < 1 THEN
          LEAVE loop_me;
        END IF;

        SET @no_gaps_id := 0;

        INSERT INTO rands
           SELECT r1.id
             FROM (SELECT id, @no_gaps_id := @no_gaps_id + 1 AS no_gaps_id FROM random) AS r1 JOIN
                  (SELECT (RAND() *
                                (SELECT COUNT(*)
                                   FROM random)) AS id)
                   AS r2
            WHERE r1.no_gaps_id >= r2.id
            ORDER BY r1.no_gaps_id ASC
            LIMIT 1;

        SET cnt = cnt - 1;
      END LOOP loop_me;

이 기사에서 그는 코드를 최적화하기 위해 많은 시간을 보냈습니다. 변경 사항이 성능에 영향을 미치지 만 나에게 매우 잘 작동한다면 아이디어가 없습니다.


다소 큰 테이블에서 많은 수의 임의 행을 반환하는 쿼리가 필요했습니다. 이것이 내가 생각해 낸 것입니다. 먼저 최대 레코드 ID를 얻으십시오.

SELECT MAX(id) FROM table_name;

그런 다음 해당 값을 다음으로 대체하십시오.

SELECT * FROM table_name WHERE id > FLOOR(RAND() * max) LIMIT n;

여기서 max는 테이블의 최대 레코드 ID이고 n은 결과 집합에서 원하는 행 수입니다. 레코드 ID에 차이가 없다고 가정하지만 (있는 경우 시도하지 않은 경우) 결과에 영향을 줄 것입니다. 또한이 저장 프로 시저를보다 일반적인 것으로 만들었습니다. 반환 할 테이블 이름과 행 수를 전달하십시오. Windows 2008, 32GB, 이중 3GHz E5450 및 17,361,264 행이있는 테이블에서 MySQL 5.5.38을 실행 중이며 1,000,000 행을 반환하기 위해 ~ .03 초 / ~ 11 초에서 상당히 일관성이 있습니다. (시간은 MySQL Workbench 6.1에서 온 것입니다. 선호도에 따라 두 번째 select 문에서 FLOOR 대신 CEIL을 사용할 수도 있습니다)

DELIMITER $$

USE [schema name] $$

DROP PROCEDURE IF EXISTS `random_rows` $$

CREATE PROCEDURE `random_rows`(IN tab_name VARCHAR(64), IN num_rows INT)
BEGIN

SET @t = CONCAT('SET @max=(SELECT MAX(id) FROM ',tab_name,')');
PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

SET @t = CONCAT(
    'SELECT * FROM ',
    tab_name,
    ' WHERE id>FLOOR(RAND()*@max) LIMIT ',
    num_rows);

PREPARE stmt FROM @t;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
END
$$

그때

CALL [schema name].random_rows([table name], n);

여기 많은 사람들에게 도움이 될 수있는 게임 체인저가 있습니다.

200k 개의 행이있는 테이블이 있고 순차 ID가 N 개의 임의의 행 을 선택해야 하므로 테이블에서 가장 큰 ID를 기반으로 임의의 값을 생성하도록 선택하면이 스크립트가 가장 빠른 작업인지 확인합니다.

logTime();
query("SELECT COUNT(id) FROM tbl");
logTime();
query("SELECT MAX(id) FROM tbl");
logTime();
query("SELECT id FROM tbl ORDER BY id DESC LIMIT 1");
logTime();

결과는 다음과 같습니다.

  • 개수 : 36.8418693542479ms
  • 최대 : 0.241041183472ms
  • 주문 : 0.216960906982ms

이 결과를 바탕으로 order desc는 최대 id를 얻는 가장 빠른 작업입니다.
다음은 질문에 대한 답변입니다.

SELECT GROUP_CONCAT(n SEPARATOR ',') g FROM (
    SELECT FLOOR(RAND() * (
        SELECT id FROM tbl ORDER BY id DESC LIMIT 1
    )) n FROM tbl LIMIT 10) a

...
SELECT * FROM tbl WHERE id IN ($result);

참고하십시오 200K 테이블에서 10 개 임의의 행을 얻으려면, 그것은 나에게 1.78했다 MS (PHP는 측면에서 모든 작업을 포함하여)


모든 최고의 답변이 이미 게시되었습니다 (주로 http://jan.kneschke.de/projects/mysql/order-by-rand/ 링크 참조 ).

또 다른 속도 향상 가능성을 캐싱 하고 싶습니다 . 임의의 행을 가져와야하는 이유를 생각해보십시오. 웹 사이트에 임의의 게시물이나 임의의 광고를 표시하려고 할 수 있습니다. 100 req / s를 얻는다면 각 방문자가 임의의 행을 가져와야합니까? 일반적으로 이러한 X 임의 행을 1 초 (또는 10 초) 동안 캐시하는 것이 좋습니다. 동일한 1 초에 100 명의 순 방문자가 동일한 임의의 게시물을 얻는 경우는 중요하지 않습니다. 다음 초에 100 명의 다른 방문자가 다른 게시물을 가져 오기 때문입니다.

이 캐싱을 사용할 때 요청 / 초에 관계없이 초당 1 회만 MySQL에서 가져 오기 때문에 임의의 데이터를 가져 오기 위해 더 느린 솔루션을 사용할 수도 있습니다.


@Riedsio의 답변을 개선했습니다. 이것은 간격 이 좁고 균일하게 분산 된 큰 테이블에서 찾을 수있는 가장 효율적인 쿼리입니다 (> 2.6B 행이있는 테이블에서 1000 개의 임의 행을 가져 오는 테스트).

(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max := (SELECT MAX(id) FROM table)) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
(SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1)

무슨 일이 일어나고 있는지 짐을 풀자.

  1. @max := (SELECT MAX(id) FROM table)
    • 최대 값을 계산하고 저장하고 있습니다. 매우 큰 테이블의 MAX(id)경우 행이 필요할 때마다 계산에 약간의 오버 헤드 가 있습니다.
  2. SELECT FLOOR(rand() * @max) + 1 as rand)
    • 임의의 ID를 가져옵니다
  3. SELECT id FROM table INNER JOIN (...) on id > rand LIMIT 1
    • 이것은 공백을 채 웁니다. 기본적으로 간격에서 임의로 숫자를 선택하면 다음 ID 만 선택합니다. 간격이 균일하게 분포되어 있다고 가정해도 문제가되지 않습니다.

통합을 수행하면 모든 쿼리를 하나의 쿼리에 맞추는 데 도움이되므로 여러 쿼리를 수행하지 않아도됩니다. 또한 계산 오버 헤드를 줄일 수 있습니다 MAX(id). 응용 프로그램에 따라 이것은 거의 또는 거의 중요하지 않을 수 있습니다.

이것은 id 만 가져오고 무작위 순서로 가져옵니다. 더 진보 된 것을하고 싶다면 다음과 같이하십시오.

SELECT t.id, t.name -- etc, etc
FROM table t
INNER JOIN (
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max := (SELECT MAX(id) FROM table)) + 1 as rand) r on id > rand LIMIT 1) UNION
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1) UNION
    (SELECT id FROM table INNER JOIN (SELECT FLOOR(RAND() * @max) + 1 as rand) r on id > rand LIMIT 1)
) x ON x.id = t.id
ORDER BY t.id

이것은 매우 빠르며 간격이 있어도 100 % 무작위입니다.

  1. x사용 가능한 행 계산하십시오.SELECT COUNT(*) as rows FROM TABLE
  2. a_1,a_2,...,a_100과 0 사이의 10 개의 고유 난수를 선택하십시오.x
  3. 다음과 같이 행을 쿼리하십시오. SELECT * FROM TABLE LIMIT 1 offset a_ifor i = 1, ..., 10

나는이 책이 해킹 발견 SQL 안티 패턴 에서 빌 Karwin을 .


읽기 요청이 하나만있는 경우

@redsio의 대답을 임시 테이블과 결합하십시오 (600K는 그다지 크지 않습니다).

DROP TEMPORARY TABLE IF EXISTS tmp_randorder;
CREATE TABLE tmp_randorder (id int(11) not null auto_increment primary key, data_id int(11));
INSERT INTO tmp_randorder (data_id) select id from datatable;

그런 다음 @redsios Answer 버전을 가져옵니다.

SELECT dt.*
FROM
       (SELECT (RAND() *
                     (SELECT MAX(id)
                        FROM tmp_randorder)) AS id)
        AS rnd
 INNER JOIN tmp_randorder rndo on rndo.id between rnd.id - 10 and rnd.id + 10
 INNER JOIN datatable AS dt on dt.id = rndo.data_id
 ORDER BY abs(rndo.id - rnd.id)
 LIMIT 1;

테이블이 크면 첫 번째 부분을 체질 할 수 있습니다.

INSERT INTO tmp_randorder (data_id) select id from datatable where rand() < 0.01;

읽기 요청이 많은 경우

  1. 버전 : 테이블을 tmp_randorder지속적으로 유지하고 이를 datatable_idlist라고 부를 수 있습니다. 구멍이 생길 수 있으므로 특정 간격 (일, 시간)으로 해당 테이블을 다시 작성하십시오. 테이블이 정말 커지면 구멍을 리필 할 수도 있습니다

    datatable_idlist에서 l.data_id를 전체로 선택하십시오.

  2. 버전 : 데이터 세트에 직접 또는 영구적 인 추가 테이블에 랜덤 셋 정렬 열을 데이터 세트에 제공하십시오 datatable_sortorder. 해당 열을 색인화하십시오. 응용 프로그램에서 임의의 값을 생성하십시오 (이하라고 부릅니다 $rand).

    select l.*
    from datatable l 
    order by abs(random_sortorder - $rand) desc 
    limit 1;
    

이 솔루션은 '가장자리 행'을 가장 높고 가장 낮은 random_sortorder로 구분하므로 간격 (하루에 한 번)으로 다시 정렬하십시오.


또 다른 간단한 해결책은 행의 순위를 매기고 그중 하나를 임의로 가져 오는 것입니다.이 솔루션을 사용하면 테이블에 'Id'기반 열이 필요하지 않습니다.

SELECT d.* FROM (
SELECT  t.*,  @rownum := @rownum + 1 AS rank
FROM mytable AS t,
    (SELECT @rownum := 0) AS r,
    (SELECT @cnt := (SELECT RAND() * (SELECT COUNT(*) FROM mytable))) AS n
) d WHERE rank >= @cnt LIMIT 10;

원하는만큼 많은 행에 액세스해야 할 때마다 한계 값을 변경할 수 있지만 대부분 연속적인 값입니다.

그러나 연속적인 임의의 값을 원하지 않으면 더 큰 샘플을 가져 와서 임의로 선택할 수 있습니다. 같은 ...

SELECT * FROM (
SELECT d.* FROM (
    SELECT  c.*,  @rownum := @rownum + 1 AS rank
    FROM buildbrain.`commits` AS c,
        (SELECT @rownum := 0) AS r,
        (SELECT @cnt := (SELECT RAND() * (SELECT COUNT(*) FROM buildbrain.`commits`))) AS rnd
) d 
WHERE rank >= @cnt LIMIT 10000 
) t ORDER BY RAND() LIMIT 10;

자동 생성 된 ID가있는 경우 꽤 좋은 방법은 모듈로 연산자 '%'를 사용하는 것입니다. 예를 들어, 70,000 개 중 10,000 개의 임의 레코드가 필요한 경우 7 개 행 중 1 개가 필요하다고 말하면이를 단순화 할 수 있습니다. 이 쿼리에서이를 단순화 할 수 있습니다.

SELECT * FROM 
    table 
WHERE 
    id % 
    FLOOR(
        (SELECT count(1) FROM table) 
        / 10000
    ) = 0;

대상 행을 사용 가능한 총계로 나눈 결과가 정수가 아닌 경우 요청한 것보다 몇 개의 추가 행이 있으므로 결과 집합을 다음과 같이 정리하는 데 도움이되도록 LIMIT 절을 추가해야합니다.

SELECT * FROM 
    table 
WHERE 
    id % 
    FLOOR(
        (SELECT count(1) FROM table) 
        / 10000
    ) = 0
LIMIT 10000;

이것은 전체 스캔이 필요하지만 ORDER BY RAND보다 빠르며 내 의견으로는이 스레드에 언급 된 다른 옵션보다 이해하기가 더 간단합니다. 또한 DB에 쓰는 시스템이 배치로 행 세트를 작성하는 경우 예상 한대로 임의의 결과를 얻지 못할 수 있습니다.


하나의 임의의 레코드를 원한다면 (ID 사이에 간격이 있는지 여부에 관계없이) :

PREPARE stmt FROM 'SELECT * FROM `table_name` LIMIT 1 OFFSET ?';
SET @count = (SELECT
        FLOOR(RAND() * COUNT(*))
    FROM `table_name`);

EXECUTE stmt USING @count;

출처 : https://www.warpconduit.net/2011/03/23/selecting-a-random-record-using-mysql-benchmark-results/#comment-1266


나는 모든 대답을 살펴 보았고 아무도이 가능성에 대해 언급하지 않았다고 생각하며 그 이유를 모르겠습니다.

약간의 비용으로 최대한의 단순성과 속도를 원한다면 DB의 각 행에 대해 임의의 숫자를 저장하는 것이 합리적입니다. 추가 열을 만들고 random_number기본값을로 설정하십시오 RAND(). 이 열에 색인을 작성하십시오.

그런 다음 행을 검색 할 때 코드에서 임의의 숫자 (PHP, Perl 등)를 생성하고 열과 비교하십시오.

SELECT FROM tbl WHERE random_number >= :random LIMIT 1

하나의 행에 대해 매우 깔끔하지만 OP와 같은 10 개의 행에 대해 10 개의 별도 시간을 호출해야한다고 요청했습니다 (또는 즉시 나를 탈출하는 영리한 조정을해야합니다)


다음은 빠르고, 편견이 없으며 id 열과 무관해야합니다. 그러나 리턴 된 행 수가 요청 된 행 수와 일치한다고 보장하지는 않습니다.

SELECT *
FROM t
WHERE RAND() < (SELECT 10 / COUNT(*) FROM t)

설명 : 100 개 중 10 개의 행을 원한다고 가정하면 각 행은에 의해 달성 될 수있는 SELECTed를 얻을 확률이 1/10 WHERE RAND() < 0.1입니다. 이 방법은 10 개의 행을 보장하지 않습니다. 그러나 쿼리가 충분한 횟수로 실행되면 실행 당 평균 행 수는 약 10이되고 테이블의 각 행은 균등하게 선택됩니다.


이 쿼리를 사용합니다.

select floor(RAND() * (SELECT MAX(key) FROM table)) from table limit 10

쿼리 시간 : 0.016s


이것이 내가하는 방법입니다.

select * 
from table_with_600k_rows
where rand() < 10/600000
limit 10

나는 다른 테이블을 필요로하지 않기 때문에 그것을 좋아합니다. 쓰기가 쉽고 실행이 매우 빠릅니다.


아래의 간단한 쿼리를 사용하여 테이블에서 임의의 데이터를 가져옵니다.

SELECT user_firstname ,
COUNT(DISTINCT usr_fk_id) cnt
FROM userdetails 
GROUP BY usr_fk_id 
ORDER BY cnt ASC  
LIMIT 10

이것이 최선의 방법이라고 생각합니다 ..

SELECT id, id * RAND( ) AS random_no, first_name, last_name
FROM user
ORDER BY random_no

참고 URL : https://stackoverflow.com/questions/4329396/mysql-select-10-random-rows-from-600k-rows-fast

반응형