MySQL의 ORDER BY FIELD ()는 내부적으로 어떻게 작동합니까


37

ORDER BY절의 작동 방식과 FIELD()함수의 작동 방식을 이해합니다 . 내가 이해하고 싶은 것은 두 가지가 함께 작동하여 정렬하는 방법입니다. 행은 어떻게 검색되고 정렬 순서는 어떻게 파생됩니까?

+----+---------+
| id |  name   |
+----+---------+
|  1 | stan    |
|  2 | kyle    |
|  3 | kenny   |
|  4 | cartman |
+----+---------+ 

SELECT * FROM mytable WHERE id IN (3,2,1,4) ORDER BY FIELD(id,3,2,1,4)

위의 쿼리는

+----+---------+
| id |  name   |
+----+---------+
|  3 | kenny   |
|  2 | kyle    |
|  1 | stan    |
|  4 | cartman |
+----+---------+ 

ORDER BY 3, 2, 1, 4와 비슷한 말

질문

  • 내부적으로 어떻게 작동합니까?
  • MySQL은 어떻게 행을 가져오고 정렬 순서를 계산합니까?
  • MySQL은 id 열을 기준으로 정렬해야한다는 것을 어떻게 알 수 있습니까?

1
쿼리의 변화를 시도 : SELECT *, FIELD(id,3,2,1,4) AS f FROM mytable WHERE id IN (3,2,1,4);그런 다음 추가 ORDER BY f또는 ORDER BY FIELD(id,3,2,1,4)다시 시도하십시오.
ypercubeᵀᴹ

답변:


64

기록을 위해

SELECT * FROM mytable WHERE id IN (1,2,3,4) ORDER BY FIELD(id,3,2,1,4);

WHERE절의 목록을 주문할 필요가 없기 때문에 잘 작동합니다.

작동 방식은

  • FIELD () 는 검색하려는 값이 존재하는 경우 쉼표로 구분 된 목록의 색인 위치를 반환하는 함수입니다.

  • ORDER BY값이 무엇에 의해 평가 분야 () 반환

모든 종류의 멋진 주문을 만들 수 있습니다

예를 들어 IF () 함수 사용

SELECT * FROM mytable
WHERE id IN (1,2,3,4)
ORDER BY IF(FIELD(id,3,2,1,4)=0,1,0),FIELD(id,3,2,1,4);

이렇게하면 처음 4 개의 ID가 목록의 맨 위에 나타나고 그렇지 않으면 맨 아래에 나타납니다. 왜?

에서 ORDER BY0 또는 1을 얻습니다.

  • 첫 번째 열이 0이면 처음 4 개의 ID 중 하나가 나타나도록합니다
  • 첫 번째 열이 1이면 나중에 표시하십시오.

첫 번째 열에서 DESC로 뒤집어 봅시다

SELECT * FROM mytable
WHERE id IN (1,2,3,4)
ORDER BY IF(FIELD(id,3,2,1,4)=0,1,0) DESC,FIELD(id,3,2,1,4);

에서 ORDER BY여전히 0 또는 1을 얻습니다.

  • 첫 번째 열이 1이면 첫 번째 4 개의 ID 이외의 것을 표시하십시오.
  • 첫 번째 열이 0이면 처음 4 개의 ID가 원래 순서대로 표시됩니다.

실제 질문

이것에 대해 내부를 심각하게 원한다면 , 책의 189 쪽과 192쪽으로 가십시오

MySQL 내부

실제 심해 다이빙.

본질적으로 ORDER *order( ORDER BY식 트리) 라는 C ++ 클래스가 있습니다. 에서가 JOIN::prepare, *order라는 함수에 사용됩니다 setup_order(). 수업 중간에 왜 JOIN? 모든 쿼리, 단일 테이블에 대한 쿼리조차도 항상 JOIN으로 처리됩니다 (내 게시물 참조 JOIN 조건과 WHERE 조건 사이에 실행 차이가 있습니까? )

이 모든 소스 코드는 sql/sql_select.cc

분명히 ORDER BY나무는에 대한 평가를 보유 할 것입니다 FIELD(id,3,2,1,4). 따라서 숫자 0,1,2,3,4는 관련된 행을 참조하면서 정렬되는 값입니다.


1
이것은 뛰어난 설명입니다. 이 방법을 사용하여 3 개의 주문을 얻을 수있었습니다. 첫 번째 값은 세트의 최대 값, FIELD, FIELD 세트에없는 값의 다른 열입니다. 얼마 전에 내가 꿈꾸지 않았던 것. 실제로 어떻게 작동하는지 시간을내어 주셔서 감사합니다.
Lizardx

N에 모두 값 이 있다고 가정합니다 . 이 예에서는 . 이 쿼리가 최소한 작업 을 수행한다는 것을 올바르게 알고 있습니까 ? 각 계산은 각 행마다 한 번씩 비교하기 때문입니다. 그렇다면 이것이 상당히 느리다면 아마도 좋은 접근 방법이 아닐까요? INFIELDN=4~N^2FIELD~NN
Gherman

@Gherman이 FIELD()함수는 숫자 인덱스를 가지 O(1)므로 연산 이어야합니다 . 그래서 나는 다른 것을 보지 않고 행을 기반으로합니다. 필요한 반복 작업을 수행하는 것을 보지 못했습니다 . FIELD()idO(n)FIELD()GREATEST()
RolandoMySQLDBA

@RolandoMySQLDBA 내 포인트는 경우가 있다는 것입니다 FIELD가지고 N다음이 실행됩니다 비교할 인수 N비교. 그렇지 않으면 어떻게 하나의 숫자를 N다른 숫자 와 비교 O(N)합니까? 내가 생각할 수있는 유일한 가능성은 해시 또는 인수 트리와 같은 특수 데이터 구조를 통한 일종의 최적화입니다. 실제로 나는 IN그런 최적화가 있다는 것을 알고 있습니다. 에 대해 모르겠습니다 FIELD. "숫자 지수"는 무엇을 의미합니까?
Gherman

1
Hey @RaymondNijland, CASE 진술이 더 이해하기 쉽습니다.이 경우 구문 설탕은 글쓰기가 적습니다.
RolandoMySQLDBA

1

어쩌면 이것은 실제 코드와 너무 멀어서 원하는 수준에서 충분히 낮지 않을 것입니다.

MySQL이 인덱스를 사용하여 정렬 된 순서로 데이터를 검색 할 수없는 경우 선택한 모든 열과 추가 데이터가있는 임시 테이블 / 결과를 생성합니다. 그중 하나는 각 행의 ORDER BY 표현식 값 결과를 저장하는 일종의 열입니다. 그런 다음이 tmp 테이블을 정렬 할 열이 포함 된 "filesort"루틴으로 보냅니다. 그런 다음 행이 정렬 순서대로 정렬되어 하나씩 열을 선택하고 선택한 열을 반환 할 수 있습니다.


이 설명은 FIELD계산에서 기능이 어떻게 수행 되는지 고려하지 않습니다 . 성능에 큰 영향을 줄 수 있습니다.
Gherman

@Gherman 매우 긴 인수 목록을 사용하지 않는 한 그렇게 생각하지 않습니다 (함수가 인수의 수와 선형 이기 때문에 . 데이터 액세스는 간단한 비교보다 훨씬 느립니다.
jkavalik

예, 긴 인수 목록. 이 예제에는 레코드 수만큼 많은 인수가 있습니다.
Gherman

수백 또는 수천 개만 레이블을 지정하면 어쨌든 다른 문제가 발생합니다 (질의 크기 등)
jkavalik

왜 수백 개의 결과가 아닌가? 많은가요?
Gherman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.