Forum » Izdelava spletišč » [Mysql]počasen rand in rešitve
[Mysql]počasen rand in rešitve
kriko1 ::
Danes sem izkusil kako počasna je fukncija RAND(), kjer se uporablja na določeni strani mojega portala.
Query je tak:
SELECT data.id, data.post FROM data ORDER by RAND() LIMIT 0,10;
Ko napolnem z bazo z npr. 1000 vnosi je razlika občutna, saj stran se nalaga že več sekund (5 - 10s).
Kako bi naredil drugače da mi povleče naključne podatke ki se ne ponavljajo?
Jaz sem začel nekaj pisat, ampak nastaja že cela solata iz skripte...
Query je tak:
SELECT data.id, data.post FROM data ORDER by RAND() LIMIT 0,10;
Ko napolnem z bazo z npr. 1000 vnosi je razlika občutna, saj stran se nalaga že več sekund (5 - 10s).
Kako bi naredil drugače da mi povleče naključne podatke ki se ne ponavljajo?
Jaz sem začel nekaj pisat, ampak nastaja že cela solata iz skripte...
iggy ::
a ne bi blo lažje da bi v programskem jeziku v katerem delaš naredil 10 random števil in potem te id-je vn iz baze potegneš?
Hey, you're fat!
CrustyDOD ::
Vsem znani problem.. Ne uporabljat ORDER BY RAND()..
Rešitev:
SELECT
*
FROM
tablename AS t1
JOIN
(
SELECT
ROUND(RAND() * (SELECT MAX(id) FROM tablename)) AS id
) AS t2
ON
t1.id >= t2.id
ORDER BY
t1.id ASC
LIMIT 1;
Več o samem problemu in rešitvi..
Rešitev:
SELECT
*
FROM
tablename AS t1
JOIN
(
SELECT
ROUND(RAND() * (SELECT MAX(id) FROM tablename)) AS id
) AS t2
ON
t1.id >= t2.id
ORDER BY
t1.id ASC
LIMIT 1;
Več o samem problemu in rešitvi..
kriko1 ::
BigWhale: Na podstrani je npr. 10 naključnih novic, torej ne morem uporabit za servirat enega uporabnika toliko časa.
CrustyDOD: To je zelo hitro, vendar problem nastane ko so luknje vmes in potem ne vrne toliko vnosov kot jaz hočem (npr. 10).
Nekaj bom še dodelal...
CrustyDOD: To je zelo hitro, vendar problem nastane ko so luknje vmes in potem ne vrne toliko vnosov kot jaz hočem (npr. 10).
Nekaj bom še dodelal...
ziga7 ::
BW pravi, da bi kljub 1000 vnosom, pa to sploh ni veliko, RAND kakorkoli že uporabljen moral delovati hitreje. Torej predpostavlja, da baza ni urejena tako kot se šika.
Si probal iggy-evo varianto?
Si probal iggy-evo varianto?
CrustyDOD ::
rand je v mysql bazi v k... po domače povedanoo. In ja, 1000 vnosov in mysql rand se že muči. Seveda odvisno od velikost tabele in indexov ampak se..
kriko1: ta query, ko ga executaš ti najde samo 1 random record! če daš limit 10, ti bo našel recimo record z IDjem 152 in vseh 9 ki sledijo tej številki, se pravi 153, 154,... zato, če hočeš dobiti 10 random vnosov, boš moral 10x pognat tist query in daš limit 1, ali pa kakšen union. Preberi tisto stran, proti koncu razloži kako dobiti več random vnosov. Ni druge..
kriko1: ta query, ko ga executaš ti najde samo 1 random record! če daš limit 10, ti bo našel recimo record z IDjem 152 in vseh 9 ki sledijo tej številki, se pravi 153, 154,... zato, če hočeš dobiti 10 random vnosov, boš moral 10x pognat tist query in daš limit 1, ali pa kakšen union. Preberi tisto stran, proti koncu razloži kako dobiti več random vnosov. Ni druge..
kriko1 ::
Ja, ampak težave so ko pridejo luknje vmes.
>There is no real solution for this problem, but your data is mostly constant you can add a mapping table which maps the row-number to the id.
Nekako mi ni všeč imet še eno tabelo, idejo imam da bi naredil npr. takole:
Konfiguracija skripte zahteva npr. 10 random različnih vnosov.
- na zgornji način poberem naključni blok in ga shranim v spremenljivko
- preštejem koliko vnosov sem dobil, če nimam 10 nadaljujem
- vzamem offset + 1 (naslednji blok 10 števil), če zaradi lukenj še vedno ne morem dopolnit prvega, vzamem offset -1
- od sredine prvega bloka se odmikam levo ter desno, dokler ne dobim vseh 10 vnosov, oz. dokler ne naletim na minId oz. maxId.
Meni se zdi v redu. Pozneje bom delal naprej na temu.
>There is no real solution for this problem, but your data is mostly constant you can add a mapping table which maps the row-number to the id.
Nekako mi ni všeč imet še eno tabelo, idejo imam da bi naredil npr. takole:
Konfiguracija skripte zahteva npr. 10 random različnih vnosov.
- na zgornji način poberem naključni blok in ga shranim v spremenljivko
- preštejem koliko vnosov sem dobil, če nimam 10 nadaljujem
- vzamem offset + 1 (naslednji blok 10 števil), če zaradi lukenj še vedno ne morem dopolnit prvega, vzamem offset -1
- od sredine prvega bloka se odmikam levo ter desno, dokler ne dobim vseh 10 vnosov, oz. dokler ne naletim na minId oz. maxId.
Meni se zdi v redu. Pozneje bom delal naprej na temu.
BigWhale ::
Ugh, ne. Naredi takole:
SELECT id FROM table;
Selektiras vse ali pa limitiras na neko smiselno stevilo, ce je teh vnosov resnicno prevec. Zbases jih v indexiran array, potem pa iz tistega arraya izberes deset nakljucnih elementov. To lahko celo tako pocnes, da v eni zanki loopas toliko casa, dokler ti en drug array ne naraste na velikost 10. Potem pa izvedes se en select.
SELECT * FROM table WHERE id IN ( array );
Ce je tisti random res tako pocasen, bo taka resitev boljsa, naredis samo dva klica na bazo, ker je recimo, da se sprejemljivo.
Ce imas pa id, ki je narascujoc in vmes IDji ne manjkajo in je v vseeno kateri vnos potegnes iz baze, samo da je random, potem se prvega selecta ne nucas. Potem samo deset random stevilk nastancas v skripti in potem naredis SELECT z IN.
SELECT id FROM table;
Selektiras vse ali pa limitiras na neko smiselno stevilo, ce je teh vnosov resnicno prevec. Zbases jih v indexiran array, potem pa iz tistega arraya izberes deset nakljucnih elementov. To lahko celo tako pocnes, da v eni zanki loopas toliko casa, dokler ti en drug array ne naraste na velikost 10. Potem pa izvedes se en select.
SELECT * FROM table WHERE id IN ( array );
Ce je tisti random res tako pocasen, bo taka resitev boljsa, naredis samo dva klica na bazo, ker je recimo, da se sprejemljivo.
Ce imas pa id, ki je narascujoc in vmes IDji ne manjkajo in je v vseeno kateri vnos potegnes iz baze, samo da je random, potem se prvega selecta ne nucas. Potem samo deset random stevilk nastancas v skripti in potem naredis SELECT z IN.
kriko1 ::
Če naredim select id, je tudi počasno na veliki tabeli, oz. se izvajanej skripte prekine (prekorači limit pomnilnika na skripto).
Naredil sem približno kot sem prej opisal, večino stvari opravljam v sami skripti in deluje bliskovito hitro.
Naredil sem približno kot sem prej opisal, večino stvari opravljam v sami skripti in deluje bliskovito hitro.
BigWhale ::
Če naredim select id, je tudi počasno na veliki tabeli, oz. se izvajanej skripte prekine (prekorači limit pomnilnika na skripto).
Emmm. Kaksno tabelo pa imas in kje imas indexe? Ker SELECT id FROM bla; bi moral delovati bliskovito hitro za prakticno kakrsno koli tabelo.
kriko1 ::
Baza je bila komaj kreirana, nobenih indexov ni.
Kakorkoli stvar je rešena, sedaj vidim da bi lahko še boljše naredil, tako da grem optimizirat.
Kakorkoli stvar je rešena, sedaj vidim da bi lahko še boljše naredil, tako da grem optimizirat.
iggy ::
ja fant, bo treba mal osnove dat čez, kako lahko narediš tabelo brez indexov?
Hey, you're fat!
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | [mySQL] Malo bolj kompliciran query :)Oddelek: Programiranje | 926 (726) | Old Spice |
» | MYSQL vprašanjeOddelek: Programiranje | 1763 (1378) | MrBrdo |
» | postgreSql/Mysql - počasen countOddelek: Programiranje | 1230 (1151) | yimi |
» | 2002-03-29 -> 29.3.2002Oddelek: Izdelava spletišč | 1575 (1401) | cahahopie |
» | Še eno mysql vprašanjeOddelek: Programiranje | 911 (836) | lordgreg |