[SQL] MySQL은 : ORDER BY RAND 대안 ()
SQLMySQL은 : ORDER BY RAND 대안 ()
나는 몇 RAND BY의 MySQL의 ORDER 대안 () 함수에 대해 읽었습니다,하지만 대안의 대부분은 단일 무작위 결과를 필요한 곳에 적용됩니다.
사람이 어떻게 쿼리를 최적화하는 어떤 생각을 가지고 있는가하는 이와 같은 반환 여러 무작위 결과 :
SELECT u.id,
p.photo
FROM users u, profiles p
WHERE p.memberid = u.id
AND p.photo != ''
AND (u.ownership=1 OR u.stamp=1)
ORDER BY RAND()
LIMIT 18
해결법
-
==============================
1.이 솔루션은 인덱스 컬럼을 사용하여 가장 잘 작동합니다.
이 솔루션은 인덱스 컬럼을 사용하여 가장 잘 작동합니다.
여기에 10 개 로우로 표시된 간단한 예 최적화 된 질의 벤치이다.
최적화 된 :이 300ms
SELECT g.* FROM table g JOIN (SELECT id FROM table WHERE RAND() < (SELECT ((4 / COUNT(*)) * 10) FROM table) ORDER BY RAND() LIMIT 4) AS z ON z.id= g.id
제한 액수에 대한 참고 사항 : 제한 4 4 / 수 (*). 4S는 같은 수 있어야합니다. 많은 당신의 반환이 그만큼 속도에 영향을주지 않는 방법 변경. 제한 4 1000 한계 기준은 동일하다. 제한 만은 600ms의로 채택했다
에 대한 가입주의 : 단지 ID를 무작위 화하는 것은 빠른 전체 행을 무작위보다. 이 메모리에 전체 행을 복사므로 다음을 랜덤. 는 tablescans을 방지하기 위해 하위 쿼리 그것과 연결되는 모든 테이블이 될 수 있습니다 가입 할 수 있습니다.
참고 where 절 : 무작위되는 결과의 양을 아래로 한계를 계산하는 곳. 이 결과의 비율을 소요하고 전체 테이블이 아니라 그들을 정렬합니다.
참고 하위 쿼리 다음 일을 조인 및 추가 조항 조건이 서브 쿼리와 subsubquery에 그들 모두를 배치해야합니다. 정확한 계산을 다시 올바른 데이터를 당깁니다.
최적화되지 않은 : 1200ms
SELECT g.* FROM table g ORDER BY RAND() LIMIT 4
총
4 배 빠른 순서와 랜드에 의해 (). 이 솔루션은 인덱스 열이있는 테이블로 작업 할 수 있습니다.
CONS
그것은 복잡한 쿼리와 조금 복잡하다. 하위 쿼리에서이 개 코드베이스를 유지하기 위해 필요
-
==============================
2.여기에 대안이다,하지만 여전히 RAND ()를 사용하여 기반으로합니다 :
여기에 대안이다,하지만 여전히 RAND ()를 사용하여 기반으로합니다 :
SELECT u.id, p.photo, ROUND(RAND() * x.m_id) 'rand_ind' FROM users u, profiles p, (SELECT MAX(t.id) 'm_id' FROM USERS t) x WHERE p.memberid = u.id AND p.photo != '' AND (u.ownership=1 OR u.stamp=1) ORDER BY rand_ind LIMIT 18
이것은 약간 더 복잡하지만 임의 INT 값의 더 나은 분포를 가지고 :
SELECT u.id, p.photo, FLOOR(1 + RAND() * x.m_id) 'rand_ind' FROM users u, profiles p, (SELECT MAX(t.id) - 1 'm_id' FROM USERS t) x WHERE p.memberid = u.id AND p.photo != '' AND (u.ownership=1 OR u.stamp=1) ORDER BY rand_ind LIMIT 18
-
==============================
3.그것은 RAND () 방법으로 가장 빠르게,하지만 빠르게 다음 일반적인 ORDER되지 않습니다 :
그것은 RAND () 방법으로 가장 빠르게,하지만 빠르게 다음 일반적인 ORDER되지 않습니다 :
당신은 인덱스 열을 찾기 위해 그것을 사용하는 경우 ORDER BY RAND ()는 느린 없습니다. 이 같은 하나 개의 쿼리에서 모든 ID를 수행 할 수 있습니다
SELECT id FROM testTable ORDER BY RAND();
임의 ID의 시퀀스를 얻고, 다른 SELECT 또는 매개 변수를 다른 쿼리에 결과에 가입 :
SELECT t.* FROM testTable t JOIN (SELECT id FROM `testTable` ORDER BY RAND()) AS z ON z.id= t.id WHERE t.isVisible = 1 LIMIT 100;
귀하의 경우에는 다음과 같습니다
SELECT u.id, p.photo FROM users u, profiles p JOIN (SELECT id FROM users ORDER BY RAND()) AS z ON z.id = u.id WHERE p.memberid = u.id AND p.photo != '' AND (u.ownership=1 OR u.stamp=1) LIMIT 18
아주 무딘 방법 그리고 그것은 매우 큰 테이블하지 적절한 될 수 있지만, 여전히 더 빨리 일반 RAND 이상 ()입니다. 나는 20 배 빠른 속도로 거의 400000 3000 개 임의의 행을 검색 실행 시간을 얻었다.
-
==============================
4.나는이 오늘로 달려 조인과 함께 'DISTINCT'사용하려고했지만, RAND는 각 가입 행 구별하기 때문에 나는 가정 중복을 얻고 있었다. 내가 조금 주위 뒤죽박죽하고 해결책을 발견,이 같은 작품 :
나는이 오늘로 달려 조인과 함께 'DISTINCT'사용하려고했지만, RAND는 각 가입 행 구별하기 때문에 나는 가정 중복을 얻고 있었다. 내가 조금 주위 뒤죽박죽하고 해결책을 발견,이 같은 작품 :
SELECT DISTINCT t.id, t.photo FROM (SELECT u.id, p.photo, RAND() as rand FROM users u, profiles p WHERE p.memberid = u.id AND p.photo != '' AND (u.ownership=1 OR u.stamp=1) ORDER BY rand) t LIMIT 18
-
==============================
5.열을 생성하거나 열 랜덤 (실시 예 PHP 용 생성) 번호 순서와 선택에 참여.
열을 생성하거나 열 랜덤 (실시 예 PHP 용 생성) 번호 순서와 선택에 참여.
-
==============================
6.랜드에 의해 주문 (), 큰 테이블에 매우 느립니다
랜드에 의해 주문 (), 큰 테이블에 매우 느립니다
나는 PHP 스크립트에서 다음 해결 방법을 찾을 수 :
Select min(id) as min, max(id) as max from table;
그리고 PHP에서 무작위로 할
$rand = rand($min, $max);
그때
'Select * from table where id>'.$rand.' limit 1';
매우 빠른 것 같다 ....
-
==============================
7.내가 사용하고이 솔루션은 아래 링크에 게시됩니다 : 내가 어떻게 MySQL을의 ORDER BY RAND () 함수를 최적화 할 수 있습니다?
내가 사용하고이 솔루션은 아래 링크에 게시됩니다 : 내가 어떻게 MySQL을의 ORDER BY RAND () 함수를 최적화 할 수 있습니다?
난 안 후 1 기수 1의 경우 사용자 테이블, 당신의 프로파일 테이블보다 크게 될 것입니다 가정입니다.
그렇다면, 내가 먼저 프로파일 테이블에 가입하기 전에 사용자 테이블에 임의의 선택을 할 것입니다.
첫 번째 선택을 할 :
SELECT * FROM users WHERE users.ownership = 1 OR users.stamp = 1
그런 다음이 풀에서, 계산 가능성을 통해 임의의 행을 선택하십시오. 테이블은 M 행을 가지고 있으며, 당신이 N 임의의 행을 선택하려는 경우, 무작위 선택의 확률은 N / M해야합니다. 그 후:
SELECT * FROM ( SELECT * FROM users WHERE users.ownership = 1 OR users.stamp = 1 ) as U WHERE rand() <= $limitCount / (SELECT count(*) FROM users WHERE users.ownership = 1 OR users.stamp = 1)
N은 $ limitCount이고 M은 테이블의 행 수를 계산 부질된다. 우리가 확률에 노력하고 있습니다 때문에, 반환 된 행의 $ limitCount 미만을 가질 수 있습니다. 따라서 우리는 무작위로 풀 크기를 증가시키는 요인에 의해 N을 곱해야한다.
즉 :
SELECT* FROM ( SELECT * FROM users WHERE users.ownership = 1 OR users.stamp = 1 ) as U WHERE rand() <= $limitCount * $factor / (SELECT count(*) FROM users WHERE users.ownership = 1 OR users.stamp = 1)
더 무작위 풀 크기 (예 : 1.5) 감소에 나는 보통 세트 $ 인자 = 2. 당신은 낮은 값으로 요소를 설정할 수 있습니다.
이 시점에서, 우리는 이미 약 2N 크기 아래로 M 사이즈 테이블을 제한한다. 여기에서 우리는 다음 LIMIT 가입 할 수 있습니다.
SELECT * FROM ( SELECT * FROM ( SELECT * FROM users WHERE users.ownership = 1 OR users.stamp = 1 ) as U WHERE rand() <= $limitCount * $factor / (SELECT count(*) FROM users WHERE users.ownership = 1 OR users.stamp = 1) ) as randUser JOIN profiles ON randUser.id = profiles.memberid AND profiles.photo != '' LIMIT $limitCount
큰 테이블에서이 쿼리는 RAND ()의 요청에 의한 정상적인 주문을 능가 할 것이다.
도움이 되었기를 바랍니다!
from https://stackoverflow.com/questions/1823306/mysql-alternatives-to-order-by-rand by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 어떻게 SQL 서버에서 중복 행을 삭제하려면? (0) | 2020.03.09 |
---|---|
[SQL] 어떻게 Access에서 서로 다른 상황에서 VBA에서 매개 변수를 사용합니까? (0) | 2020.03.09 |
[SQL] 어떻게 카테고리 별 최신 네 개의 항목을 선택하려면? (0) | 2020.03.09 |
[SQL] SQL 다중 열 정렬 (0) | 2020.03.09 |
[SQL] 어떻게 MySQL의에서 재귀 SELECT 쿼리를 할까? (0) | 2020.03.09 |