MySQL은 쿼리에서 ORDER BY 및 LIMIT를 어떻게 처리합니까?


250

다음과 같은 쿼리가 있습니다.

SELECT article FROM table1 ORDER BY publish_date LIMIT 20

ORDER BY는 어떻게 작동합니까? 모든 레코드를 주문한 다음 처음 20 개를 받거나 20 개 레코드를 가져 와서 publish_date필드 별로 주문 합니까?

마지막 기사 인 경우 가장 최근 기사 20 개를 얻을 수있는 것은 아닙니다.


6
일부 publish_date가 동일하면 순서대로 정렬해도 결과가 명확하지 않으므로 LIMIT페이지 매김에 사용하면 다른 페이지에서 동일한 항목을 얻을 수 있습니다!
Konrad Morawski

답변:


244

데이터베이스는 먼저 주문한 다음 처음 20 개를 가져옵니다. 데이터베이스는 WHERE이전 절의 내용도 처리 ORDER BY합니다.


1
그래서 타이밍은 동일합니까?
사르 아라파트

7
잘못된! LIMIT휴식 ORDER BY. 와 반환 잘못된 결과. 어떻게 든 반환 결과 집합을 다시 LIMITORDER BYLIMITORDER BY
Green

6
@ 그린, 착각 했어 설명을 위해 이것을 읽으십시오 : dev.mysql.com/doc/refman/5.7/en/limit-optimization.html ORDER BY 열이 색인 될 때 ​​LIMIT가 없을 때와 다른 순서로 레코드가 더 많이있을 수 있습니다. 해당 열에서 동일한 값을 가진 1 개 이상의 레코드
yitwail

1
이러한 문제에 대한 하나의 빠른 해결책은 열의 첫 번째 열 값이 여러 행에 대해 동일 할 때 데이터베이스가 행을 정렬하는 일관된 규칙을 갖도록 고유 한 값을 가짐으로써 순서에 따라 열을 하나 더 추가하는 것입니다.
rineez

37

LIMIT 절을 사용하여 SELECT 문에 의해 리턴되는 행 수를 제한 할 수 있습니다. LIMIT는 하나 또는 두 개의 숫자 인수를 취하는데, 둘 다 음이 아닌 정수 상수 여야합니다 (준비된 명령문을 사용할 때 제외).

두 개의 인수를 사용하면 첫 번째 인수는 반환 할 첫 번째 행의 오프셋을 지정하고 두 번째 인수는 반환 할 최대 행 수를 지정합니다. 초기 행의 오프셋은 0 (1 아님)입니다.

SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15

특정 오프셋에서 결과 집합의 끝까지 모든 행을 검색하려면 두 번째 매개 변수에 큰 숫자를 사용할 수 있습니다. 이 명령문은 96 번째 행에서 마지막 행까지의 모든 행을 검색합니다.

SELECT * FROM tbl LIMIT 95,18446744073709551615;

하나의 인수로 값은 결과 집합의 시작 부분에서 반환 할 행 수를 지정합니다.

SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows

즉, LIMIT row_count는 LIMIT 0, row_count와 같습니다.

http://dev.mysql.com/doc/refman/5.0/en/select.html 에 대한 모든 세부 사항


5-14 행을 검색하지 않습니까?
Adonis K. Kakoulidis 2018 년

@adonis 아니요, 그렇지 않습니다. 예는 MySQL 문서
dcaswell

5 번은 6 번째 줄입니다. 5 개의 행 (0-4)은 무시됩니다.
Phil Perry

1
그러나 ORDER BY없이 LIMIT를 사용하면 결과가 일치하지 않을 수 있습니다! 불행히도 LIMIT를 적용하기 전에 전체 결과 세트를 주문해야하거나 DBMS가 결과를 임의로 주문한 다음 해당 세트에 대해 OFFSET 및 LIMIT를 수행 할 수 있습니다. DBMS가 OFFSET 및 LIMIT를 기반으로 대체 쿼리 계획을 선택하여 임의의 순서로 인해 발생할 수 있음을 읽었습니다.
Barton

4
질문은 한계 및 주문을 요청하는 것입니다. 그러나 대답은이 질문과 전혀 관련이 없습니다
Shen liang

9

@James가 말한 것처럼 모든 레코드를 주문한 다음 처음 20 행을 가져옵니다.

따라서 처음 게시 된 20 개의 기사를 얻을 수 있으며 최신 기사는 표시되지 않습니다.

최신 기사를 원하면 최신 기사가 먼저 나오는 경우에 추가 desc하는 것이 좋습니다 order by publish_date.

결과를 오름차순으로 유지하고 10 개의 최신 기사 만 원하는 경우 mysql에 결과를 두 번 정렬하도록 요청할 수 있습니다.

아래의이 쿼리는 결과를 내림차순으로 정렬하고 결과를 10 (괄호 안의 쿼리)으로 제한합니다. 여전히 내림차순으로 정렬되며 만족스럽지 않으므로 mysql에 한 번 더 정렬하도록 요청합니다. 이제 마지막 행에서 최신 결과를 얻습니다.

select t.article 
from 
    (select article, publish_date 
     from table1
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

모든 열이 필요한 경우 다음과 같이 수행됩니다.

select t.* 
from 
    (select * 
     from table1  
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

데이터베이스를 검사하기 위해 수동으로 쿼리를 작성할 때이 기술을 사용합니다. 프로덕션 환경에서는 사용하지 않았지만 이제 벤치마킹하면 추가 정렬이 성능에 영향을 미치지 않습니다.


2
추가 정렬은 10 개의 행 / 항목으로 제한되므로 성능에 실질적으로 영향을 미치지 않습니다. :-). 일반적으로 메모리 내 테이블 (하위 선택이 생성하는)을 정렬하는 것은 수백만 행이 없거나 DBMS가 메모리에 맞지 않기 때문에 결과 세트를 디스크에 페이징하지 않는 한 매우 빠르며 거의 측정 할 수 없습니다. DBMS에 따라 쿼리를 중단 할 수도 있습니다).
Martin Kersten

7

이 경우 publish_date필드 에 적합한 인덱스가있는 경우 MySQL은 20 개의 레코드를 요청하기 위해 전체 인덱스를 스캔 할 필요가 없습니다. 인덱스의 시작 부분에 20 개의 레코드가 있습니다. 그러나 적합한 인덱스가 없으면 테이블을 전체 스캔해야합니다.

이에 대한 2009 년 의 MySQL 성능 블로그 기사가 있습니다.


7

가장 이른 또는 최신 레코드를 얻기 위해 주문 끝에 [asc] 또는 [desc]를 추가 할 수 있습니다.

예를 들어, 이렇게하면 먼저 최신 레코드가 제공됩니다

ORDER BY stamp DESC

다음에 LIMIT절을 추가하십시오ORDER BY


3
stackoverflow에 오신 것을 환영합니다. 나는 당신이 그 질문을 오해했을 것입니다. 나는 그들이 "정렬하는 방법"보다는 운영의 순서에 대해 묻고 있다고 믿는다. (그러나 질문이 이미 얼마 전에 답변 된 이래로 무례합니다.)
Leigh

5

이 코드를 사용할 수 있습니다. SELECT article FROM table1 ORDER BY publish_date LIMIT 0,10 여기서 0은 레코드의 시작 한계 및 10 개의 레코드 수입니다.


8
필요 하지 않습니다 . LIMIT 10의 줄임말입니다 LIMIT 0,10.
Lawrence Dol

2
네, LIMIT 0,10 필요하지만 할 수 있습니다 체감이 제한 10, 20 필요하지 않습니다
gaurangkathiriya을

3

LIMIT는 일반적으로 마지막 작업으로 적용되므로 결과가 먼저 정렬 된 다음 20으로 제한됩니다. 실제로 처음 20 개의 정렬 된 결과가 발견되면 정렬이 중지됩니다.


11
두 번째 문장은 첫 번째 문장에 반대됩니다. 결과가 반환되기 전에 정렬이 완료되었으므로 처음 20 개의 결과가 발견되면 정렬을 중지 할 수 없습니다. MySQL은 정렬이 완료된 후 처음 20 개의 결과 만 알 수 있습니다.
Tom

@Tom, 인덱스 열로 주문하면 실제로 가능합니다. 그것은 여기에서 설명하는 것 : dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
yitwail

-3

또한 LIMIT 구문은 데이터베이스에 따라 다릅니다 (예 :

mysql -제한 1, 2

postgres -한계 2 오프셋 1

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.