postgresql funkcja random()
zlotawy - 12-11-2006 01:31
postgresql funkcja random()
witam, czy jest jakis sprytny myk zeby przyspieszyc funkcje random() na bazie ze 100 000 rekordami?
wyglada mniej wiecej to tak:
select * from tabela order by X, random() limit 20
no i jest to lekko zabojcze. Chodzi mi o jakies praktyczne metody, myslalem zeby najpierew wylosowac fragment bazy i potem randomowac tylko rekordy z tego fragmentu.
chodzi mi po glowie zeby wyrzucic poza tabele randomowanie, ale nie wiem jak to zrobic.
Uzycie FETCH troche zbilo czas oczekiwania.
pozdrawiam zlotawy
Paweł Matejski - 12-11-2006 01:31
zlotawy wrote: > witam, > czy jest jakis sprytny myk zeby przyspieszyc funkcje random() na bazie ze > 100 000 rekordami? > > > wyglada mniej wiecej to tak: > > select * from tabela > order by X, random() > limit 20 > > no i jest to lekko zabojcze. Chodzi mi o jakies praktyczne metody, myslalem > zeby najpierew wylosowac fragment bazy i potem randomowac tylko rekordy z > tego fragmentu. > > chodzi mi po glowie zeby wyrzucic poza tabele randomowanie, ale nie wiem jak > to zrobic.
a) explain b) powiedz coś o X i czy masz na nim index c) co chcesz uzyskać tym random
-- P.M.
zlotawy - 12-11-2006 01:31
Użytkownik "Paweł Matejski" <madej@spam.madej.pl.eu.org> napisał w wiadomości news:efehdm$lju$1@inews.gazeta.pl...
> > a) explain > b) powiedz coś o X i czy masz na nim index > c) co chcesz uzyskać tym random
X to kolumna ktora zawiera radykalnie duzo NULLi i troszke char. Index btree nalozylem, ale o ile wiem na nullach to zbytnio nie podziala.
Random ma sprawic ze przy kazdym uruchomieniu uzyskam inna dwudziestke.
bede wdzieczny za jakikolwiek pomysl
zlotawy
Paweł Matejski - 12-11-2006 01:31
zlotawy wrote: > Użytkownik "Paweł Matejski" <madej@spam.madej.pl.eu.org> napisał w > wiadomości news:efehdm$lju$1@inews.gazeta.pl... > >> a) explain >> b) powiedz coś o X i czy masz na nim index >> c) co chcesz uzyskać tym random > > > X to kolumna ktora zawiera radykalnie duzo NULLi i troszke char. Index btree > nalozylem, ale o ile wiem na nullach to zbytnio nie podziala. > > Random ma sprawic ze przy kazdym uruchomieniu uzyskam inna dwudziestke. > > bede wdzieczny za jakikolwiek pomysl
Używając random tak jak w Twoim zapytaniu powodujesz, że baza musi przydzielić przypadkową liczbę WSZYSTKIM rekordom (czyli przeczytać całą tabelę). Dlatego żeby to ominąć trzeba dobrze wiedzieć do czego to potrzebujesz, żeby obejść problem. Możesz np. losować 20 id rekorów i wybierać tylko te rekordy. Ale to nie do każdego rozwiązania się nadaje.
-- P.M.
Antoni Jakubiak - 12-11-2006 01:31
zlotawy wrote: > Użytkownik "Paweł Matejski" <madej@spam.madej.pl.eu.org> napisał w > wiadomości news:efehdm$lju$1@inews.gazeta.pl... > >> a) explain >> b) powiedz coś o X i czy masz na nim index >> c) co chcesz uzyskać tym random > > > X to kolumna ktora zawiera radykalnie duzo NULLi i troszke char. Index btree > nalozylem, ale o ile wiem na nullach to zbytnio nie podziala.
Zaloz indeks warunkowy, np.: creat index a on tabela( x ) where x is not null; Nastepnie zmodyfikuj zapytanie: select * from tabela where x is not null order by X, random() limit 20;
Zadziała tylko wtedy, jezeli wartosci nie nullowych masz wiecej niz 20.
Pozdrawiam Antoni Jakubiak http://www.jakubiak.biz/
Michał Zaborowski - 12-11-2006 01:31
Jeżeli samo zapytanie nie jest kosztowne, można wylosować offset z count(*) - 20. W innym przypadku, może liczba zwracanych rekordów da się dobrze oszacować i wtedy zamiast count(*) można dać stałą. Tyle, że w offset nie można dać subquery, więc trzeba dwa zapytania wykonać... Może jakaś procedura, która przyjmie zapytanie wylosuje offset, wykona i zwróci zadaną liczbę wierszy?
-- Pozdrawiam, Michał Zaborowski (TeXXaS)
zlotawy - 12-11-2006 01:31
wykombinowalem dzisiaj cos takiego:
BEGIN WORK; create table tabela(),
insert into tabela (select COSTAM from (
TUTAJ JEST ZAPYTANIE KTOREGO DO TEJ PORY UZYWALEM) as wstawione
order by X,Random()
); --koniec inserta
create index index_Los on tabela(Los);
create index index_wyw on tabela(ANKIETERID);
COMMIT;
w ten sposob otrzymuje tabele, ktorej zawartosc jest polosowana jak nalezy
i teraz juz momentalnie wykonuje mi sie ponizszy select:
select * FROM tabela
WHERE SPORO_INNYCH_WARUNKOW
limit 20 offset 2000
--drop table tabela
utworzeni tej pierwszej tabeli zajmuje dlugo, ale musze to zrobic tylko raz. no i przy kazdej zmianie zawartosci pierwotnej tabeli, z ktorej powstaje ta nowa. myslalem ze perspektywa mi tu jakos pomoze, ale w perspektywie random wykonuje sie przy kazdym wywolaniu.
potem uzytkownicy juz z powyzszego selecta wynik maja niemal natychmiast (100 miliseknd)
nie jest to losowanie kazdorazowe, ale uzytkownik sie nie zorientuje, zwlaszcza jesli bede losowal jeszcze OFFSET.
generalnie jestem zadowolony, choc moze mozna uzyc czegos lepszego.. nie wiem np. kiedy sie korzysta z klastrowania.
dzieki za pomoc
zlotawy
Michał Zaborowski - 12-11-2006 01:32
zlotawy napisał(a):
[...]
Zostają jeszcze kursory... Nie trzeba tworzyć tabeli tymczasowej, przy 20 zwracanych rekordach procedura spokojnie może je zwracać...
> generalnie jestem zadowolony, choc moze mozna uzyc czegos lepszego.. nie > wiem np. kiedy sie korzysta z klastrowania. > Eeee - raczej nie do tego ;)
-- Pozdrawiam, Michał Zaborowski (TeXXaS)
Bartek Siebab - 12-11-2006 01:33
> zlotawy w dniu 2006-09-28 20:50 pisze: > wykombinowalem dzisiaj cos takiego: --<>-- > w ten sposob otrzymuje tabele, ktorej zawartosc jest polosowana jak nalezy > i teraz juz momentalnie wykonuje mi sie ponizszy select: --<>-- > utworzeni tej pierwszej tabeli zajmuje dlugo, ale musze to zrobic tylko raz. > no i przy kazdej zmianie zawartosci pierwotnej tabeli, z ktorej powstaje ta > nowa. myslalem ze perspektywa mi tu jakos pomoze, ale w perspektywie random > wykonuje sie przy kazdym wywolaniu. > > potem uzytkownicy juz z powyzszego selecta wynik maja niemal natychmiast > (100 miliseknd) > > nie jest to losowanie kazdorazowe, ale uzytkownik sie nie zorientuje, > zwlaszcza jesli bede losowal jeszcze OFFSET. > > generalnie jestem zadowolony, choc moze mozna uzyc czegos lepszego.. nie > wiem np. kiedy sie korzysta z klastrowania.
A czy do źródłowej tabeli nie możesz dodać dodatkowego pola np. los i przy wstawieniu rekordu od razu w to pole wpychać odpowiedni random? Później wystarczyło by tylko wygenerować jakieś dwie liczby random i zapytaniem wybrać z tej tabeli ograniczając pobierać where los between random1 and random2 limit ileśtam
-- ..---------- -------- ------ ---- ---- --- - -- - | Bartek `saphire` Siebab http://bartek.siebab.net
zanotowane.pldoc.pisz.plpdf.pisz.pleffulla.pev.pl
|
[PostgreSQL] - jak =?ISO-8859-2?Q?zabezpieczy=E6_interesy_tw?==?ISO-8859-2?Q?=F3rcy_systemu_=3F=3F=3F?=
postgresql - int/int
postgresql Select count(*) czy raczej Select count(ID)
[postgresql] INSERT OR UPDATE - jak =?ISO-8859-2?Q?b=EAdzie_na?==?ISO-8859-2?Q?jlepiej=3F?=
[postgresql] kilka =?ISO-8859-2?Q?rekord=F3w_subquery_jako_?==?ISO-8859-2?Q?string?=
Postgres - replikcja master-master
Dopasowanie do "najlepszego" dopasowania :) [ PostgreSQL]
Problemy z =?ISO-8859-2?Q?instalacj=B1_PostgreSQL_na_syste?==?ISO-8859-2?Q?mach_Windows?=
=?ISO-8859-2?Q?[psql]_Polskie_t=B3umaczenie_?= =?ISO-8859-2?Q?licencji_BSD_dla_PostgreSQL=3F?=
[firebird] Czym =?ISO-8859-2?Q?zast=B1pi=E6_postgresowy_inte?==?ISO-8859-2?Q?rval_=3F?=
zanotowane.pldoc.pisz.plpdf.pisz.platanvarne633.opx.pl
Cytat
Decede mihi sole - nie zasłaniaj mi słonca. Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści Hoc fac - tak czyń. A tergo - od tyłu; z tyłu. I czarne włosy posiwieją. Safona |
|