i MySQL, historiskt grupp av användes för att ge sortering samt. Om en fråga specificerade grupp av, resultatet sorterades som om ordning efter var närvarande i frågan.
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> infoga i T-värden (4,1),(3,2),(1,4),(2,2),(1,1),(1,5),(2,6),(2,1),(1,3),(3,4),(4,5),(3,6);
fråga OK, 12 rader påverkas (0,02 sek)
poster: 12 dubbletter: 0 varningar: 0
mysql-5,7 > välj id, summa( cnt) från T-gruppen med id;
+——+———-+
| id / summa (cnt) /
+——+———-+
| 1 | 13 |
| 2 | 9 |
| 3 | 12 |
| 4 | 6 |
+——+———-+
4 rader i set (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).
1
2
3
4
5
6
7
8
9
10
|
mysql-5.7> SELECT id, SUM(cnt) FROM t GROUP BY id DESC;
+——+———-+
| id / summa (cnt) /
+——+———-+
| 4 | 6 |
| 3 | 12 |
| 2 | 9 |
| 1 | 13 |
+——+———-+
4 rader i set, 1 Varning (0,00 sek)
|
detta har ändrats i 8.0 eftersom det inte längre stöder antingen implicit eller explicit sortering för grupp efter. I det här blogginlägget kommer jag att förklara varför denna förändring blev nödvändig och även det arbete som gjordes som en föregångare till denna förändring.
gruppera i MySQL
För att gruppera en uppsättning rader väljer MySQL optimizer olika metoder. En av dem är att sortera raderna innan de grupperas. Detta gör det enkelt att gruppera en grupp efter en annan. Det blir också billigt om det finns ett index som kan användas för att få sorterade rader. Om det inte finns något index kan MySQL optimizer fortfarande besluta att göra extern (filesort) sortering innan gruppering.
1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
33
34
35
|
MySQL-5.7> förklara välj sql_big_resultat id, summa(CNT) från t-gruppen med ID \G
*************************** 1. rad ***************************
id: 1
select_type: enkel
tabell: t
partitioner: NULL
ordning: alla
possible_keys: NULL
nyckel: 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
typ: index
possible_keys: id
nyckel: id
key_len: 10
ref: NULL
rader: 12
filtrerad: 100.00
Extra: använda index
1 rad i set, 1 Varning (0,00 sek)
|
som framgår av exemplet, innan du lägger till index i tabellen, använder MySQL extern sortering för att göra grupp efter. För exempelfrågan har jag tvingat planen genom att använda SQL_BIG_RESULTAT (eftersom MySQL inte väljer den här planen för datasetet vi har). Men MySQL skulle använda denna plan för att gruppera i avsaknad av ett index för att få sorterade rader och använda tillfällig tabell blir kostsamt på grund av stort antal grupper. När indexet har lagts till använder det indexet för att göra grupp av.
men att ha sorterat rader före gruppering är inte en nödvändighet. Optimizer kan besluta att använda sig av en tillfällig tabell för att göra det. Varje rad i denna tabell skulle vara en grupperad rad och med varje inkommande rad uppdateras raden som motsvarar den gruppen i tabellen. Sortering behövs inte här. Men som GROUP BY i MySQL förväntades Sortera, tvingades det att sortera de grupperade raderna även i det här fallet .
1
2
3
4
5
6
7
8
9
10
11
12
14
15
16
17
18
19
|
MySQL-5.7> ändra tabell t DROP INDEX id;
fråga OK, 0 rader påverkas (0,01 sek)
poster: 0 dubbletter: 0 varningar: 0
mysql-5,7> förklara välj id, summa(cnt) från T-gruppen med id \G
*************************** 1. rad ***************************
id: 1
select_type: enkel
tabell: t
partitioner: NULL
Typ: alla
possible_keys: NULL
nyckel: NULL
key_len: NULL
ref: NULL
rader: 12
filtrerad: 100.00
Extra: använda tillfällig; använda filesort
1 rad i uppsättning, 1 Varning (0.00 sek)
|
i exempelfrågan kan vi se att även om tillfällig tabell används, MySQL gör fortfarande extern sortering. Användare måste uttryckligen ange ORDER BY NULL för att låta MYSQL veta att gruppen inte behöver Sortera. Så en icke-standard (ORDER BY NULL) syntax behövdes för att motverka effekten av en annan icke-standard förlängning (grupp genom sortering). Det är mycket renare nu när vi har eliminerat den röra.
borttagning av implicit sortering för grupp av
någon gång tillbaka försökte jag fixa bugg 71804. Reportern förväntade sig att MySQL inte skulle göra den onödiga filen-Sortera den gjorde för grupp efter. Att försöka göra en patch för buggen fick oss att inse att optimering av denna speciella situation inte är mycket rakt fram på grund av stödet för implicit och explicit sortering av den gruppen som tillhandahålls. Så vi drog slutsatsen att innan denna optimering kunde göras, borde vi återfaktorera kod relaterad till sortering för grupp efter.
det första steget i att göra det var att ta bort den implicita sorteringen för GROUP BY. Som nämnts i användarhandboken här beslutades att ta bort stödet för det en tid tillbaka . Det har gjorts som en del av den nedåtgående indexfunktionen i 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
|
som framgår av exemplet ovan utförs inte sortering för frågan. Som ett resultat sorteras inte grupperade rader i slutresultatet. Om användare behöver sorterade rader måste de ange ordning efter i frågan.
i MySQL 5.7 och under versioner hittar användarna följande varning i manualen.
”GROUP BY
implicit sorterar som standard (det vill säga i frånvaro av ASC
eller DESC
beteckningar för GROUP BY
kolumner). Men förlitar sig på implicit GROUP BY
sortering (det vill säga sortering i frånvaro av ASC
eller DESC
beteckningar) eller explicit sortering för GROUP BY
(det vill säga genom att använda explicit ASC
eller DESC
beteckningar för GROUP BY
kolumner) är föråldrat. För att producera en viss sorteringsordning, ange enORDER BY
klausul. ”
borttagning av explicit sortering för grupp med
När det gällde borttagning av explicit sortering var det lite svårare att göra det. Vi kunde inte ta bort det om inte MySQL stödde ORDER BY med samlad. Samlad med ORDER BY var inte tillåtet i MySQL 5.7 och tidigare versioner. Så som ett alternativ skulle användarna använda GROUP BY ASC/desc för att få sorterade data med samlad (även om sorteringen var mycket restriktiv med super Aggregerade rader alltid placerade efter raderna som användes för att beräkna dem vid ASC och vice versa för desc). Vi var tvungna att lyfta denna begränsning innan vi tog bort stödet för explicit sortering för grupp efter.
MySQL tillåter nu beställning med samlad. Jag har förklarat i detalj hur man utnyttjar denna förbättring här. Som förklaras i samma blogg, om användarna vill ha exakt samma Sorteringsordning för nollor som för MySQL 5.7 för samlad, bör de använda funktionen gruppering() för att skriva om frågan på ett enkelt sätt.
så kort sagt har vi gjort följande saker som föregångare för att ta bort explicit sortering för grupp efter.
1. Lägga till gruppering () funktion
2. Borttagning av implicit sortering för grupp med
3. Tillåter beställning med samlad
och slutligen har vi tagit bort explicit sortering för grupp av i MySQL 8.0.13.
vi bad om samhällets åsikt för en tid tillbaka. Vi drog slutsatsen att användare som var medvetna om denna icke-standardiserade förlängning som MySQL tillhandahöll var bra med att det gick bort.
slutsats
Även om vi fortfarande har lite mer arbete att göra innan vi fixar bug 71804, är vi glada att vi fick det gjort. Låt oss veta dina tankar. Tack för att du använder MySQL!