Autor | Zpráva | ||
---|---|---|---|
Ssob Profil |
#1 · Zasláno: 16. 9. 2008, 23:55:19
Dneska jsem si zkoušel hrát se subselectama v mysql a nemohu se zbavit dojmu, že jsou neskutečně pomalé!
Zatím jsem nezkoušel varianty s různými indexy a celkově ty testy nebyly rozsáhle, tak jsem se možná sekl.. Je možné, že se jedná pouze o variantu subselectů s použitím IN v podmínce. Uvedu příklad: mám tabulku testing (INT id, VARCHAR(100) name, INT category, DECIMAL price), záznamů je něco přes milion. dotaz SELECT id FROM testing WHERE category IN (SELECT max(category) FROM testing); zatímco dotaz s rovnítkem místo IN ( SELECT id FROM testing WHERE category = (SELECT max(category) FROM testing); Když jsem zkoušel dotaz: SELECT * FROM testing WHERE ROW(price, category) IN (SELECT MIN(price), category FROM testing GROUP BY category) GROUP BY category ORDER BY category tak jsem se samozřejmě nedočkal.. Tento dotaz měl vrátit záznam s nejmenší cenou (price) z každé kategorie (category). Podotázka: dá se dosáhnout stejného výsledku nějakym jiným (lepším) dotazem? Můžete mi vysvětlit proč jsou subselecty tak pomalé? Není lepší použít více jednoduchých dotazů místo jednoho se subselectem? |
||
Kajman_ Profil * |
#2 · Zasláno: 17. 9. 2008, 08:30:16
Můžete mi vysvětlit proč jsou subselecty tak pomalé?
Zkuste si explain select ... tam uvidíte, jak daná mysql daný dotaz zpracovává. Tohle se může měnit v různých verzích, třeba to v novějších už bude lepší. dá se dosáhnout stejného výsledku nějakym jiným (lepším) dotazem? Tohle by mohlo zrychlit, jak to rovnítko (ideální index asi (category,price)) SELECT t1.* FROM testing t1, (SELECT MIN(t2.price) price, t2.category FROM testing t2 GROUP BY t2.category) t3 WHERE t1.category=t3.category and t1.price=t3.price GROUP BY t1.category ORDER BY t1.category |
||
Ssob Profil |
#3 · Zasláno: 17. 9. 2008, 14:29:53 · Upravil/a: Ssob
Kajman_
Děkuji, tvůj dotaz je skutečné mnohem rychlejší. Bez indexu se provede za 15 sekund, s dvojitým indexem (category, price) za 1,1 sekundy a s indexy na sloupcích category a price za 1,8 sekundy, což je podle mě dostatečná rychlost. Podotázka: při provádění dvou stejných dotazů za sebou se pak používá nějaká cache, protože druhý dotaz je hotový hned. Dá se tato cache nějak vyprázdnit/zrušit? Hodilo by se mi to pro testovací účely. Ale pořád mi není jasné proč je dotaz s použitím IN tak pomalý. Tady jsou výsledky EXPLAIN těch dvou dotazů (bez indexů): Dotaz s IN: +----+--------------------+---------+------+---------------+------+--- ------+------+---------+---------------------------------------------- + | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+--------------------+---------+------+---------------+------+--- ------+------+---------+---------------------------------------------- + | 1 | PRIMARY | testing | ALL | NULL | NULL | NULL | NULL | 1321546 | Using where; Using temporary; Using filesort | | 2 | DEPENDENT SUBQUERY | testing | ALL | NULL | NULL | NULL | NULL | 1321546 | Using temporary; Using filesort | +----+--------------------+---------+------+---------------+------+---------+------+---------+----------------------------------------------+ Dotaz s rovnítkem: +----+-------------+------------+------+---------------+------+------- --+------+---------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+------------+------+---------------+------+------- --+------+---------+---------------------------------+ | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 49 | Using temporary; Using filesort | | 1 | PRIMARY | t1 | ALL | NULL | NULL | NULL | NULL | 1321546 | Using where | | 2 | DERIVED | t2 | ALL | NULL | NULL | NULL | NULL | 1321546 | Using temporary; Using filesort | +----+-------------+------------+------+---------------+------+---------+------+---------+---------------------------------+ Rozdíl vidím v tom, že u dotazů s IN je jako select_type 'DEPENDENT SUBQUERY'. Co to znamená? Že se poddotaz provádí pro každý záznam z hlavní tabulky? Děkuji |
||
DJ Miky Profil |
#4 · Zasláno: 17. 9. 2008, 14:35:03
„Dá se tato cache nějak vyprázdnit/zrušit?“
SELECT SQL_NO_CACHE tl.* ... |
||
Kajman_ Profil * |
#5 · Zasláno: 17. 9. 2008, 14:54:42
'DEPENDENT SUBQUERY'. Co to znamená?
Nějak si asi mysql myslí, že ten poddotaz závisí na obalujícím selectu, což by v tomhle případě být nemělo. Třeba to mají již opravené v nějakých chystaných verzích. Že se poddotaz provádí pro každý záznam z hlavní tabulky? Asi to tak bude, když v prvním explain je v rows plný počet řádků. |
||
Časová prodleva: 16 let
|
0