Mysql dotazuje viacero dotazov v jednom. Optimalizácia MySQL dotazov

V minulej lekcii sme sa stretli s jednou nepríjemnosťou. Keď sme chceli vedieť, kto vytvoril tému „bicykle“ a položili sme zodpovedajúci dotaz:

Namiesto mena autora sme dostali jeho identifikátor. Je to pochopiteľné, pretože sme urobili dotaz na jednu tabuľku – Témy a mená autorov tém sú uložené v inej tabuľke – Používatelia. Preto, keď sme sa dozvedeli identifikátor autora témy, musíme urobiť ešte jeden dotaz - do tabuľky Používatelia, aby sme zistili jeho meno:

SQL poskytuje možnosť spojiť takéto dotazy do jedného tak, že jeden z nich zmení na poddotaz (vnorený dotaz). Aby sme teda zistili, kto vytvoril tému „bicykle“, položíme nasledujúci dotaz:

Teda po kľúčovom slove KDE, do podmienky napíšeme ešte jeden dotaz. MySQL najskôr spracuje poddotaz, vráti id_author=2 a táto hodnota sa odovzdá do klauzuly KDE externá požiadavka.

V jednom dotaze môže byť niekoľko poddotazov, syntax pre takýto dotaz je nasledovná: Všimnite si, že poddotazy môžu vybrať iba jeden stĺpec, ktorého hodnoty vrátia do vonkajšieho dotazu. Pokus o výber viacerých stĺpcov bude mať za následok chybu.

Urobme ďalšiu požiadavku na konsolidáciu, zistime, aké správy zanechal autor témy „bicykle“ na fóre:

Teraz si úlohu skomplikujeme, zistime, v ktorých témach autor témy „bicykle“ zanechal správy:

Pozrime sa, ako to funguje.

  • MySQL najskôr vykoná najhlbší dotaz:

  • Výsledok (id_author=2) bude odovzdaný externej požiadavke, ktorá bude mať tvar:

  • Výsledok (id_topic:4,1) bude odovzdaný externému dotazu, ktorý bude mať tvar:

  • A poskytne konečný výsledok (názov témy: o rybolove, o rybolove). Tie. autor témy "bicykle" uverejnil príspevky v téme "O rybolove" vytvorenej Sergejom (id=1) a v téme "O rybolove" od Sveta (id=4).
To je vlastne všetko, čo som chcel povedať o vnorených dopytoch. Je však potrebné venovať pozornosť dvom bodom:
  • Neodporúča sa vytvárať dopyty s úrovňou vnorenia vyššou ako tri. To vedie k zvýšeniu času vykonávania a zložitosti vnímania kódu.
  • Daná syntax vnorených dopytov je skôr najbežnejšia, no ani zďaleka nie jediná. Napríklad namiesto žiadania

    písať

    Tie. môžeme použiť akékoľvek používané operátory kľúčové slovo KDE (študovali sme ich v minulej lekcii).

Už som písal o rôznych SQL dotazy, ale je čas porozprávať sa o zložitejších veciach, napr. SQL dotaz na výber záznamov z viacerých tabuliek.

Keď sme robili výber z jednej tabuľky, všetko bolo veľmi jednoduché:

SELECT požadované_názvy_polí FROM názov_tabuľky WHERE select_condition

Všetko je veľmi jednoduché a triviálne, ale s načítanie viacerých tabuliek naraz je to trochu ťažšie. Jednou z ťažkostí je zhoda názvov polí. Napríklad každá tabuľka má pole id.

Zoberme si takúto žiadosť:

SELECT * FROM table_1, table_2 WHERE table_1.id > table_2.user_id

Mnohým, ktorí sa s takýmito otázkami nezaoberali, sa bude zdať, že všetko je veľmi jednoduché, mysliac si, že pred názvy polí boli pridané iba názvy tabuliek. V skutočnosti sa tým zabráni konfliktom medzi identickými názvami polí. To však nie je problém, ale algoritmus takéhoto SQL dotazu.

Algoritmus práce je nasledujúci: prvý záznam je prevzatý z stôl 1. prijaté id tento záznam od stôl 1. Tabuľka je uvedená nižšie. tabuľka_2. A všetky záznamy sú pridané tam, kde je hodnota poľa ID používateľa menej id vybraný záznam v stôl 1. Po prvej iterácii sa teda môže objaviť od 0 do nekonečna výsledné záznamy. Pri ďalšej iterácii sa použije ďalší záznam tabuľky stôl 1. Znovu sa zobrazí celá tabuľka tabuľka_2 a znova sa spustí podmienka výberu table_1.id > table_2.user_id. Do výsledku sa pridajú všetky záznamy, ktoré spĺňajú túto podmienku. Výstupom môže byť obrovské množstvo záznamov, mnohonásobne väčšie ako celková veľkosť oboch tabuliek.

Ak po prvýkrát pochopíte, ako to funguje, je to skvelé, ale ak nie, čítajte, kým úplne nepochopíte. Ak to pochopíte, bude to jednoduchšie.

Predchádzajúce SQL dotaz, ako taký, sa používa zriedka. Bolo to práve dané za vysvetlenie algoritmu výberu viacerých tabuliek. A teraz poďme analyzovať viac drep SQL dotaz. Povedzme, že máme dve tabuľky: s tovarom (je tam pole identifikátor_vlastníka zodpovedný za id vlastník produktu) a s používateľmi (existuje pole id). Chceme jednu SQL dotaz získať všetky záznamy a každý by mal obsahovať informácie o používateľovi a jeho jednom produkte. Ďalší záznam obsahoval informácie o tom istom používateľovi a jeho ďalšom produkte. Keď sa tovar tohto používateľa minie, prejdite k ďalšiemu používateľovi. Preto musíme spojiť dve tabuľky a získať výsledok, v ktorom každý záznam obsahuje informácie o užívateľovi a jednom z jeho produktov.

Dotaz, ako je tento, nahradí 2 SQL dotazy: podľa výberu oddelene od tabuľky s produktmi a od tabuľky s používateľmi. Takáto požiadavka sa navyše okamžite zhoduje s používateľom a jeho produktom.

Samotná žiadosť je veľmi jednoduchá (ak ste porozumeli predchádzajúcej):

SELECT * FROM users, products WHERE users.id = products.owner_id

Algoritmus je tu už jednoduchý: prvý záznam sa vyberie z tabuľky používateľov. Ďalej to trvá id a všetky záznamy z tabuľky sa analyzujú Produkty, pričom k výsledku sa pridali tie s identifikátor_vlastníka rovná sa id od stola používateľov. Pri prvej iterácii sa teda zhromažďujú všetky produkty od prvého používateľa. Pri druhej iterácii sa zhromaždí všetok tovar od druhého používateľa atď.

Ako môžeš vidieť SQL dotazy na výber z viacerých tabuliek nie sú najjednoduchšie, ale výhody z nich môžu byť obrovské, preto je veľmi žiaduce poznať a vedieť používať takéto dotazy.

Tento krátky článok sa zameria na databázy najmä MySQL, vzorkovanie a počítanie. Pri práci s databázami je často potrebné spočítať počet riadkov COUNT() s určitou podmienkou alebo bez nej, je to veľmi jednoduché pomocou nasledujúceho dotazu

Zobrazenie kódu MySQL

Dotaz vráti hodnotu s počtom riadkov v tabuľke.

Podmienečné počítanie

Zobrazenie kódu MySQL

Dotaz vráti hodnotu s počtom riadkov v tabuľke, ktoré spĺňajú danú podmienku: var = 1

Ak chcete získať viacero hodnôt počtu riadkov s rôznymi podmienkami, môžete napríklad vykonať viacero dotazov jeden po druhom

Zobrazenie kódu MySQL

V niektorých prípadoch však tento prístup nie je praktický a nie je optimálny. Organizácia dotazu sa preto stáva relevantnou s niekoľkými poddotazmi, aby sa v jednom dotaze naraz získalo niekoľko výsledkov. Napríklad

Zobrazenie kódu MySQL

Vykonaním len jedného dotazu do databázy teda dostaneme výsledok s počítaním riadkov podľa viacerých podmienok, obsahujúci viacero hodnôt počtu, napr.

Zobraziť kód TEXT

c1|c2|c3 -------- 1 |5 |8

Za nevýhodu použitia poddotazov oproti niekoľkým samostatným dotazom možno považovať rýchlosť vykonávania a zaťaženie databázy.

Nasledujúci príklad dotazu, ktorý obsahuje viaceré počty COUNT v jednom dotaze MySQL, je štruktúrovaný mierne odlišne pomocou konštrukcií IF(podmienka, hodnota1, hodnota2), ako aj súčtu SUM(). Umožňuje vám vybrať údaje podľa špecifikovaných kritérií v rámci jedného dotazu, potom ich zosumarizovať a zobraziť niekoľko hodnôt.

Zobrazenie kódu MySQL

Ako vidno z dotazu, je postavená celkom výstižne, no rýchlosť jej vyhotovenia tiež nepotešila, výsledok daná žiadosť bude ďalší

Zobraziť kód TEXT

celkom|c1|c2|c3 --------------- 14 |1 |5 |8

Ďalej uvediem porovnávaciu štatistiku rýchlosti vykonania troch možností dotazu na výber niekoľkých COUNT () . Na testovanie rýchlosti vykonávania dotazov bolo vykonaných 1000 dotazov každého typu, pričom tabuľka obsahovala viac ako tri tisícky záznamov. Zároveň zakaždým, keď dotaz obsahoval SQL_NO_CACHE, aby sa zakázalo ukladanie výsledkov do pamäte cache databázy.

Rýchlosť vykonávania
Tri samostatné žiadosti: 0,9 sek
Jeden dotaz s poddotazmi: 0,95 sek
Jeden dotaz s konštrukciou IF a SUM: 1,5 sek

Záver. Máme teda niekoľko možností, ako vytvoriť dopyty do databázy údaje MySQL s viacerými COUNT(), prvá možnosť so samostatnými dopytmi nie je príliš pohodlná, ale má najlepší výsledok z hľadiska rýchlosti. Druhá možnosť s poddotazmi je o niečo pohodlnejšia, ale rýchlosť jej vykonávania je o niečo nižšia. A napokon tretia stručná verzia dotazu s konštrukciami IF a SUM, ktorá sa zdá byť najpohodlnejšia, má najnižšiu rýchlosť vykonávania, ktorá je takmer dvakrát nižšia ako prvé dve možnosti. Preto pri optimalizácii chodu databázy odporúčam použiť druhú možnosť dotazu obsahujúcu poddotazy s COUNT (), po prvé sa rýchlosť jeho vykonávania blíži k najrýchlejšiemu výsledku a po druhé je takáto organizácia v rámci jedného dotazu celkom pohodlná.