Nejste přihlášen(a)
Díky upozornění Honzy Trtika jsem přišel na velmi nepříjemnou vlastnost MySQL: v subquery neumí použít indexy.
Co to znamená. Mějme tabulku orders s indexem nad customer_id. Potom:
# klasický dotaz -> RYCHLÉ SELECT * FROM orders ORDER BY customer_id # subquery -> POMALÉ, index nevyužije SELECT * FROM (SELECT * FROM orders) x ORDER BY customer_id # subquery -> POMALÉ SELECT COUNT(*) FROM (SELECT * FROM orders) x
Hodně mě to překvapilo, protože pro pohledy to bezproblémů zvládá:
CREATE OR REPLACE VIEW dibidatasource AS SELECT * FROM orders # RYCHLÉ SELECT * FROM dibidatasource x ORDER BY customer_id # RYCHLÉ SELECT COUNT(*) FROM dibidatasource x
Na subqueries je postaven celý DibiDataSource. Musím proto bohužel apelovat na to, abyste jej v současné podobě pod MySQL nepoužívali :-(
Jaké je řešení? Jedno jsem naznačil a to je jít cestou pohledů. Není to vůbec elegantní a uživatel musí mít práva na vytváření pohledů. Bohužel MySQL neumí vytvořit temporary view, takže vytvoření pohledu není časově nezanedbatelné.
Částečné řešení za použití UNIONu vymyslel Jakub Vrána:
(SELECT * FROM `orders`) ORDER BY customer_id LIMIT 10
Bohužel tu nelze snadno omezit získané sloupce a přidat další podmínky WHERE.
Nejčistší řešení tak asi je views předgenerovat. Tedy model místo
dibi::dataSource(...) vrátí new DibiDataSource('viewname',
dibi::getConnection()), kde viewname je už nějaký (třeba
i modelem) vytvořený pohled. Tohle by mělo fungovat optimálně.
Ověřil jsem, že stejným problémem NEtrpí PostreSQL (8.1.11) ani SQLite 2, nezkoušel jsem ORACLE, ale předpokládám, že ani tady nebude problém.
Pokud ctu dobre tak ve verzi 6 by to melo byt opraveno, ale to bude asi jeste nejaky ten rok trvat:(
Mělo, ale co jsem zkoušel aktuální betu, tak ještě není.