ugrás a tartalomhoz

count(*) vs mysql_num_rows(), te mit hasznalsz?

pp · 2005. Okt. 12. (Sze), 09.01
Lapozásnál te mit használsz?

<?
$res=mysql_query("select count(*) from ....");
$count=array_pop(mysql_fetch_assoc($res));
//... lapozás ...
$res=mysql_query("select * from .... limit $first,$db ");
while($row=mysql_fetch_assoc($res))
{
 ....//feldolgozas
}
?>
vagy

<?
$res=mysql_query("select * from ....");
$count=mysql_num_rows($res);
//... lapozás ...
mysql_data_seek($res,$first);
for($i=0;$i<$db;$i++)
{
    $row=mysql_fetch_assoc($res)
 ....//feldolgozas
}
?>
Az első kíméli az adatbázis kezelőt(minek?) a másik pedig nem.
 
1

count()

Hojtsy Gábor · 2005. Okt. 12. (Sze), 09.10
Egyértelműen count(). A SELECT óriási memóriát foglal a MySQL szerveren nagy táblára, hiszen a sorok számának kiderítéséhez minden sort elő kell állítania. A count() viszont tárolt érték (ha szűrési feltétel is van, csak akkor kell számolni), nagyon hamar megvan. Ahhoz, hogy a MySQL ne foglalja le a teljes eredménytáblának a memóriát, mysql_unbuffered_query()-t lehetne használni, azzal viszont érthető okok miatt a mysql_num_rows() nem ad használható eredményt, hiszen nem ismert a sorok száma.
2

És a cache?

pp · 2005. Okt. 12. (Sze), 10.00
<csakkérdés>
Egy nagy forgalmú híroldalnál, jellemzően ugyan azokat a lekérdezéseket kell sokszor egymás után előállítani, ezeket meg "bekeseli" a mysql, így nagy sebesség növekedés tudunk elérni, nem? Az adatbázis kezelőnek nem kell újra és újra előállítania a lekérdezést, újabb memóriafoglalásokat eszközölve tehát kit érdekel, hogy *egyszer* lefoglalta?
Ez egy nagyon speciális eset?
</csakkérdés>

pp
3

bekesselte?

Hojtsy Gábor · 2005. Okt. 12. (Sze), 12.28
Hát a MySQL 4.01 óta támogatja a Query Cache funkciót, és globális változókban kell bekapcsolni (osztott szerveren csak a rendszergazda állíthatja be). Ha be van kapcsolva, lehet praktikus, de csak akkor lehet egyáltalán a count() nélküli lapozó kialakításra gondolni, ha biztos van query cache, és biztos nem használsz a lapozandó dologban semmi olyat, ami invalidálja a gyorsítótárat (aktuális dátum, random szám, stb), illetve nem változik túl gyakran a lekérdezés eredménye (a forrás táblák tartalma). Szóval csak akkor érdemes a count() nélküli módszert választani, ha saját szervered van, vagy garantáltan gyorsítótáras MySQL, és tudod, hogy mit csinálsz. Semmiképpen sem szabad rászokni.
5

félig

Hodicska Gergely · 2008. Nov. 27. (Cs), 23.21
A szerver oldali memória foglalás amúgy is általában meglesz, mert a limit csak a legvégén hajtódik végre, a resultset előáll (ha nem unbuffered query van, de ez nem jellemző). Viszont a kliens oldalra megérkezik a teljes resultset, ezért a limit nélküli query akár óriási fölösleges házlózati forgalmat generálhat, plusz megnöveli a PHP script memória fogalálását, szóval mindenféleképpen rossz megoldás. A helyzetet súlyosbítja ráadásul, hogy a libmysql nem a PHP memória managerét használja, így a memory limit sem vonatkozik rá, szóval akár szépen haza is lehet vele vágni a szervert. Ezért is várjuk nagyon a mysqlnd-t.

SQL_CALC_FOUND_ROWS felvetés: ezzel vigyázni kell, elég jól le tudja rontani a query futás idejét, van amikor simán jobb a külön count(*)-os query, érdemes tesztelni.
4

count() helyett használd

yanchi · 2008. Nov. 27. (Cs), 21.49
count() helyett használd inkább a SQL_CALC_FOUND_ROWS-t a queryben, és SELECT FOUND_ROWS() segítségével olvasd ki a sorok számát. Előnye, hogy a LIMIT végű querynél is azt az értéket kapod, ahány sort LIMIT nélkül tartalmazna a válasz. Hatalmas a sebességnövekedés, ha van a queryben WHERE, nem kell kétszer megcsinálni ugyanazt.