Autor | Zpráva | ||
---|---|---|---|
VaKvas Profil |
#1 · Zasláno: 14. 11. 2012, 16:14:04
Zdravim a prosim o pomoc. Potrebuji zrychlit(optimalizovat) nasledujici dotaz do db. Provadim generovani jine tabulky, kde v cyklu cca 5000 zaznamu vykonavam tento dotaz.
Takze v kazdem cyklu potrebuji sahnout do tabulky payments, kde si musim vysoucovat castku za obdobi (paysum) pak potrebuji zjistit pocet nalezenych zazanamu za dane obdobi. Proto ty SubSelecty. Ale urcite by to slo napsat lepe. Prosim o radu. V rodicovskem cyklu ziskavam prave mrp_cislo a to datum. Rodic vrati prace cca 5000 zaznamu ja nasledne v cyklu prochazim zaznamy a dotahuji tato data. Snad je to srozumitelne .. :-) SELECT p.name,p.amount,p.contractId,p.branchId, (SELECT sum(amount) FROM payments p WHERE contractId = (SELECT id FROM contracts WHERE mrp_cislo ='20111485') AND '2012-10-31' BETWEEN p.since AND IFNULL(p.to, '2099-12-31')) as paysum, // soucet za dane obdobi (SELECT count(id) FROM payments p WHERE contractId = (SELECT id FROM contracts WHERE mrp_cislo ='20111485') AND '2012-10-31' BETWEEN p.since AND IFNULL(p.to, '2099-12-31')) as rows // potrebuji zjistit pocet nalezenych za dane obdobi FROM payments p WHERE contractId = (SELECT id FROM contracts WHERE mrp_cislo ='20111485') AND '2012-10-31' BETWEEN p.since AND IFNULL(p.to, '2099-12-31') |
||
Kajman Profil |
#2 · Zasláno: 14. 11. 2012, 16:43:04
Ověřte si v explain, zda se používají vhodně indexy.
Poddotaz ve where raději přepište na inner join. Ty dva poddotazy v select části zkuste spočítat jedním dotazem připojený přes join. A zkuste místo 5000 dotazů udělat jeden s použitím group by. |
||
VaKvas Profil |
Ty joiny celkem motam. Mohu poprosit o vzor, jak joiny spravne pouzit v tomto pripade..
Jednoduche JOINy davam, ale tady se v tom vzdycky zamotam.. Diky! |
||
Časová prodleva: 5 dní
|
|||
Majkl578 Profil |
#4 · Zasláno: 19. 11. 2012, 20:45:42
V MySQL doporučuji nepoužívat závislé poddotazy (dependent subquery), MySQL má problém s aplikováním indexů a čas vykonávání dotazů exponenciálně roste s počtem záznamů, na 5000 řádků může být i 1000x horší než udělat n+1 dotazů.
Byl by problém oddělit ty dva poddotazy do samostatných dotazů (a tedy provést 3 dotazy)? Napadá mě jedině konzistence výsledku, což by pro minulé (neměnné) období mělo být irelevantní. Je mrp_cislo unikátní hodnota? Pokud ano, nedávají mi smysl ty poddotazy, pokud ne, nedávají smysl WHERE podmínky. Nejlépe dodej zakládací script (create) tabulky. |
||
VaKvas Profil |
#5 · Zasláno: 20. 11. 2012, 09:18:08
Zkusim trochu popsat princip.
1. provadim import z CSV do tabulky MRP. /to tech cca 5000 zaznamu/ 2. Prochazim tabulkou MRP a ziskavam contratctID /tedy mrp_cislo/ a datum zdan.pln., ktere mam pro ukazku vyplnene na pevno. 3. Na zaklade ziskanych dat z tabulky MRP prochazim platby/rozpady/ z tabulky payments 4. ukladam do dalsi tabulky.... Ukladani v bodu 4 delam pres multiinsert a probehne do par vterin (vsech cca 5000 radek) mrp_cislo je uniq. Zkousel jsem to dat do jednoho dotazu pridanim sum a cout, ale pak to musim nejak groupovat a uz neziskavam vsehcny zaznamy z tabulky payments... ale jen jeden zgrupovany. Script na tabulku A tady kod PHP (NETTE - ty to urcite znas ;)) Díky Majkle |
||
Kajman Profil |
#6 · Zasláno: 21. 11. 2012, 17:36:19
VaKvas:
„a uz neziskavam vsehcny zaznamy z tabulky payments“ Tak ke zgroupovaným datům pro výpočet součtů a počtů můžete připojit payments tabulku znovu. Něco jako SELECT * FROM (SELECT m.id, m.varsym, m.ico, m.datzdanpln, m.firma, m.cislo_zak, m.sum, Sum(p.amount) AS paysum, Count(p.id) AS rows, c.type, c.id AS contractid FROM mrp m LEFT JOIN contracts c ON c.mrp_cislo = m.cislo_zak LEFT JOIN payments p ON p.contractid = c.id AND m.datzdanpln BETWEEN p.since AND Ifnull(p.to, '2099-12-31') WHERE m.datzdanpln BETWEEN '2011-01-01' AND '2011-12-31' GROUP BY m.id, c.id) x LEFT JOIN payments p2 ON p2.contractid = x.contractid AND x.datzdanpln BETWEEN p2.since AND Ifnull(p2.to, '2099-12-31') |
||
Časová prodleva: 12 let
|
0