Gyorsabb véletlen rekordok lekérdezése

Bejegyzés dátuma:
2011-06-26

Bizonyára sokszor találkozunk azzal a feladattal, ami arról szól hogyan tudunk kiválasztani 1 véletlen rekordot egy megadott táblából? Pl: egy webáruház megadott rendeléseiből akarunk véletlenszerűen kiválasztani egyet. Ilyenkor a legkézenfekvőbb megoldás lehet erre MySql adatbázist felhasználva a következő lekérdezés:

SELECT * FROM test ORDER BY RAND() LIMIT 0,1;

Sokszor láttam, ezt a kódot nagynevű oldalak sorai között. Vizsgáljuk egy kicsit meg közelebbről. Készítettem egy 500 ezres nagyságrendű adattáblát. Erre egy tesztadatokat készítő egyszerű tárolt eljárást írtam, majd egy teszt osztályt, ami végrehajtja a lekérdezést és kiírja a script futási idejét.

A tesztosztály részeként írtam egy másik lekérdezést, ami ugyanezt végzi el, csak egy kicsit másképp, két lekérdezést futtatva.

SELECT FLOOR(RAND() * COUNT(*)) AS offset FROM test;

SELECT * FROM test LIMIT offset, 1;

A tesztkörnyezetemben az első lekérdezés majdnem 3x olyan lassan fut le, mint a második változat. Az eredmény pedig ugyanaz. Mi lehet ennek az oka?

A magyarázatot a MySql kézikönyvben találhatjuk. Vagyis az első esetben egy segédtábla keletkezik, amit véletlenszerűen rendez, majd ebből visszaadja az elsőt. Az eredmény tehát egy véletlen rekord lesz.

A második esetben, pedig előállít egy véletlen offsetet, a test rekordok számából, majd visszaad a vélelenszámú offsettől 1 darabot, tehát nem történik rendezés és köztes tábla létrehozás.

Egyes esetekben jelentős sebességnövekedést és erőforrás kihasználást tudunk elérni, ha odafigyelünk erre.