ugrás a tartalomhoz

Véletlen sor változó feltételek alapján

pkadam · 2013. Okt. 25. (P), 14.25
Sziasztok!

Az ORDER BY RAND() kiváltásának elég bő az irodalma, azonban ezek döntő többsége nem foglalkozik egyéb kiválasztási kritériumokkal.

Tegyük fel, hogy van egy weboldal, ahol minden cikk végén szeretnénk az adott szerzőtől 5 véletlenszerű további cikket ajánlani. Sok szerző van, sok cikk, és sok törölt is.

– MAX(article_id) alapján hiába generálunk találomra lehetséges ID-kat akár nagyobb számban, mert jó eséllyel vagy nem az adott szerzőtől származik, vagy nem létezik.

– Ha "cikk ID >= random ID" feltételt adunk meg, hogy biztosan létezzen a cikk, akkor több egymás után törölt cikket követő ID túl gyakran fog szerepelni, ezt sem szeretnénk.

– Az összes lehetséges sor lekérése (a programban történő utólagos feldolgozásra) nagyon nagy számú eredményt is hozhat.

Ti hogyan közelítenétek meg a problémát?

Előre is köszönettel,
pkadam
 
1

SELECT * FROM cikkek WHERE

Hidvégi Gábor · 2013. Okt. 25. (P), 14.36
SELECT * FROM cikkek WHERE szerzo = '{$aktualis_szerzo}' AND torolt = 0 AND cikk_kulcs <> '{$aktualis_kulcs}' ORDER BY RAND() LIMIT 5?
2

ORDER BY RAND() nélkül

pkadam · 2013. Okt. 25. (P), 15.26
A probléma pont az, hogy az ORDER BY RAND()-ot kellene kiváltani, mivel nagyobb táblák esetén (>10 ezer sor) már nagyon lassú.
3

Akkor le lehetne generálni

Hidvégi Gábor · 2013. Okt. 25. (P), 15.52
Akkor le lehetne generálni előre a véletlenszerű 5 cikk-kulcsból egy táblázatot.
4

Egyszerűbb tábla?

csla · 2013. Okt. 25. (P), 15.58
Próbáltam most egy ilyen egyszerű lekérdezést egy 2,6 millió rekordot tartalmazó táblán, és rendre 2 ezredmásodperc alatt kaptam meg az eredményt. Ez egy egyszerű tábla, három numerikus, egy date és két time mezővel. Lehet, hogy kéne egy olyan tábla, amiben csak a szerző és cikk ID mezők vannak, és azon elvégezni a véletlen kiválasztást.
5

Ehhez elég egy jó index.

Hidvégi Gábor · 2013. Okt. 25. (P), 16.16
Ehhez elég egy jó index.
11

Nem hiszem, hogy sok olyan

tgr · 2013. Okt. 25. (P), 22.43
Nem hiszem, hogy sok olyan szerző van, akinek több, mint 10 ezer cikke van...
12

Csak példa

pkadam · 2013. Okt. 26. (Szo), 00.02
A szerző-cikk koncepció csak példa (ezzel tudtam a legegyszerűbben szemléltetni a lényeget), a tényleges rendszerben azonban több tízezer rekord kb. egyharmada felel meg a keresési feltételnek – a rekordok száma növekedhet, az arány nagyjából állandó.
6

Szeretnék egy tömbből

MadBence · 2013. Okt. 25. (P), 20.05
Szeretnék egy tömbből kiválasztani 5 véletlen elemet, de úgy, hogy magát a tömböt nem ismerem. Sok szerencsét. :)

Kérd le feltételeknek megfelelő sorok számát, válassz ki rajta 5 random indexet, és kérd le azokat (egyesével, vagy seekelve)
7

Nem lehet, mert nem folytonos

Joó Ádám · 2013. Okt. 25. (P), 21.11
Nem lehet, mert nem folytonos az elsődleges kulcsok tartománya (vannak törölt rekordok).
13

Nem is kell, az

MadBence · 2013. Okt. 26. (Szo), 03.00
Nem is kell, az eredményhalmaz méretének ismeretében kell kiválasztani 5 véletlen számot (pozíciót az eredményhalmazban), majd ezeket a rekordokat lekérdezni (tehát ehhez nem kell rendezni, csak a megfelelő helyre ugrani az eredményhalmazban)
14

Ezzel gyakorlatilag azt

Joó Ádám · 2013. Okt. 26. (Szo), 03.12
Ezzel gyakorlatilag azt mondod, hogy adott esetben kérdezzen le tízezres nagyságrendű rekordot. Nekem nem tűnik túl hatékonynak.
15

Nem kell lekérdezni mindet,

BlaZe · 2013. Okt. 26. (Szo), 10.43
Nem kell lekérdezni mindet, ha előre minden rekordhoz hozzárendel egy sorszámot, vagyis eltárol egy adott szerzőn belüli, folyamatos sequence id-t. Azt tudja, hogy hány rekordból kell választani, kiválaszt 5 véletlenszerű számot, ami rekordok számánál kisebb, és where author_id=x and author_seq in (3,6,8,16,42), vagy ilyesmi. Erre tud indexet is tenni. Nyilván karban kell tartani, de az azért nem akkora mágia.
16

Karbantartás

Pepita · 2013. Okt. 26. (Szo), 12.05
Több tízezres rekordnál, egyetlen törlés után átlagosan a fél tábla update-elése egy kicsit "mágia". Illetve az adott szerző "újraindexelése". Ez sem hatékony.
19

Több tízezres rekordnál,

BlaZe · 2013. Okt. 26. (Szo), 12.51
Több tízezres rekordnál, egyetlen törlés után átlagosan a fél tábla update-elése egy kicsit "mágia"

Ez már miért lenne így?

A felvetés egyébként a lekérdezésről szólt. Legalábbis nem említette, hogy nagyon write-heavy lenne az alkalmazás. Ha ritka a törlés (pl adminról történik), akkor gyakorlatilag ez mindegy még akkor is, ha 1 másodpercig tart egy update, amit ekkora rekordszámnál én nem hinnék. Az íráson is lehet optimalizálni többféle módon, pl ki lehet tenni kapcsolótáblába stb.

Ez sem hatékony.

Annál, hogy a lekérdezés pontosan 5 random rekordot választ ki egyetlen lekérdezéssel index alapján, aligha fogsz hatékonyabb eredményt kapni.
20

Gyors mérés

BlaZe · 2013. Okt. 26. (Szo), 13.49
Egy kis gyors mérés:

select version();
                                                   version                                                    
--------------------------------------------------------------------------------------------------------------
 PostgreSQL 9.1.10 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.8.1-10ubuntu7) 4.8.1, 64-bit
(1 row)



CREATE TABLE update_test (
  outer_ref_id SERIAL,
  author_id BIGINT NOT NULL,
  author_seq INTEGER NOT NULL,
  CONSTRAINT update_test_outer_ref_id_key UNIQUE(outer_ref_id),
  CONSTRAINT update_test_pkey PRIMARY KEY(author_id, author_seq)
);

do $$                            
declare 
author_id integer;
author_seq integer;
begin
  for author_id in 1..1000 loop
    for author_seq in 1..1000 loop
      insert into update_test (author_id, author_seq) values (author_id, author_seq);
    end loop;
  end loop;
end;
$$;
DO
Time: 20970.795 ms

commit;
COMMIT
Time: 0.729 ms

delete from update_test where author_id=888 and author_seq=500;
DELETE 1
Time: 0.903 ms

update update_test set author_seq=author_seq-1 where author_id=888 and author_seq>500;
UPDATE 500
Time: 15.749 ms

commit;
COMMIT
Time: 1.256 ms

select * from update_test where author_id=888 and author_seq in (35,250,333,420,950);
 outer_ref_id | author_id | author_seq 
--------------+-----------+------------
     20642000 |       888 |         35
     20642215 |       888 |        250
     20642298 |       888 |        333
     20642385 |       888 |        420
     20642916 |       888 |        950
(5 rows)

Time: 1.092 ms

explain analyze select * from update_test where author_id=888 and author_seq in (35,250,333,420,950);
                                                         QUERY PLAN                                                          
-----------------------------------------------------------------------------------------------------------------------------
 Bitmap Heap Scan on update_test  (cost=36.31..1733.99 rows=2896 width=16) (actual time=0.180..0.224 rows=5 loops=1)
   Recheck Cond: ((author_id = 888) AND (author_seq = ANY ('{35,250,333,420,950}'::integer[])))
   ->  Bitmap Index Scan on update_test_pkey  (cost=0.00..35.58 rows=2896 width=0) (actual time=0.134..0.134 rows=6 loops=1)
         Index Cond: ((author_id = 888) AND (author_seq = ANY ('{35,250,333,420,950}'::integer[])))
 Total runtime: 0.287 ms
(5 rows)

Time: 2.449 ms

Annyi még, hogy i7, 8G, SSD. Nyilván a disket mérsékelten macerálta közben :)
21

Mérés jó

Pepita · 2013. Okt. 26. (Szo), 15.19
Ez már miért lenne így?

Említette, hogy kevés szerzőtől tízezernyi cikk.

A mérés +1, bár a szöveges mezők hiányában nyilván jóval kisebb a táblád a valódinál.
31

Ezért érdemes kitenni egy

BlaZe · 2013. Okt. 26. (Szo), 18.47
Ezért érdemes kitenni egy kapcsolótáblába.
24

Ezzel megintcsak az a baj,

tgr · 2013. Okt. 26. (Szo), 15.40
Ezzel megintcsak az a baj, hogy ezer cikkért kár nekiállni, az ORDER BY RAND() remekül működik.
25

Ha jól emlékszem

Pepita · 2013. Okt. 26. (Szo), 15.57
több tízezres nagyságrendről indultunk, és kijelentett tény, hogy lassú. Szerintem ezt higgyük el a kérdezőnek.
27

Akkor fogalmazzunk úgy, hogy

tgr · 2013. Okt. 26. (Szo), 16.28
Akkor fogalmazzunk úgy, hogy az értelmes mérés az lenne, ha BlaZe módszerének és az ORDER BY RAND()-nak az időigényét hasonlítanánk össze ugyanazon az adathalmazon.
32

Egyetértek, 1000 rekordnál (a

BlaZe · 2013. Okt. 26. (Szo), 19.05
Egyetértek, 1000 rekordnál (a laptopomon) 1 ms körül van a különbség. Ez a difi az esetek igen nagy százalékában belefér. Más a helyzet azonban, ha szerzőnként 100e rekordra módosítom a rekordokat.
select * from update_test where author_id=777 and author_seq in (350,15550,83133,70020,99950);
 outer_ref_id | author_id | author_seq 
--------------+-----------+------------
    108355315 |       777 |        350
    108370515 |       777 |      15550
    108424985 |       777 |      70020
    108438098 |       777 |      83133
    108454915 |       777 |      99950
(5 rows)

Time: 0.817 ms


select * from update_test where author_id=777 order by random() limit 5;
 outer_ref_id | author_id | author_seq 
--------------+-----------+------------
    108404008 |       777 |      49043
    108384339 |       777 |      29374
    108388754 |       777 |      33789
    108449042 |       777 |      94077
    108407012 |       777 |      52047
(5 rows)

Time: 48.233 ms
Ez már azért jelentős. Az előbbi query 0.7-1.1 ms között szór, utóbbi 35-50 ms között. Itt már persze az update sincs "ingyen".
delete from update_test where author_id=888 and author_seq=50000;
DELETE 1
Time: 3.354 ms

update update_test set author_seq=author_seq-1 where author_id=888 and author_seq>50000;
UPDATE 50000
Time: 533.242 ms
De igazából semmi szükség az összes nagyobb sequence-ű rekord módosítására, elég a legnagyobbat átírni a törölt sequence-ére, így csak 1 rekordot módosítunk.
update update_test set author_seq=50000 where author_id=888 and author_seq=(select max(author_seq) from update_test where author_id=888);
UPDATE 1
Time: 1.213 ms
Ez így kezelhető nagyobb rekordmennyiségnél is.
33

De igazából semmi szükség az

tgr · 2013. Okt. 26. (Szo), 19.45
De igazából semmi szükség az összes nagyobb sequence-ű rekord módosítására, elég a legnagyobbat átírni a törölt sequence-ére, így csak 1 rekordot módosítunk.


Erre nem gondoltam; így ez tűnik eddig a legjobb megoldásnak.
34

Úgy van

Pepita · 2013. Okt. 27. (V), 00.45
Ott a pont.
30

Sequence ID karbantartás

pkadam · 2013. Okt. 26. (Szo), 18.18
A karbantartás úgy is mehetne, hogy egy plusz táblában nyilván lennének tartva a törölt rekordok sequenceID-jai, és beszúráskor mindig ebből használnánk fel a legkisebbet (majd a "segéd-rekordot" töröljük). Így a folytonosság biztosítva lenne, és nem kell hozzá semmit update-elni, csak beszúráskor ránézni erre a táblára.
8

$rand = mt_rand(0,100);

szabo.b.gabor · 2013. Okt. 25. (P), 21.26
$rand = mt_rand(0,100); //vagy ami megfelel..

$sql='blabla where (id & '.$rand.') = '.$rand; // plusz még vmi egyéb random értéknél nagyobb id vizsgálat

esetleg union egyéb querykkel, hogy mindenképp meglegyen az 5 rekord..

pl ha valaminél nagyobbra szűrsz, akkor uniózd az annál kisebbekre is, két subquery limit 5, unió egészére limit 5 szintén

biztos lehet játszani

hátha kapsz valami ihletet..
9

Ez ugye szintén lassú lesz,

tgr · 2013. Okt. 25. (P), 22.31
Ez ugye szintén lassú lesz, de legalább nem is véletlenszerű.
10

Csinálsz egy extra mezőt,

tgr · 2013. Okt. 25. (P), 22.42
Csinálsz egy extra mezőt, mentéskor RAND()-ot írsz bele, indexeled, SELECT * WHERE rand > $random AND author = $authorId ORDER BY rand DESC LIMIT 1. Néha meg kell ismételni, mert az összes rand értéknél nagyobb számot választottál, de sok rekord esetén ennek kicsi az esélye (ha nincs sok rekordod, akkor meg használd az ORDER BY RAND()-ot).

Az öt cikket egyesével kell lekérni (esetleg egy únióval); szerintem ez semmilyen valóban véletlen kiválasztási módszernél nem kerülhető el.
29

Szimpatikus

pkadam · 2013. Okt. 26. (Szo), 18.08
Ez szimpatikus megoldásnak tűnik. Az ORDER BY rand viszont ASC kell, hogy legyen, különben mindig a legmagasabb random értékű sor fog megfelelni.

Illetve így egy rekord könnyen "hátrányos helyzetbe" kerülhet, ha olyan random értéket kap, ami épp egy kicsit nagyobb egy már létezőnél – mivel így csak akkor kerülhet kiválasztásra, ha a két érték közé esik a $random, tehát máris sérül a véletlenszerűség.
17

10-es

Pepita · 2013. Okt. 26. (Szo), 12.24
Szerintem eddig tgr 10-es kommentje a legjobb, én viszont másik irányba gondolkodnék:
összevegyítve eddigieket egy külön indextáblát csinálnék a random lekérdezéshez, cikk_id, szerző_id, random mezőkkel.
Természetesen kapcsolni kell ONDELETE-re.
A randomba egyszerűen beírsz egy jó nagy nagyságrendű véletlen számot.
- A lekérdezés szíve persze az indextábla, szűrsz szerzőre és egy generált számnál nagyobb értékre, LIMIT 5.
- Ha 5-nél kevesebb eredményt kaptál, akkor megnézed, hogy van-e 5 cikke a szerzőnek, ha van, akkor viszed lejjebb a generált számodat, mondjuk az eredeti 10 %-ával, és újra próbálsz. (Ha nem egyesével viszed lejjebb a számot, akkor picit sérül a véletlenszerűség, de egyesével meg hatalmas lekérdezésmennyiségbe futnál.)
- Ha kevesebb, mint 5 cikke van, akkor lekéred random nélkül az összeset.
- Persze JOIN a cikkekkel, de szerintem az nem jelent gondot.

Ha esetleg a sorrendnek is véletlenszerűnek kell lenni, akkor pl. crontabbal(*) rendszeresen update-eled a random értékeket, vagy csinálsz erre random2 oszlopot, és azt update-eled. Előbbi a "valódi véletlenszerűség" szempontjából jobb.
Természetesen mindehhez ügyes tranzakciókezelés is szükséges.

*: ha nincs cron, akkor pl. cikk insertkor, vagy minden 10. lekérdezés után (akár kiküldött kimenet után, hurokban), stb.
18

A limit 5-tel az a baj, hogy

tgr · 2013. Okt. 26. (Szo), 12.26
A limit 5-tel az a baj, hogy így csak az első cikk lesz véletlenszerű, adott cikk szomszédai mindig ugyanazok lesznek.
22

Cron

Pepita · 2013. Okt. 26. (Szo), 15.20
Erre van a cron és / vagy mégegy random mező.
23

Nem tudsz egyszerre több

tgr · 2013. Okt. 26. (Szo), 15.36
Nem tudsz egyszerre több random mezőt használni, én legalábbis nem látom, hogyan lehetne. Futtathatsz persze állandóan cront, de akkor nem vagy előrébb, mint az ORDER BY RAND()-dal.
26

Nem muszáj

Pepita · 2013. Okt. 26. (Szo), 16.02
több random, jobb az egy (akkor az 5 közötti sorrend is keveredik).
A cronnal, vagy ezt helyesen kiváltó eseményvezérléssel annyival vagyok beljebb, hogy a kimenet kiküldését nem lassítja, elvileg egyetlen szálon fut (ha valóban cron, akkor biztosan, egyébként meg egy egyszerű fájl IO-val lehet garantálni), és nem szükséges csak mondjuk 10 percenként futtatni, feladatfüggő. (Ugye jelezte is, hogy a cikkes történet csak példa, a tényleges feladat más.)

Ennyire egyedien gondolkodom?
28

Az írás belockloja a táblát,

tgr · 2013. Okt. 26. (Szo), 16.32
Az írás belockloja a táblát, én semmi nyilvánvaló okát nem látom, hogy miért lassítana kevésbé. Ha ritkán futtatja a cront, akkor meg rákattint a user az ajánlóra, és a következő cikk is ugyanazokat fogja ajánlani. Egy második random oszlopnak meg egyszerűen nem tudod hasznát venni.
35

Nem

Pepita · 2013. Okt. 27. (V), 00.53
a következő cikk is ugyanazokat fogja ajánlani
Nem, mert a viszonyítási alapot (ami szintén egy random) újból generálod. A cron-nak pusztán annyi a szerepe, hogy ha ugyanaz a kezdősorszámú ajánlott jön elsőnek, akkor mögötte már keveredés legyen. Ezt tesztekkel be lehet saccolni, hogy milyen sűrűre érdemes belőni,de szerintem min. 10 perc is jó. Több tízezres táblánál annak is kicsi az esélye, hogy belátható időn belül ugyanaz lesz a kezdő az ötből.

Szerk.: a lényeg, hogy nem a kiválasztott cikktől függ a kezdősorszám (hisz ez is feladat volt), hanem randomtól. Lehet, hogy nincs is jelentősége a cron-nak, mert mire kijön ugyanarra a cikkre ugyanaz a kezdő ajánlott, addigra rég elhal az a látogató, aki az elsőt generálta, mert eltelt vagy 100 év... :)
36

Hi! Ezt csinálnám: 1. Adott

halee · 2013. Okt. 27. (V), 07.22
Hi!

Ezt csinálnám:
1. Adott szerző cikk darabszámának lekérdezése
2. 5 (n) különböző random szám generálása 1. pontos darabszám maximummal
3. 5 (n) random számmal külön (vagy unionolva) alacsony költségű rowid-re rendezett selectek limittel: SELECT .... ORDER BY <rowid> LIMIT 1 OFFSET <random szám>
Mysql esetén LIMIT 1, <random szám>

H.

Szerk: igazából a rendezés bármire lehet (ha jól indexelt a mező/mezők), csak a rowid volt a legkézenfekvőbb...
Szerk2: fontos: a darab szám lekérdezésnél is csak a nem törölt rekordok darabszáma kell.
37

Nagy offsettel lekérdezni

tgr · 2013. Okt. 27. (V), 11.08
Nagy offsettel lekérdezni nagyon költséges művelet.
38

Ha tényleg nagyon kevés

inf · 2013. Okt. 29. (K), 02.11
Ha tényleg nagyon kevés szerző van, és mindegyikre kb azonos számú cikk jut, akkor meg lehet oldani úgy is, hogy random cikk id-ket generálsz, megkeresed a hozzájuk tartozó cikkeket (már ha léteznek), és ha megfelelnek a feltételekhez, akkor hozzáadod a listádhoz.

Pl: 2 szerző, 50-50% a cikkek aránya, 5 cikkre van szükséged: kiválasztasz 10 cikket teljesen random, aztán statisztikai alapon benne kell lennie 5-nek az egyik szerzőtől. Ennek a költsége nő a szerzők számával, és csak akkor működik hatékonyan, ha közel azonos számú cikk tartozik minden szerzőhöz.

Az egésznél az alap probléma, hogy a teljes eredményhalmazt rendezi az order miatt, és csak utána választ belőle a limit-nek megfelelőt. Helyette azt kéne, hogy lekérdezni az eredményhalmaz hosszát - hány rekord tartozik bele - és random rekord sorszámot generáltatni ez alapján, és utána sorszám alapján kikeresni a nekünk kellő rekordokat. Erre szerintem mysql nem képes, legalábbis nem tudok róla, hogy sorszámozná a találatokat, vagy hogy lenne bármilyen ezzel kapcsolatos függvény. Nyitottam egy témát ezzel a fajta megoldással kapcsolatban: http://stackoverflow.com/questions/19647474/mysql-order-by-rand-faster, kíváncsi vagyok, hogy mi jön ki belőle.
39

Ezt dobta a gép:

inf · 2013. Okt. 29. (K), 02.29
Ezt dobta a gép: http://jan.kneschke.de/projects/mysql/order-by-rand/
Szóval mysql-ben csak id alapján lehet tippelni, nincs beépített feature ilyesmire...
40

Nem néztem utána, de

MadBence · 2013. Okt. 29. (K), 02.38
Nem néztem utána, de fenntartom a véleményem, hogy a struktúra megváltoztatása nélküli (azaz mindenféle random mezők karbantartása nélküli) leggyorsabb, valóban egyenletes eloszlást biztosító, általános esetben is működő megoldás, ha a lekérdezés eredményének 5 random sorát adjuk vissza, ekkor nem kell redezni, és a seekelés is olcsó, ha indexelve van szerző szerint a tábla (hiszen csak azokat a sorokat kell ténylegesen beolvasni, amire szükségünk van). Ennél olcsóbban nem lehet megúszni...
41

Ja, de pontosan ez az, ami

inf · 2013. Okt. 29. (K), 02.46
Ja, de pontosan ez az, ami mysql-ben nincsen, mármint az "order by rand() limit x" láthatóan nem így működik, mert baromi lassú... Írni kéne ezzel kapcsolatban feature request-et, hogy optimalizáljanak már rá a kódjára, mert amit most csinál az valszeg előbb rendezi a teljes listát, és abból választja az első 5-öt, nem pedig a rendezetlen listából választ random 5-öt... Érdemes lenne egy "select count"-ot is lefuttatni, ha az lényegesen gyorsabb, mint az 5 véletlen sor kiválasztása, akkor tényleg rossz algoritmus alapján dolgozik, ha nem, akkor viszont tényleg ez a lehetőségekhez képest legjobban működő megoldás.
43

Ha jól értem, Bence azt

Joó Ádám · 2013. Okt. 29. (K), 03.04
Ha jól értem, Bence azt mondja, hogy alkalmazásoldalon válassz ki öt véletlen számot, aztán a teljes, rendezetlen eredményhalmazon végiglépkedve ezeket tárold, a többit dobd el.
44

Ez a random rendezős nem bug,

MadBence · 2013. Okt. 29. (K), 03.08
Ez a random rendezős nem bug, hanem egy olyan hack, ami véletlenül pont a várt végeredményt adja. Minden sorhoz rendel egy random értéket, ami alapján rendezi az eredményhalmazt.
Nem várható el, hogy a mysql kitalálja, hogy a fejlesztő valójában mit akart, és pláne nem azt, hogy ezt még ki is optimalizálja...
45

Ebben az esetben feature

inf · 2013. Okt. 29. (K), 03.23
Ebben az esetben feature request-et kell küldeni, mert nincs olyan nyelvi elem, amivel random lehet választani a találati listából. A limit-tel csak az első x db-ot lehet választani, lehetne LIMIT 5 RAND vagy hasonló... Nem tudom a többi relációs adatbázisnál hogy megy ez...
42

Küldjél rá légyszives két

inf · 2013. Okt. 29. (K), 02.52
Küldjél rá légyszives két SQL-t az adatbázisra:
SELECT * FROM articles WHERE articles.author_id = 1 ORDER BY RAND() LIMIT 5;
SELECT * FROM articles WHERE articles.author_id = 1 LIMIT 5;
Ha nagy a különbség a két idő között, akkor rossz az algoritmus, amit használnak és jelenteni kell a mysql-nek bug-ként. Ezt mondjuk nem én fogom megtenni, mert lusta vagyok oracle account-ot regisztrálni... :D