Sziasztok!
Van egy elég bonyolult sok subqueryt tartalmazó lekérdezésem.
SELECT
C.ID,
C.NEVROVID AS KOD,
C.NEV AS MEGNEVEZES,
C.KISZERELES_2_VALTOSZAM AS KARTONOS,
C.KISZERELES_1_VALTOSZAM AS DOBOZOS
FROM CIKKTORZS C,
(SELECT ACS.*
FROM AR_CIKK_OSSZERENDELO ACS,
(SELECT
ID_CIKK,
MAX(DATUM_TOL) DATUM_TOL
FROM AR_CIKK_OSSZERENDELO
GROUP BY ID_CIKK) ACF
WHERE ACS.ID_CIKK = ACF.ID_CIKK
AND ACS.DATUM_TOL = ACF.DATUM_TOL) AC,
(SELECT BAS.*
FROM BESZERZESI_ARAK BAS,
(SELECT
ID_CIKK,
MAX(DATUM) DATUM
FROM BESZERZESI_ARAK
GROUP BY ID_CIKK) BAF
WHERE BAS.ID_CIKK = BAF.ID_CIKK
AND BAS.DATUM = BAF.DATUM) BA
WHERE C.ID = AC.ID_CIKK
AND C.ID = BA.ID_CIKK
AND AC.ID_AR_TIPUS = 1
AND C.ID_CIKKCSOPORT = 1
A lekérdezés 4:20 percig fut de csak 25%-ot használ ki a CPU-ból.
Az egyes táblákban
CIKKTORZS : 44949
AR_CIKK_OSSZERENDELO: 45041
BESZERZESI_ARAK:46796
rekord található.
EXPLAIN:
1 PRIMARY ALL 44944
1 PRIMARY ALL 44959 Using where; Using join buffer
1 PRIMARY C eq_ref PRIMARY,FK_CIKKTORZS_10 PRIMARY 4 AC.ID_CIKK 1 Using where
4 DERIVED ALL 44944
4 DERIVED BAS eq_ref PRIMARY PRIMARY 7 BAF.ID_CIKK,BAF.DATUM 1
5 DERIVED BESZERZESI_ARAK range PRIMARY 4 47358 Using index for group-by
2 DERIVED ALL 44946
2 DERIVED ACS ref FK_AR_CIKK_OSSZERENDELO_01 FK_AR_CIKK_OSSZERENDELO_01 4 ACF.ID_CIKK 1 Using where
3 DERIVED AR_CIKK_OSSZERENDELO index FK_AR_CIKK_OSSZERENDELO_01 4 45453
Miért csak 25%-ot használ ki a CPU-ból a MySQL?
- 3223 megtekintés
Hozzászólások
Milyen operációs rendszer? Mert ha Windows, akkor négy CPU mag (vagy kettő + HT) esetén 1 mag maximális kiterhelése esetén 25%-ot láthatsz a Task Manager-ben.
- A hozzászóláshoz be kell jelentkezni
Ubuntu 14.04
- A hozzászóláshoz be kell jelentkezni
Szerintem 4 magos CPU-d van.
Egy query, egy mag.
Külső scriptekkel lehet párhuzamosítani.
---
"A megoldásra kell koncentrálni nem a problémára."
- A hozzászóláshoz be kell jelentkezni
Igen, 4 mag
- A hozzászóláshoz be kell jelentkezni
A sok magos rendszerek nem csak sql esetén a sok kérést tudják párhuzamosan kiszolgálni. Nehéz olyan algortmust írni, ami egymagában több magot használ, párhuzamosítható.
A mysql speed testek is arról szólnak, hogy 1000-10000 kérés/mp esetén tud-e még menni, ha a kapcsolódott kliensek száma 150-250. Itt egy kliensről van szó...
- A hozzászóláshoz be kell jelentkezni
Néha azért nézzetek már szét a nagyvilágban, van élet a MySQL-en is túl.
----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™
- A hozzászóláshoz be kell jelentkezni
Az nem lehet, hogy a művelet közben sokat vár I/O-ra azért nincs a CPU jobban kihasználva?
--
Tertilla; Tisztelem a botladozó embert és nem rokonszenvezem a tökéletessel! Hagyd már abba!; DropBox
- A hozzászóláshoz be kell jelentkezni
Ezt hogy tudom Linux alatt ellenőrizni?
- A hozzászóláshoz be kell jelentkezni
iotop lesz a barátod.
---
"A megoldásra kell koncentrálni nem a problémára."
- A hozzászóláshoz be kell jelentkezni
ez egy eleg elbaszott query igy elsore...
t
- A hozzászóláshoz be kell jelentkezni
+1
Most néztem csak meg a query-t.
Segítség: nézzz utána a JOIN -nak.
---
"A megoldásra kell koncentrálni nem a problémára."
- A hozzászóláshoz be kell jelentkezni
én sokáig követtem az szép kveriket, ahogy tanitották, de rájöttem, hogy valojában úgy a lassu. van amikor jó, de sokszor igazolodott be, hogy amire a suliba egyest adnak éles terhelt környezetben az fut szépen. tehát probálgatni kell.
------------------------
Jézus reset téged
- A hozzászóláshoz be kell jelentkezni
"tehát probálgatni kell."
Nem! Plan-t kell olvasni. ;)
Az eleje egyébként esetenként igaz is lehet, de az megint más topic lenne... :)
---
"A megoldásra kell koncentrálni nem a problémára."
- A hozzászóláshoz be kell jelentkezni
"Nem! Plan-t kell olvasni."
Úgy ám :D
- A hozzászóláshoz be kell jelentkezni
Esetleg egy optimálisabb formára át tudnád nekem írni?
- A hozzászóláshoz be kell jelentkezni
Ezt ugye nem gondolod komolyan? :)
Természetesen tudnám, de nem akarom, az alábbi okok miatt:
- csak megsejthetem a mezőneveket, és kapcsolatokat
- a bevágott query-d nincs rendesen tördelve, olvashatatlan, és innen meg nem mondja senki hány szint mélyre mentél subselect-ekkel
- nem az én dolgom
- úgy nem tanulsz
Javaslom nézz utánna a JOIN-nak: http://lmgtfy.com/?q=mysql+join+example
(off: amíg aktívan SQL-eztem, ha a kolléga segítséget kért a query-jében, és ha olyan volt a külalakja mint a tiédnek el sem olvastam, visszadobtam, azzal, hogy "ha olvasható lesz megnézem".
Annak idején eluntam, hogy más helyett én tördeljek, csak azért hogy segíthessek neki. Ilyet többet nem csinálok. J /off)
---
"A megoldásra kell koncentrálni nem a problémára."
- A hozzászóláshoz be kell jelentkezni
Csak hogy egy lépéssel (na jó, fél lépéssel) előbbre is juss:
SELECT
C.ID,
C.NEVROVID AS KOD,
C.NEV AS MEGNEVEZES,
C.KISZERELES_2_VALTOSZAM AS KARTONOS,
C.KISZERELES_1_VALTOSZAM AS DOBOZOS,
ACS.DATUM_TOL DATUM_TOL,
BAS.DATUM DATUM
FROM CIKKTORZS C,
LEFT JOIN AR_CIKK_OSSZERENDELO ACS ON ACS.ID_CIKK = C.ID
LEFT JOIN BESZERZESI_ARAK BAS ON BAS.ID_CIKK = C.ID
WHERE ACS.ID_AR_TIPUS = 1
AND C.ID_CIKKCSOPORT = 1
A jelenlegi ismereteimmel és az erre fordított 5 perccel, a megadott információkból ennyit tudtam összekalapálni.
Szerk: Ettől függetlenül petersonnak igaza van.
- A hozzászóláshoz be kell jelentkezni
szerintem ennek az egésznek így semmi értelme
reméld hogy a táblákat nem ugyan az csinálta, mint aki a query-t
mivel mezőket csak a [cikktorzs] táblából jelenítesz meg, így volt két felesleges SELECT
mivel a dátumokat sem használod, így a MAX-olás is felesleges
"ACS.ID_AR_TIPUS = 1" sem ideális helyen volt
SELECT
C.ID,
C.NEVROVID AS KOD,
C.NEV AS MEGNEVEZES,
C.KISZERELES_2_VALTOSZAM AS KARTONOS,
C.KISZERELES_1_VALTOSZAM AS DOBOZOS
FROM CIKKTORZS C
INNER JOIN (
SELECT ID_CIKK,
FROM AR_CIKK_OSSZERENDELO
WHERE ACS.ID_AR_TIPUS = 1
GROUP BY ID_CIKK
) AC ON C.ID = AC.ID_CIKK
INNER JOIN (
SELECT ID_CIKK
FROM BESZERZESI_ARAK
GROUP BY ID_CIKK
) BA ON C.ID = BA.ID_CIKK
WHERE C.ID_CIKKCSOPORT = 1
- A hozzászóláshoz be kell jelentkezni
A MAX-olás egyáltalán nem felesleges mert az AR_CIKK_OSSZERENDELO és a BESZERZESI_ARAK táblában egy cikkhez több rekord is tartozhat. Az árak változását tartalmazza .
Pl. az 1-es ID-jű cikkhez a AR_CIKK_OSSZERENDELO táblában két rekord található egy 100 Ft-os ár 2017.01.01 dátummal és egy 132 Ft-os ár 2017.01.25 dátummal ami az érvényességi idejét jelenti. Ma ugye 2017. 02. 03. van így nekem csak a 132 Ft-os ár kell.
Ugyan ez a szisztéma a BESZERZESI_ARAK táblánál is.
Tehát nekem kellet egy select ami vissza adja cikkek aktuális beszerzési és eladási árait. + kell bele egy cikkcsoport és egy ártípus szűrés.
- A hozzászóláshoz be kell jelentkezni
ez ezt struktura nelkul honnan az anyam picsajabol szopjuk ki? mar elnezest.
- A hozzászóláshoz be kell jelentkezni
Mea culpa a kötekedésért.
Tom megoldása adja magát ha feltételezzük hogy mit akart a költő. Magam is erre jutottam először.
Azonban ha nem minden cikk ID szerepel a másik két táblában akkor nem ugyan azt az eredményt adhatja mint az eredeti query. Abban az esetben csak Tom megoldás a jó, és az eredeti query hibás. Ezért is láttam meg a kihívást annak átírásában úgy hogy ugyan azt eredményt adjam vissza minden esetben.
Valamint a SELECT a dátumokat és árakat sem használta, így azokat elimináltam.
Hogy érdemben is hozzászóljak. Írtam az eredetidhez hasonló SELECT-et ugyan így 3 táblára. Mindegyik tábla: innodb, több mint 150 ezer sor, indexelve csak az ID-k voltak.
i5-2400, Ubuntu 16.04, mysql restart után visszaadott 125.004 sort 2,3 sec alatt. A visszaadott oszlopokra voltak mezőkonverziók if-ek stb.
Ez alapján nem a query-t gyanúsítanám.
iotop mit súgott?
MySQL beállításoknál próbálkozz ezzel ha nem értesz hozzá: https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltun…
- A hozzászóláshoz be kell jelentkezni
A mysqltuner hasznos, de inkább csak iránymutatás. Nem szabad készpénznek venni.
---
"A megoldásra kell koncentrálni nem a problémára."
- A hozzászóláshoz be kell jelentkezni
Nem bantasbol, de mint jol lathatoan sem a linux sem a mysql alapveto mukodesevel nem vagy tisztaban igy javaslom keress egy hozzaertot aki tamogatja a munkadat. Ha meg hobbiprojekt akkor merulj egy a google bugyraiban.
- A hozzászóláshoz be kell jelentkezni
Mysql nem szereti a subquery-t. meg ugy generalisan semmi sem. az oracle erolteti, de ok optimalizaljak is rendesen vegrehajtas elott, es amugy is az oracle elb*ttsagarol hosszasan lehetne ertekezni.
Ird at a query-t join-os megfejtesre, akkor explain-nel latni fogod, mi a gebasz. Ha szukseges, straight join-nal tudod javitani a mysql alap optimalizalasat, bonyi query-knek jol johet.
Vagy hasznalj mongodb-t.
- A hozzászóláshoz be kell jelentkezni
mongo? https://goo.gl/7ptBGS
- A hozzászóláshoz be kell jelentkezni
wow, talaltal egy mongo flame videot. es? sokaknak van preferenciaja, es furanak talaljak a masik rendszert. en hasznaltam mindkettot, hosszasan es elesben. Van, ahol jobb egy sql, de a microservice-ek vilagaban egyertelmuen mongo a nyero.
- A hozzászóláshoz be kell jelentkezni
MySQL is slow as a dog. MongoDB will run circles around MySQL because MongoDB is web scale.
"MongoDB does have some impressive benchmarks, but they do some interesting things to get those numbers. For example, when you write to MongoDB, you don't actually write anything. You stage your data to be written at a later time. If there's a problem writing your data, you're fucked. Does that sound like a good design to you?"
If that's what they need to do to get those kickass benchmarks, then it's a great design.
"..... If you were stupid enough to totally ignore durability just to get benchmarks, I suggest you pipe your data to /dev/null. It will be very fast."
Legalább megnézted? Felfogtad miről van szó? Miért cserélje le a meglevő rendszerét? fanboy..
néhány dologra jó a monogo, de itt épp szóba se jött.
Minden webshopod alatt mongo van "a microservice-ek vilagaban egyertelmuen mongo a nyero" ? -.-
- A hozzászóláshoz be kell jelentkezni
vagy postgresql-t, és a probléma meg van oldva. Mi migráltunk nagy (értsd 10+ éves) projektet postgresql-re, pár hét alatt megvolt.
- A hozzászóláshoz be kell jelentkezni
Hát... PostgreSQL-ben elkezdtek dolgozni a paralelizáció támogatásán, nem tudom mennyit hoz. 9.6-ban bejött már egy kezdeti támogatás.
Viszont tapasztalataim alapján a tábla particionálás is rengeteget tud gyorsítani nagy tábla esetén.
https://www.postgresql.org/docs/9.6/static/parallel-query.html
----------------
Lvl86 Troll, "hobbifejlesztő" - Think Wishfully™
- A hozzászóláshoz be kell jelentkezni
Gondolom 100%-on teker egy mag 4 percig. Amin a queryt nézve sztem nem is kell csodálkozni.
- A hozzászóláshoz be kell jelentkezni
Sztem sorrendben ezekkel kéne próbálkozni, csökkenő nyereségi sorrend:
1. a séma újra gondolása, a tipikus querykhez igazítás.
2. indexek kreálása, ahova kell.
3. táblák alatt DB engine váltás, (pl. InnoDB helyett TokuDB)
(és vagy 0. vagy 4. a másik adatbázisra váltás, csak ennek a költsége elég nagy. Ezt csak nagy vész esetén javasolnám.)
- A hozzászóláshoz be kell jelentkezni
Szerintem a kérdezőnek az 1. és 3. pont is nagy költségű, a 0./4. db váltás pedig a megfizethetetlen kategória.
- A hozzászóláshoz be kell jelentkezni
A 3. az 1 db ALTER TABLE per tábla. Ezt nem nevezném drágának.
A 2. kicsit drágább, mert gondolkozni kell hozzá, pl. a plan-t figyelembe venni, de amúgy 1 db CREATE index, ha a 3. után csinálod.
- A hozzászóláshoz be kell jelentkezni
Nem a sémát kell a query-hez igazítani, hanem a query-t a sámához.
Ugyanis a tárolt adatok összefüggései adottak.
Plant kell olvasni! (Mint azt fentebb már írtam is...)
A 2. 3. rendben van.
---
"A megoldásra kell koncentrálni nem a problémára."
- A hozzászóláshoz be kell jelentkezni