MySQL 서버 블로그

MySQL,역사적으로 그룹에 의해 사용되었을 정렬니다. 쿼리가 GROUP BY 를 지정한 경우 결과는 order BY 가 쿼리에 존재하는 것처럼 정렬되었습니다.

5.7 – Implicit sort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

mysql-5.7> CREATE TABLE t (id INTEGER, cnt INTEGER);
Query OK, 0 rows affected (0.03 초)
mysql-5.7>삽입 t 값(4,1),(3,2),(1,4),(2,2),(1,1),(1,5),(2,6),(2,1),(1,3),(3,4),(4,5),(3,6);
쿼리 확인,12 영향을 받은 행(0.02 초)
레코드:12 중복:0 한 경고:0
mysql-5.7>SELECT id,SUM(cnt)에서 t 그룹 id;
+——+———-+
|id|SUM(cnt)|
+——+———-+
| 1 | 13 |
| 2 | 9 |
| 3 | 12 |
| 4 | 6 |
+——+———-+
4 행에서 설정(0 입니다.00 sec)

MySQL here implicitly sorts the results from GROUP BY (i.e. in the absence of ASC or DESC designators for GROUP BY columns ).

MySQL also supported explicit sorting with GROUP BY (i.e. by using explicit ASC or DESC designators for GROUP BY columns).

5.7 – Explicit sort

1
2
3
4
5
6
7
8
9
10

mysql-5.7> SELECT id, SUM(cnt) FROM t GROUP BY id DESC;
+——+———-+
|id|SUM(cnt)|
+——+———-+
| 4 | 6 |
| 3 | 12 |
| 2 | 9 |
| 1 | 13 |
+——+———-+
4 행에 설정,1 개의 경고(0.00sec)

이 변경되었 8.0 그것이 더 이상 지원하지 않거나 암시적 또는 명시적 분류에 대한 그룹이다. 이 블로그 게시물에서 나는이 변화가 필요하게 된 이유와이 변화의 선구자로서 수행 된 작업에 대해서도 설명 할 것입니다.

그룹 별 MySQL

행 집합을 그룹화하려면 MySQL optimizer 가 다른 방법을 선택합니다. 그 중 하나는 행을 그룹화하기 전에 행을 정렬하는 것입니다. 이렇게하면 한 그룹을 다른 그룹 다음에 그룹화하는 것이 쉽습니다. 또한 정렬 된 행을 가져 오는 데 사용할 수있는 인덱스가있는 경우 저렴 해집니다. 인덱스가없는 경우 MySQL optimizer 는 여전히 그룹화하기 전에 외부(파일 정렬)정렬을 수행하기로 결정할 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
mysql-5.7>설명을 선택 SQL_BIG_RESULT id,SUM(cnt)에서 t 그룹 id\G
*************************** 1. 행***************************
id:1
select_type:간단한
테이블:t
파티션:NULL
기:모든
possible_keys:NULL
키: NULL
key_len:NULL
ref: NULL
rows: 12
filtered: 100.00
Extra: Using filesort
1 row in set, 1 warning (0.01 sec)
mysql-5.7> ALTER TABLE t ADD INDEX (id, cnt);
Query OK, 0 rows affected (0.03 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql-5.7> EXPLAIN SELECT id, SUM(cnt) FROM t GROUP BY id \G
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: t
partitions: NULL
type:index
possible_keys:id
키:id
key_len:10
ref:NULL
행 12
여과:100.00
추가:를 사용하여 지수
1 행정,1 개의 경고(0.00sec)

에서 볼 수 있듯이 예를 추가하기 전에 인덱스 테이블,MySQL 사용하여 외부 분류를 수행하여 그룹. 예를 들어 쿼리가 강제 계획을 사용하여 SQL_BIG_RESULT(로 MySQL 선택하지 않을 것이다 이 계획에 대한 데이터 집 우리는). 하지만 MySQL 사용하는 것이 이 계획에는 그룹의 부재에서 지수를 얻으로 정렬과 행하여 임시 테이블이기 때문에 비용이 많이 들의 큰 숫자의 그룹입니다. 인덱스가 추가되면,그것은 그룹별로 할 인덱스를 사용하여 리조트.

그러나 그룹화 전에 행을 정렬하는 것은 필요하지 않습니다. 옵티마이 저는 그것을 할 임시 테이블을 사용하도록 결정할 수 있습니다. 이 테이블의 각 행은 그룹화 된 행이며 들어오는 각 행과 함께 테이블의 해당 그룹에 해당하는 행이 업데이트됩니다. 여기서 정렬은 필요하지 않습니다. 그러나 MySQL 의 GROUP BY 가 정렬 될 것으로 예상되었으므로이 경우에도 그룹화 된 행을 정렬해야했습니다.

를 사용하여 temp table

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mysql-5.7>ALTER TABLE t DROP INDEX id;
쿼리를 확인,0 행 영향을 받(0.01sec)
레코드:0Duplicates:0 한 경고:0
mysql-5.7>설명을 선택 id,SUM(cnt)에서 t 그룹 id\G
*************************** 1. 행***************************
id:1
select_type:간단한
테이블:t
파티션:NULL
유형:모든
possible_keys:NULL
키: NULL
key_len:NULL
ref:NULL
행: 12
여과:100.00
추가:를 사용하여 일시적이며 사용하여 filesort
1 행정,1 개의 경고(0.00sec)

에서 쿼리를 들어,우리는 볼 수 있지만 임시 테이블을 사용, MySQL 여전히 외부 분류를 제공합니다. 사용자는 mysql 이 GROUP BY 을 정렬 할 필요가 없다는 것을 알리기 위해 NULL 로 order 를 명시 적으로 지정해야합니다. 따라서 비표준(NULL 별 순서)구문이 다른 비표준 확장(정렬 별 그룹)의 효과를 방해하는 데 필요했습니다. 우리가 그 엉망진창을 제거한 것은 이제 훨씬 깨끗합니다.

그룹에 대한 암시 적 정렬 제거

얼마 전에 버그 71804 를 수정하려고했습니다. 기자는 MySQL 이 GROUP BY 에 대해 수행 한 불필요한 파일 정렬을 수행하지 않을 것으로 예상했습니다. 를 만들려고 노력에 대한 패치 버그를 만든 우리를 깨닫는 최적화 이 특정한 상황은 아주 똑바로 앞으로의 지원에 대한 암시적이고 명시적인 정렬이 그 그룹에 의해 제공됩니다. 그래서 우리는이 최적화가 이루어지기 전에 그룹 별 정렬과 관련된 코드를 다시 인수 분해해야한다고 결론지었습니다.그렇게하는 첫 번째 단계는 GROUP BY 에 대한 암시 적 정렬을 제거하는 것이 었습니다. 여기에 사용자 설명서에 언급 된 바와 같이,그것은 다시 약간의 시간에 대한 지원을 제거하기로 결정했다. 8.0 에서 내림차순 인덱스 기능의 일부로 수행되었습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
mysql>SELECT id,SUM(cnt)에서 t 그룹 id;
+——+———-+
|id|SUM(cnt)|
+——+———-+
| 4 | 6 |
| 3 | 12 |
| 1 | 13 |
| 2 | 9 |
+——+———-+
4 행에서 세트(0.00sec)
mysql>설명을 선택 id,SUM(cnt)에서 t 그룹 id\G
*************************** 1. 행*************************** 예를 들어,이 작업을 수행 할 수 있습니다.: t
파티션:NULL
유형:모든
possible_keys:NULL
키:NULL
key_len:NULL
ref:NULL
행 12
여과:100.00
추: 를 사용하여 임시
1 행정,1 개의 경고(0.00sec)

에서 볼 수 있듯이 예를 들어,위의 정렬 수행에 대한 쿼리를 실행합니다. 결과적으로 그룹화 된 행은 최종 결과에서 정렬되지 않습니다. 사용자가 정렬 된 행이 필요한 경우 쿼리에서 순서 기준을 지정해야합니다.MySQL5 에서

.7 이하 버전에서는 사용자가 설명서에서 다음 경고를 찾습니다.

GROUP BYASCDESCGROUP BYGROUP BYASCDESCGROUP BYASCDESCGROUP BYORDER BY절을 제공하십시오. “

제거의 명시적인 분류를 위한 그룹에 의해

에 왔을 때 그의 제거를 명시적 분류,그것은 조금 더 까다 그것을 할 수 있습니다. MySQL 이 롤업을 사용하여 ORDER BY 를 지원하지 않으면 제거 할 수 없습니다. MYSQL5.7 및 이전 버전에서는 ORDER BY 로 롤업이 허용되지 않았습니다. 그래서 이에 대한 대안으로 사용자가 사용하는 것에 의해 그룹 ASC/DESC 을 얻을 정렬된 데이터와 롤업(지만 정렬 아주 제한적으로 최고 집계 행 항상 위치한 후에 행를 계산하는데 사용의 경우에는 그들을 ASC 과 그 반대에 대한 내림차순). 우리는 GROUP BY 에 대한 명시 적 정렬에 대한 지원을 제거하기 전에이 제한을 해제해야했습니다.

MySQL 은 이제 롤업으로 순서를 허용합니다. 나는 여기에이 개선의 사용을 만드는 방법에 대해 자세히 설명했다. 로 설명에서 같은 블로그는 경우,사용자가 원하는 정확히 동일한의 정렬 순서 Null 의 것 MySQL5.7 에 대한 롤업,그들은 사용하여 그룹()함수를 다시 작성하는 쿼리에는 간단한 방법입니다.

그래서 요컨대 우리는 GROUP BY 에 대한 명시 적 정렬을 제거하는 선구자로서 다음과 같은 것들을 수행했습니다.1. GROUPING()함수

2 추가.

3 에 의한 그룹에 대한 암시 적 정렬의 제거. 롤업

로 ORDER BY 허용 그리고 마지막으로 MySQL8.0.13 에서 GROUP BY 에 대한 명시 적 정렬을 제거했습니다.

우리는 얼마 전에 지역 사회의 의견을 요청했습니다. 우리는 MySQL 이 제공 한이 비표준 확장을 알고 있던 사용자가 사라지는 것이 괜찮 았다고 결론지었습니다.

결론

지만 우리는 여전히 해야 할 일이 더하기 전에 우리는 버그 수정 71804,우리는 행복한 우리는 가지고 있습니다. 당신의 생각을 알려주십시오. MySQL 을 사용해 주셔서 감사합니다!

Related Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다