Autor | Zpráva | ||
---|---|---|---|
davchy Profil |
#1 · Zasláno: 24. 8. 2012, 10:31:08
Zdravím,
DELETE FROM `cfp_bandwidth` WHERE `id` NOT IN (SELECT max(`id`) AS `meta_id` FROM (SELECT * FROM `cfp_bandwidth`) AS `t1` GROUP BY `img_id`); používám tento dotaz, ale protože má `cfp_bandwidth` 7,5M řádků, odstaví to na celý den aplikaci, nebo zkolabuje. Lze toho stejného dosáhnou podstatně lehčím dotazem, nebo aby dotaz běžel „po částech“? Jde o to, že potřebuji vymazat všechny řádky se stejným `img_id` kromě toho nejmladšího. Díky |
||
Kajman Profil |
#2 · Zasláno: 24. 8. 2012, 10:51:51
Možná něco takového (bez záruky na data :)
DELETE FROM b1 USING `cfp_bandwidth` b1 LEFT JOIN (SELECT Max(`id`) AS `meta_id` FROM `cfp_bandwidth` GROUP BY `img_id`) AS `b2` ON b1.id = b2.meta_id WHERE b2.meta_id IS NULL Index na img_id případně na kombinaci (img_id, id) bude pro takové mazání vhodný. Případně může dopadnou rychleji v transakci přesunout chtěné řádky do stejné prázné tabulky, používanou truncnout a vrátit řádky zpět. Případně tabulku dropnout a tu původně práznou přejmenovat. |
||
Kajman Profil |
#3 · Zasláno: 24. 8. 2012, 10:54:15
Ale koukám, že jste stejný dotaz už testovat chtěl. Jak to dopadlo?
|
||
davchy Profil |
#4 · Zasláno: 24. 8. 2012, 13:01:37
Bohužel, výsledek je stejný. I po přidání indexu je aplikace po spuštění dotazu nepoužitelná :(
|
||
Kajman Profil |
#5 · Zasláno: 24. 8. 2012, 14:08:36
davchy:
„Bohužel, výsledek je stejný.“ Takže také celý den? Neběží to s tím joinem a indexem třeba jen půl dne? Když mažete 7 milionu řádků, tak to potrvá. Urychlit by to mohla ta zmíněná pomocná tabulka. Něco jako CREATE TEMPORARY TABLE mojetmp AS SELECT b1.* FROM `cfp_bandwidth` b1 JOIN (SELECT Max(`id`) AS `meta_id` FROM `cfp_bandwidth` GROUP BY `img_id`) AS `b2` ON b1.id = b2.meta_id; TRUNCATE TABLE cfp_bandwidth; INSERT INTO cfp_bandwidth SELECT * FROM mojetmp; DROP TEMPORARY TABLE mojetmp; |
||
davchy Profil |
#6 · Zasláno: 24. 8. 2012, 15:39:42
Zda celý den, to nevím. Pustil jsem ho v okamžik kdy jste ho postnul a stále běží (a blokuje běh aplikace).. ..uvidíme jak to dopadne přesně. Případně bych vyzkoušel ten další postup. Díky
|
||
davchy Profil |
#7 · Zasláno: 26. 8. 2012, 12:34:06
Ta druhá varianta je o 50% rychlejší. Navíc prvním během se počet řádků zredukoval na cca 100k a teď už je to otázka maximálně minuty.
Mockrát děkuji. |
||
Časová prodleva: 2 měsíce
|
|||
davchy Profil |
#8 · Zasláno: 23. 10. 2012, 18:47:17
Zdravím, jsem tu opět..
..a opět se jedná o to stejné. Ten poslední dotaz s použitím dočasné tabulky fungoval skvěle, jak jsem i psal, ale narazil jsem na další problém: maže i to, co potřebuji ponechat. Potřeboval bych, aby řádek ponechal, pokud je v tabulce `img_id` jen jednou. Mazat má pouze pokud se vyskytne více jak jednou a to ty nejstarší, tedy ty, které mají nižší `id`. Prosím tedy, jak by měl vypadat upravený dotaz? Mockrát děkuji. |
||
Kajman Profil |
Pokud je v tabulce jediný řádek s daným img_id, bude i tak v temporary tabulce a tudíž bude zachován. Máte to uzavřené do transkace, případně zamykáte tabulku, aby ji mezi těmy příkazy nikdo neupravoval?
Ještě můžete zkusit jednu variantu s delete z faq, třeba bude o fous rychlejší než verze v [#2] (ale tipuji, že to bude podobné, možné i pomalejší). Opět jeden index na dvou sloupích (img_id, id). DELETE FROM t1 USING cfp_bandwidth t1, cfp_bandwidth t2 WHERE t1.img_id = t2.img_id AND t1.id < t2.id |
||
Časová prodleva: 11 let
|
0