Autor Zpráva
Ssob
Profil
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);
se prováděl 15 minut, pak jsem ho vypnul
zatímco dotaz s rovnítkem místo IN (
SELECT id FROM testing WHERE category = (SELECT max(category) FROM testing);
) se prováděl necelou sekundu.

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 *
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
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
Dá se tato cache nějak vyprázdnit/zrušit?
SELECT SQL_NO_CACHE tl.* ...
Kajman_
Profil *
'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ů.

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm: