mysql_unbuffered_query

Školení, která pořádám

Bylo pro mě nemilým překvapením, když jsem se dozvěděl, že funkce mysql_query od MySQL serveru spolu s položením dotazu také získá všechna vrácená data a uloží je do paměti. Funkce mysql_fetch_assoc a podobné pak už s MySQL serverem nekomunikují a data předávají z paměti. Pokud běží MySQL server na jiném počítači, je toto chování samozřejmě žádoucí, vzdálená komunikace kvůli každému řádku by zbytečně zdržovala. Pokud ale MySQL server běží na stejném počítači jako webový server, tak může být zatížení serveru spojené se zaplněním paměti výraznější než režie komunikace s databází. Pro položení SQL dotazu bez ukládání výsledků do paměti slouží funkce mysql_unbuffered_query. Tato funkce se používá stejně jako mysql_query, ale má některá omezení – především nelze zjistit počet vrácených řádek a lze pracovat jen s posledním položeným dotazem, takže ji rozhodně není možné použít jako univerzální náhradu. Použití je tedy vhodné při splnění těchto podmínek:

Po pravdě řečeno, takové podmínky jsou u webových aplikací splněny málokdy. Lepší je tedy navrhovat dotazy tak, aby se nevýhoda funkce mysql_query naplno neprojevila a přenášet jen ta data, která opravdu budeme potřebovat:

<?php
// pokud tabulka stranky obsahuje např. i obsah stránky, je lepší se vyhnout SELECT *
$result = mysql_query("SELECT id, nadpis FROM stranky");
while ($row = mysql_fetch_assoc($result)) {
    echo "<a href='?id=$row[id]'>" . htmlspecialchars($row["nadpis"]) . "</a>\n";
}

// pokud bude potřeba většina dat, je možné SELECT * použít
$row = mysql_fetch_assoc(mysql_query("SELECT * FROM stranky WHERE id = " . intval($_GET["id"])));
echo "<h1>$row[nadpis]</h1>\n$row[stranka]";

// pokud nebudeme potřebovat všechny řádky, je vhodné použít LIMIT
$result = mysql_query("SELECT * FROM vyrobky ORDER BY nazev LIMIT 20");
?>

Filtrování dat je samozřejmě záhodno dělat rovněž na straně databáze pomocí WHERE, přenášení do PHP a filtrování až ve skriptu je zbytečně pomalé a náročné na paměť.

Přijďte si o tomto tématu popovídat na školení Výkonnost webových aplikací.

Jakub Vrána, Dobře míněné rady, 30.9.2005, diskuse: 7 (nové: 0)

Diskuse

Leo:

Nejak jsme nepochopil vas pocatecni uzas, protoze tak jsem si to vzdycky predstavoval ze to beha:

"funkce mysql_query od MySQL serveru spolu s položením dotazu také získá všechna vrácená data a uloží je do paměti. Funkce mysql_fetch_assoc a podobné pak už s MySQL serverem nekomunikují a data předávají z paměti"

ikona Jakub Vrána OpenID:

Já jsem si to představoval tak, že mysql_query() položí dotaz, který databáze kompletně zpracuje, zjistí, kolik vrátí řádek, a mysql_fetch_*() následně tato data získává. Rozdíl mezi mysql_unbuffered_query() jsem viděl v tom, že tato funkce skončí hned po parsování dotazu, ještě před jeho vyhodnocením.

ikona dgx:

a ještě jedna nevýhoda: tabulka zůstane blokována, dokud všechny řádky nepřečtete (nebo ukončíte spojení). Tohle by mohla řešit volba SQL_BUFFER_RESULT, ale nikdy jsem to nezkoušel.

Leo:

Ted jsem to nepochopil / ta nevyhoda je u ktere verze? Leo

Leo:

"Já jsem si to představoval tak, že mysql_query() položí dotaz, který databáze kompletně zpracuje, zjistí, kolik vrátí řádek, a mysql_fetch_*() následně tato data získává."

No ale stejne by se to muselo nejak mezitim ulozit ne, co kdyz se zmeni obsah databaze mezi polozenim dotazu a nacitanim dat vysledne sady? Leo

Ondrej Ivanic:

No... takto by som to uzcite netvrdil. Pozri si funkcie: mysql_use_result() a mysql_store_result() (C API, nie PHP).

pri mysql_query() sa pouziva mysql_store_result()

Co sa tychto podmienok:
# Databázový a webový server běží na stejném počítači.
# Přenášených dat je hodně.
# Stačí nám pracovat s posledním položeným dotazem a nepotřebujeme předem vědět počet vrácených řádek

Prva je diskutabilna, druha je k veci a tretiu je mozne eliminovat dizajnom aplikacie.

ikona spaze:

Jen technicka, unbuffered queries pouziva i PDO.

Diskuse je zrušena z důvodu spamu.

avatar © 2005-2024 Jakub Vrána. Publikované texty můžete přetiskovat pouze se svolením autora. Ukázky kódu smíte používat s uvedením autora a URL tohoto webu bez dalších omezení Creative Commons. Můžeme si tykat. Skripty předpokládají nastavení: magic_quotes_gpc=Off, magic_quotes_runtime=Off, error_reporting=E_ALL & ~E_NOTICE a očekávají předchozí zavolání mysql_set_charset. Skripty by měly být funkční v PHP >= 4.3 a PHP >= 5.0.