Autor | Zpráva | ||
---|---|---|---|
MaK Profil |
#1 · Zasláno: 11. 10. 2021, 15:42:51
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 |
#2 · Zasláno: 12. 10. 2021, 12:17:39
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). |
||
Časová prodleva: 2 roky
|
0