Oznámení
Velký problém s DibiDataSource (a MySQL)
před 10 lety
- David Grudl
- Nette Core | 6806
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 :-(
Co s tím?
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ě.
Jiné databáze
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.
před 10 lety
- phx
- Člen | 652
Pokud ctu dobre tak ve verzi 6 by to melo byt opraveno, ale to bude asi jeste nejaky ten rok trvat:(
před 10 lety
- David Grudl
- Nette Core | 6806
Mělo, ale co jsem zkoušel aktuální betu, tak ještě není.