MySQL, historiallisesti ryhmä BY käytettiin tarjoamaan lajittelu samoin. Jos kyselyn määritetty ryhmä, tulos lajiteltiin ikään kuin järjestyksessä oli läsnä kyselyssä.
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> lisää T-arvoihin (4,1),(3,2),(1,4),(2,2),(1,1),(1,5),(2,6),(2,1),(1,3),(3,4),(4,5),(3,6);
Query OK, 12 riviä vaikuttaa (0, 02 sek)
tietueet: 12 päällekkäistä: 0 Varoitukset: 0
MySQL-5, 7> valitse id, SUM (cnt) t-ryhmästä id: n mukaan;
+——+———-+
/ id / SUM (cnt) /
+——+———-+
| 1 | 13 |
| 2 | 9 |
| 3 | 12 |
| 4 | 6 |
+——+———-+
4 riviä sarjassa (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 / SUM (cnt) /
+——+———-+
| 4 | 6 |
| 3 | 12 |
| 2 | 9 |
| 1 | 13 |
+——+———-+
4 riviä setissä, 1 varoitus (0,00 sek)
|
Tämä on muuttunut 8.0: ssa, koska se ei enää tue joko implisiittistä tai eksplisiittistä ryhmittelyä. Tässä blogikirjoituksessa kerron, miksi tämä muutos tuli tarpeelliseksi ja myös tämän muutoksen edeltäjänä tehty työ.
ryhmä MySQL: ssä
ryhmittääkseen rivijoukon, MySQL optimizer valitsee erilaisia menetelmiä. Yksi niistä on lajitella rivit ennen ryhmittelyä. Näin on helppo ryhmitellä ryhmä toisensa jälkeen. Se tulee myös edullinen, jos on indeksi, jolla voitaisiin saada lajiteltuja rivejä. Jos indeksiä ei ole, MySQL optimizer voi silti päättää tehdä ulkoisen (filesort) lajittelun ennen ryhmittelyä.
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
35
|
MySQL-5.7 > selitä t-ryhmästä sql_big_result id, sum(CNT) id \g
*************************** 1. rivi ***************************
id: 1
select_type: SIMPLE
taulukko: t
osiot: NULL
order: ALL
possible_keys: NULL
key: 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
key: id
ref: NULL
rivit: 12
suodatettu: 100.00
Extra: Using index
1 rivi setissä 1 varoitus (0,00 sek)
|
kuten esimerkissä nähdään, ennen indeksin lisäämistä taulukkoon MySQL käyttää ulkoista lajittelua ryhmittelyyn. Esimerkiksi kysely olen pakottanut suunnitelman käyttämällä SQL_BIG_RESULT (koska MySQL ei valitse tätä suunnitelmaa aineisto meillä). Mutta MySQL käyttäisi tätä suunnitelmaa ryhmitellä ilman indeksiä saada lajiteltu rivit ja väliaikaisen taulukon käyttäminen tulee kalliiksi, koska suuri määrä ryhmiä. Kun indeksi on lisätty, se turvautuu käyttää indeksiä tehdä ryhmä.
mutta rivien lajittelu ennen ryhmittelyä ei ole välttämätöntä. Optimizer voi päättää käyttää väliaikaisen pöydän tehdä sen. Jokainen rivi tässä taulukossa olisi ryhmitelty rivi, ja jokaisella tulevalla rivillä päivitetään taulukon kyseistä ryhmää vastaava rivi. Lajittelua ei täällä tarvita. Kuitenkin, kuten ryhmä MySQL odotettiin lajitella, se oli pakko lajitella ryhmitelty rivit tässäkin tapauksessa .
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;
Query OK, 0 riviä vaikuttaa (0,01 sek)
tietueet: 0 päällekkäisyyksiä: 0 Varoitukset: 0
MySQL-5.7> selitä t-ryhmästä id \g
*************************** 1. rivi ***************************
id: 1
select_type: SIMPLE
taulukko: t
osiot: NULL
type: kaikki
possible_keys: NULL
key: NULL
ref: NULL
rivit: 12
suodatettu: 100.00
Extra: käytetään väliaikaista; käytetään filesort
1 rivi setissä, 1 varoitus (0.00 sek)
|
esimerkkikyselyssä voidaan nähdä, että vaikka tilapäinen taulukkoa käytetään, MySQL tekee vielä ulkoista lajittelua. Käyttäjien olisi nimenomaisesti määrittää järjestyksessä NULL antaa MYSQL tietää, että ryhmä ei tarvitse lajitella. Tarvittiin siis epästandardi (ORDER BY NULL) syntaksi, joka kumosi toisen epästandardin laajennuksen vaikutuksen (ryhmä lajittelemalla). Se on paljon puhtaampaa nyt, kun olemme poistaneet sen sotkuisuuden.
implisiittisen ryhmittelyn poistaminen
jokin aika sitten yritin korjata bugia 71804. Toimittaja odotti MySQL ei tee tarpeetonta tiedosto-lajitella se teki ryhmä kerrallaan. Yrittää tehdä korjaus vika sai meidät ymmärtämään, että optimointi tässä tilanteessa ei ole kovin suoraviivaista, koska tuki implisiittinen ja eksplisiittinen lajittelu, että ryhmä edellyttäen. Joten päätimme, että ennen kuin tämä optimointi voitaisiin tehdä, meidän pitäisi uudelleen factoring koodi liittyy lajittelu ryhmä.
ensimmäinen askel tässä oli poistaa implisiittinen lajittelu ryhmittäin. Kuten tässä käyttöohjeessa mainittiin, sen tuki päätettiin poistaa jokin aika sitten . Se on tehty osana laskeva indeksi ominaisuus 8.0.
1
2
3
4
5
6
7
9
10
11
12
13
14
15
16
17
18
19
20
21
22
div> 23 24
25
26
|
mysql> SELECT id, SUM (cnt) FROM t GROUP BY id;
+——+———-+
/ id / SUM (cnt) /
+——+———-+
| 4 | 6 |
| 3 | 12 |
| 1 | 13 |
| 2 | 9 |
+——+———-+
4 riviä setissä (0,00 sek)
MySQL> selitä T-ryhmän SELECT id, SUM(cnt) id \g
*************************** 1. rivi ***************************
id: 1
select_type: yksinkertainen
taulukko: t
osiot: NULL
type: ALL
possible_keys: NULL
key: NULL
ref: NULL
rivit: 12
suodatettu: 100.00
Extra: käyttämällä väliaikaista
1 rivi setissä, 1 varoitus (0,00 sek)
|
kuten yllä olevassa esimerkissä nähdään, kyselyä varten ei suoriteta lajittelua. Tämän seurauksena ryhmitettyjä rivejä ei järjestetä lopputulokseen. Jos käyttäjät tarvitsevat lajiteltuja rivejä,heidän on määritettävä järjestys kyselyssä.
MySQL: ssä 5.7 ja alla versiot, käyttäjät löytävät seuraavan varoituksen käyttöohjeessa.
”GROUP BY
lajittelee implisiittisesti oletusarvoisesti (eli jos ASC
tai DESC
tunnukset GROUP BY
sarakkeet). Vedoten kuitenkin implisiittiseen GROUP BY
lajitteluun (eli lajitteluun ilman ASC
tai DESC
tunnisteita) tai eksplisiittiseen lajitteluun GROUP BY
(eli käyttämällä eksplisiittistä ASC
tai DESC
GROUP BY
sarakkeet) on vanhentunut. Tietyn järjestysjärjestyksen tuottamiseksi annetaan ORDER BY
lauseke. ”
ryhmän eksplisiittisen lajittelun poistaminen
kun oli kyse eksplisiittisen lajittelun poistamisesta, sen tekeminen oli hieman hankalampaa. Emme voineet poistaa sitä, ellei MySQL tukenut järjestyksessä ROLLUP. ROLLUP ORDER BY ei ollut sallittua MySQL 5.7 ja aiemmissa versioissa. Joten, vaihtoehtona, käyttäjät käyttäisivät ryhmä ASC / DESC saada lajiteltu tiedot ROLLUP (vaikka lajittelu oli hyvin rajoittava super yhteenlaskettu rivit aina jälkeen rivit käytetään laskea ne tapauksessa ASC ja päinvastoin DESC). Meidän oli poistettava tämä rajoitus ennen kuin poistimme tuen selkeälle ryhmittelylle.
MySQL sallii nyt tilauksen ROLLUPILLA. Olen selittänyt yksityiskohtaisesti, miten tätä parannusta voidaan hyödyntää täällä. Kuten samassa blogissa on selitetty, jos käyttäjät haluavat täsmälleen saman Nullien lajittelujärjestyksen kuin MySQL 5.7: n RULLAUKSESSA, heidän tulisi käyttää RYHMITTELYTOIMINTOA() kyselyn uudelleen kirjoittamiseen yksinkertaisella tavalla.
joten lyhyesti sanottuna olemme tehneet seuraavat asiat esiasteina poistamalla eksplisiittisen lajittelun ryhmä kerrallaan.
1. Lisäämällä ryhmittely () funktio
2. Implisiittisen ryhmittelyn poistaminen
3. Mahdollistaa järjestyksessä ROLLUP
ja lopuksi olemme poistaneet eksplisiittinen lajittelu ryhmä MySQL 8.0.13.
pyysimme yhteisöjen mielipidettä jokin aika sitten. Tulimme siihen tulokseen, että käyttäjät, jotka olivat tietoisia tästä ei-standardi laajennus, että MySQL tarjotaan olivat kunnossa se menee pois.
johtopäätös
vaikka meillä on vielä jonkin verran tehtävää ennen kuin korjaamme vian 71804, olemme iloisia, että saimme tämän tehtyä. Kerro meille ajatuksesi. Kiitos käyttää MySQL!