MySQL Server Blog

I MySQL ble HISTORISK GRUPPE AV brukt til å gi sortering også. HVIS en spørring angitt GRUPPE ETTER, ble resultatet sortert som OM ORDER BY var til stede i spørringen.

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 sek)
mysql-5.7> SETT inn i T-VERDIER (4,1),(3,2),(1,4),(2,2),(1,1),(1,5),(2,6),(2,1),(1,3),(3,4),(4,5),(3,6);
Spørring OK, 12 rader berørt (0.02 sek)
Poster: 12 Duplikater: 0 Advarsler: 0
mysql-5.7> VELG id, SUM(CNT) fra T-GRUPPEN etter id;
+——+———-+
| id / SUM (cnt) /
+——+———-+
| 1 | 13 |
| 2 | 9 |
| 3 | 12 |
| 4 | 6 |
+——+———-+
4 rader i sett (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 rader i sett, 1 advarsel (0.00 sek)

dette har endret seg i 8.0 da det ikke lenger støtter implisitt eller eksplisitt sortering FOR GRUPPE AV. I dette blogginnlegget vil jeg forklare hvorfor denne endringen ble nødvendig og også arbeidet som en forløper for denne endringen.

GRUPPE AV I MySQL

For å gruppere et sett med rader velger MySQL optimizer forskjellige metoder. En av dem er å sortere radene før de grupperes. Dette gjør det enkelt å gruppere en gruppe etter hverandre. Det blir også billig hvis det er en indeks som kan brukes til å få sorterte rader. Hvis det ikke er noen indeks, Kan MySQL optimizer fortsatt bestemme seg for å gjøre ekstern (filesort) sortering før gruppering.

bruke indeksen til å sortere

mysql-5.7> forklar velg sql_big_result id, sum(cnt) fra t-gruppen ved id \g
*************************** 1. row ***************************
id: 1
select_type: ENKEL
tabell: t
partisjoner: NULL
rekkefølge: alle
possible_keys: NULL
nøkkel: 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:
type: index
possible_keys: id
nøkkel: id
key_len: 10
ref: NULL
rader: 12
filtrert: 100.00
Ekstra: bruk av indeks
1 rad i sett, 1 advarsel (0.00 sek)

1
3
4
5
6/div>

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

som vist i EKSEMPLET, før du legger til indeks i tabellen, bruker mysql ekstern sortering for å gjøre gruppe etter. For eksempelspørringen har jeg tvunget planen ved å bruke SQL_BIG_RESULT(Som MySQL vil ikke velge denne planen for datasettet vi har). Men MySQL ville bruke denne planen til å gruppere i fravær av en indeks for å få sorterte rader og bruke midlertidig tabell blir kostbart på grunn av stort antall grupper. Når indeksen er lagt til, tyr den til å bruke indeksen TIL Å GJØRE GRUPPE ETTER.

men å ha sortert rader før gruppering er ikke en nødvendighet. Optimizer kan velge å gjøre bruk av en midlertidig tabell for å gjøre det. Hver rad i denne tabellen vil være en gruppert rad, og med hver innkommende rad oppdateres raden som svarer til den gruppen i tabellen. Sortering er ikke nødvendig her. MEN SOM GRUPPE AV I MySQL var forventet å sortere, ble det tvunget til å sortere de grupperte radene selv i dette tilfellet .

bruke temp tabell

mysql-5.7 > ALTER TABLE T DROP INDEX id;
Spørring OK, 0 rader berørt (0.01 sek)
Poster: 0 Duplikater: 0 Advarsler: 0
mysql-5.7> FORKLAR VELG id, SUM (CNT) FRA T-GRUPPEN etter id \ G
*************************** 1. row ***************************
id: 1

select_type: ENKEL

tabell: t
partisjoner: NULL
type: alle
possible_keys: NULL
nøkkel: NULL
key_len: NULL
ref: NULL
rader: 12
filtrert: 100.00
Ekstra: bruk midlertidig; Bruk filesort
1 rad i sett, 1 advarsel (0.00 sek)
1
3
4
5
6/div>

7
8
9
10
11
12
13
14
15
16
17
18
19

i eksempelspørringen kan vi se at selv om midlertidig tabell brukes, mysql gjør fortsatt ekstern sortering. Brukere må eksplisitt spesifisere ORDER BY NULL for å la MYSQL vite AT GRUPPEN av trenger ikke å sortere. Så en ikke-standard (ORDER BY NULL) syntaks var nødvendig for å motvirke effekten av en annen ikke-standard forlengelse (GRUPPE ved sortering). Det er mye renere nå som vi har eliminert det rotet.Fjerning av implisitt sortering FOR GRUPPE AV

For en tid tilbake prøvde jeg å fikse feil 71804. Reporteren forventet MySQL å ikke gjøre unødvendig fil-sortere det gjorde FOR GROUP BY. Prøver å lage en patch for feilen gjort oss klar over at optimalisering av denne situasjonen er ikke veldig rett frem på grunn av støtte for implisitt og eksplisitt sortering SOM GRUPPE ved gitt. Så vi konkluderte med at før denne optimaliseringen kunne gjøres, bør vi re-factoring kode relatert til sortering FOR GRUPPE AV.

det første trinnet i å gjøre det var å fjerne den implisitte sorteringen FOR GROUP BY. Som nevnt i brukerhåndboken her, ble det besluttet å fjerne støtten for det litt tid tilbake . Det har blitt gjort som en del av den synkende indeksfunksjonen i 8.0.

8.0 – ingen implisitt sort

mysql> VELG id, SUM (cnt) FRA T GRUPPE av id;
+——+———-+
| id / SUM (cnt) /
+——+———-+
| 4 | 6 |
| 3 | 12 |
| 1 | 13 |
| 2 | 9 |
+——+———-+
4 rader i sett (0,00 sek)
mysql> FORKLAR VELG id, SUM(cnt) FRA T-GRUPPEN ved id \ G
*************************** 1. row ***************************
id: 1
select_type: ENKEL
tabell: alle
possible_keys: NULL
nøkkel: NULL
key_len: NULL
ref: NULL
rader: 12
filtrert: 100.00
Ekstra: Bruker midlertidig
1 rad i sett, 1 advarsel (0.00 sek)

1
2
3
4
5
7
8
10
11/div>

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

som vist i EKSEMPLET ovenfor, utføres ikke sortering for spørringen. Som et resultat sorteres ikke grupperte rader i sluttresultatet. Hvis brukere trenger sorterte rader, må DE angi ORDER BY i spørringen.

I MySQL 5.7 og under versjoner finner brukerne følgende advarsel i håndboken.

«GROUP BY sorterer implisitt som standard (det vil si i fravær av ASC eller DESC betegnelser for GROUP BY kolonner). Men stole på implisitt GROUP BY sortering (det vil si sortering i fravær av ASC eller DESC betegnelser) eller eksplisitt sortering for GROUP BY (det vil si ved å bruke eksplisitt ASC eller DESC designatorer for GROUP BY kolonner) er utdatert. For å produsere en gitt sorteringsrekkefølge, oppgi enORDER BY – klausul. «

Fjerning av eksplisitt sortering FOR GRUPPE ved

Når det kom til fjerning av eksplisitt sortering, var det litt vanskeligere å gjøre det. Vi kunne ikke fjerne det med Mindre MySQL støttet ORDRE MED SAMLEOPPDATERING. ROLLUP MED ORDER BY var ikke tillatt I MySQL 5.7 og tidligere versjoner. Så, som et alternativ, ville brukerne bruke GROUP BY ASC / DESC for å få sorterte data med SAMLEOPPDATERING (selv om sorteringen var svært restriktiv med superaggregatrader alltid plassert etter radene som ble brukt til å beregne DEM i TILFELLE ASC og omvendt FOR DESC). Vi måtte løfte denne begrensningen før vi fjernet støtten for eksplisitt sortering FOR GRUPPE AV.

MySQL tillater NÅ ORDRE MED MED SAMLEOPPDATERING. Jeg har forklart i detalj om hvordan å gjøre bruk av denne forbedringen her. Som forklart i samme blogg, hvis brukerne vil ha nøyaktig samme sorteringsrekkefølge Av NULLs som For MySQL 5.7 FOR SAMLEOPPDATERING, bør de bruke GRUPPERINGSFUNKSJONEN () til å skrive spørringen på en enkel måte.

så kort sagt har vi gjort følgende ting som forløpere til å fjerne eksplisitt sortering FOR GRUPPE AV.

1. Legge TIL GRUPPERING () funksjon

2. Fjerning av implisitt sortering FOR GRUPPE med

3. Tillater ORDRE MED MED ROLLUP

og til slutt har vi fjernet eksplisitt sortering FOR GROUP BY I MySQL 8.0.13.

Vi ba om fellesskapets mening for en tid tilbake. Vi konkluderte med at brukere som var klar over denne ikke-standardutvidelsen Som MySQL ga, var fine med at Den gikk bort.

Konklusjon

Selv om vi fortsatt har litt mer arbeid å gjøre før vi fikser feil 71804, er vi glade for at vi fikk dette gjort. Gi oss beskjed om dine tanker. Takk for at Du bruker MySQL!

Related Posts

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *