Autor Zpráva
MaK
Profil
Mám přibližně takové dvě tabulky:

CREATE TABLE dokumenty
(
    dokument_id        INTEGER,
    jmeno             VARCHAR(256),
    autor_id         INTEGER,
    cas_zverejneni     TIMESTAMP
);

CREATE TABLE lajky
(
    dokument_id     INTEGER,
    pocet             INTEGER
);

a přibližně takové dva dotazy:

-- verze A (pomalejší)
SELECT dokumenty.*, lajky.pocet
FROM dokumenty
LEFT JOIN lajky USING (dokument_id)
WHERE dokumenty.uzivatel_id = 123
ORDER BY dokument_id DESC
LIMIT 2000, 20;

-- verze B (rychlejší)
SELECT dokumenty.*, (SELECT pocet FROM lajky WHERE lajky.dokument_id = dokumenty.dokument_id) AS pocet  
FROM dokumenty
WHERE dokumenty.uzivatel_id = 123
ORDER BY dokument_id DESC
LIMIT 2000, 20;

+ používám MySQL
+ správné sloupce, jsou opatřeny správnými indexy
+ explain vychází pro oba dotazy stejně
+ verze A trvá 3x déle než verze B
+ verze A spotřebuje Handler_read_key: 2021 Innodb_buffer_pool_read_requests: 14371
+ verze B spotřebuje jen Handler_read_key: 21 Innodb_buffer_pool_read_requests: 6201
+ ostatni Server Status Variables jsou přibližně shodné

Je patrné, že MySQL otrocky propojí všechny tabulky, což se odrazí na výkonu.
Což je trochu v rozporu s doporučením nahradit (pokud to lze) subqueries spojením tabulek.

Něco mi uniká? Psát to alá verze B? Vykašlat se na to a čekat, že MySQL to jednou zadrátuje líp?
Kajman
Profil
Pokud spojení nijak neovlivní omezení z první tabulky, tak můžete pro jistotu (kdyby to nepoznal plánovač mysql) ten poddotaz nebo ještě variantu C

SELECT d.*,
       lajky.pocet
FROM   (SELECT dokumenty.*
        FROM   dokumenty
        WHERE  dokumenty.uzivatel_id = 123
        ORDER  BY dokument_id DESC
        LIMIT  2000, 20) d
       LEFT JOIN lajky USING (dokument_id)
ORDER  BY dokument_id DESC 

Na tento dotaz je pak dobrý dvousloupcový index (uzivatel_id, dokument_id).

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:

0