tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

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í.