ďťż
 
[pgsql] Losowy rekord - jak najszybciej? ďťż
 
[pgsql] Losowy rekord - jak najszybciej?
Zobacz wiadomości
 
Cytat
A gdyby tak się wedrzeć na umysłów górę, / Gdyby stanąć na ludzkich myśli piramidzie, / I przebić czołem przesądów chmurę, / I być najwyższą myślą wcieloną. . . Juliusz Słowacki, Kordian
Indeks BCB i MySQL subiekt gt fototapeta
 
  Witamy

[pgsql] Losowy rekord - jak najszybciej?



ethanak - 10-09-2006 00:16
[pgsql] Losowy rekord - jak najszybciej?
  Witam

Od razu na wstępie: jestem po przejrzeniu archiwum i coś już tam wyczytałem.

Mam takie trzy tabelki:

create table a(klucz text);

create table b(klucz text references a(klucz),... reszta nieważna);

create table c(klucz text references a(klucz),
typ text,
kiedy date,
...reszta nieważna);

Chodzi mi o wyciągnięcie losowo wybranego klucza dla podanego typu
spełniającego następujące założenia:

a) klucz musi występować w tabeli b;
b) para klucz - typ nie występuje w tabeli c, lub w przypadku gdy
występuje należy wybrać dowolny klucz z najstarszym 'kiedy' pod
warunkiem że jest to nie później niż przedwczoraj.

(mam nadzieję że jasno się wyraziłem)

Przewidywane rozmiary tabel:
a - max. 100000;
b - mniej więcej rozmiaru a;
c - 10 x wielkość a;

Jak na razie moje próby przy kilku tysiącach rekordów nie napawająmnie
zbytnim optymizmem :(

No i pytania dwa:

a) jak to zrobić aby było najszybciej?

b) czy nie lepiej rozbić to na dwa zapytania (pierwsze dla elementów
które nie występują w c, drugie dla wybrania najstarszego).

Dodam, że dane w tabeli c zmieniają się dość często (tzn. praktycznie
jednemu wykonaniu powyższego zapytania odpowiada jedna modyfikacja tabeli c)

ethanak
--
mailto=window.atob('ZXRoYW5ha0Bwb2xpcC5jb20=');





Michał Zaborowski - 10-09-2006 00:16

  Najszybciej to zrobić tabel 'with oids' i oprzeć
generowanie losowych wartości na oidach. To jest
też chyba najprostsze rozwiązanie.

--
Pozdrawiam,
Michał Zaborowski (TeXXaS)




ethanak - 10-09-2006 00:16

  Michał Zaborowski napisał(a):
> Najszybciej to zrobić tabel 'with oids' i oprzeć
> generowanie losowych wartości na oidach. To jest
> też chyba najprostsze rozwiązanie.
>
Tylko że w tym przypadku dwa egzemplarze aplikacji łączące się z bazą
dostaną te same rekordy - a ja chcę żeby dostały w miarę możliwości
różne. W tej chwili rozwiązuję to poprzez ustawienie seeda z poziomu
aplikacji na podstawie /dev/urandom i to akurat działa...

ethanak
--
mailto=window.atob('ZXRoYW5ha0Bwb2xpcC5jb20=');
/* Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
S. Friedmann/J. Kofta */




Michał Zaborowski - 10-09-2006 00:16

  No to sporo się wyjaśniło - przynajmniej dla mnie. ;)
Mówię o 'najszybciej' w tytule.
To random z PG zwraca te same dane? AFAIR działa i to
bardzo dobrze - można więc zrobić zapytanie 'select' o
losowy rekord. Nie ma potrzeby przewalania danych i
odpytywania się o losowy wiersz. OID jest po to, żeby
można było zrobić losowanie na poziomie WHERE a nie w
OFFSET, albo z podzapytaniem.

--
Pozdrawiam,
Michał Zaborowski (TeXXaS)





ethanak - 10-09-2006 00:16

  Michał Zaborowski napisał(a):
[...]
> To random z PG zwraca te same dane? AFAIR działa i to
> bardzo dobrze - można więc zrobić zapytanie 'select' o
> losowy rekord.

No kur... zabij nie wiem czemu ale wczoraj uparcie zwracał mi to samo -
pewnie jakiś błąd w aplikacji (teraz nie do sprawdzenia bo wczorajszych
kodów raczej nie mam). Ale to akurat nieważne.

> Nie ma potrzeby przewalania danych i
> odpytywania się o losowy wiersz. OID jest po to, żeby
> można było zrobić losowanie na poziomie WHERE a nie w
> OFFSET, albo z podzapytaniem.

OK, dobra, to powiedz jak bo nie bardzo mogę sobie to wyobrazić?

ethanak
--
mailto=window.atob('ZXRoYW5ha0Bwb2xpcC5jb20=');
/* Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
S. Friedmann/J. Kofta */




Michał Zaborowski - 10-09-2006 00:16

  ethanak napisał(a):
> Michał Zaborowski napisał(a):
> [...]
>> To random z PG zwraca te same dane? AFAIR działa i to
>> bardzo dobrze - można więc zrobić zapytanie 'select' o
>> losowy rekord.
>
> No kur... zabij nie wiem czemu ale wczoraj uparcie zwracał mi to samo -
> pewnie jakiś błąd w aplikacji (teraz nie do sprawdzenia bo wczorajszych
> kodów raczej nie mam). Ale to akurat nieważne.
>
CVS, SVN? To pierwsze mniejsze to drugie potężniejsze :)

>> Nie ma potrzeby przewalania danych i
>> odpytywania się o losowy wiersz. OID jest po to, żeby
>> można było zrobić losowanie na poziomie WHERE a nie w
>> OFFSET, albo z podzapytaniem.
>
Dobra, co do podzapytania to trochę przesadziłem... ;)

> OK, dobra, to powiedz jak bo nie bardzo mogę sobie to wyobrazić?
>
? Tak myślałem, że się do tego sprawadzi, ale zawsze
można mieć nadzieję...

Zapytanie może wyglądać np. tak:
select oid
from tbl
where oid = (random() * (select max(oid) from tbl))::int4

Można też przyspieszyć zapamiętując max(oid), ale od 8.1 PG
używa tu indeksu i za wiele się nie zyska.

--
Pozdrawiam,
Michał Zaborowski (TeXXaS)




ethanak - 10-09-2006 00:16

  On 2006-09-05 14:24, Michał Zaborowski wrote:
[...]
>> wczorajszych kodów raczej nie mam). Ale to akurat nieważne.
>>
> CVS, SVN? To pierwsze mniejsze to drugie potężniejsze :)

A po ciężki puhw mi źródła niedziałającego programu? Ani bloga sobie nie
założyłem, ani zeszyciku z króliczkiem na okładce nie mam...

[...]
>> OK, dobra, to powiedz jak bo nie bardzo mogę sobie to wyobrazić?
>>
> ? Tak myślałem, że się do tego sprawadzi, ale zawsze
> można mieć nadzieję...

Tak - można mieć nadzieję że gość co się zajmuje programowaniem zupełnie
innych rzeczy w C tudzież pewnymi wybranymi aspektami projektowania
stron WWW nagle zostanie mistrzem w Postgresie.

>
> Zapytanie może wyglądać np. tak:
> select oid
> from tbl
> where oid = (random() * (select max(oid) from tbl))::int4

Przykro - does not work. Ilość wierszy zero nie jest specjalnie
interesująca.

Ergo: albo chcesz mi pomóc, albo powiedz po prostu że się nie znam i
jako lejek mam nie wpierdalać się w rozmowy Wielkich Specjalistów.

ethanak
--
mailto=window.atob('ZXRoYW5ha0Bwb2xpcC5jb20=');




hubert depesz lubaczewski - 10-09-2006 00:16

  On 2006-09-05, ethanak <sweethanak@buziaczek.pl> wrote:
> create table a(klucz text);
> create table b(klucz text references a(klucz),... reszta nieważna);
> create table c(klucz text references a(klucz),

1. fatalnie, że to tekst.
2. nie dałyś rady dołożyć primary keya na int'cie?
3. jak często robisz delete? insert i update mnie nie interesuje.

depesz

--
http://www.depesz.com/index.php/2006...udzi-do-pracy/




hubert depesz lubaczewski - 10-09-2006 00:59

  On 2006-09-07, ethanak <sweethanak@buziaczek.pl> wrote:
> On 2006-09-06 19:40, hubert depesz lubaczewski wrote:
> [...]
>> pomogło?
>
> Pewnie by pomogło gdyby nie jeden drobiazg.
>
> Ten sposób pozwala na wyciągnięcie losowego rekordu z całej tabelki.
> Tymczasem ja potrzebuję wyciągnięcia losowego rekordu z tabelki
> spełniającego jakiśtam warunek, przy czym może zaistnieć sytuacja że
> taki rekord w ogóle nie istnieje, albo jest tylko jeden w tabeli mającej
> 100k rekordów...
>
> W wersji roboczej mam "order by random() limit 1" (wyczytane w archiwum
> właśnie) ale to mi się niespecjalnie podoba :(
>
> A tak przy okazji: czy wykonanie setval('randomizer_seq',0) przed
> "update tabelka..." nie oszczędziłoby jednego zapytania w random_id()?

nie za bardzo. bo i tak nie można nigdy zakładać, że to się nie zmieni.

a select min w postgresach nowych jest szybciutki.

depesz

--
http://www.depesz.com/index.php/2006...udzi-do-pracy/




ethanak - 10-09-2006 00:59

  hubert depesz lubaczewski napisał(a):
[...]
>>A tak przy okazji: czy wykonanie setval('randomizer_seq',0) przed
>>"update tabelka..." nie oszczędziłoby jednego zapytania w random_id()?
>
>
> nie za bardzo. bo i tak nie można nigdy zakładać, że to się nie zmieni.
>
> a select min w postgresach nowych jest szybciutki.

W sumie racja.

BTW problem rozwiązałem na poziomie aplikacji (tzn. nie dokładnie tak
jak chciałem, ale do moich celów wystarczający).

ethanak
--
mailto=window.atob('ZXRoYW5ha0Bwb2xpcC5jb20=');
/* Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
S. Friedmann/J. Kofta */
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • effulla.pev.pl
  • comp
    [ms sql] =?ISO-8859-2?Q?wy=B6wietlenie_pierwszych_5_rekord?==?ISO-8859-2?Q?=F3w_z_zapytania_=3F_odpowiednik_ROWNUM_w_o?== ?ISO-8859-2?Q?raclu_dla_MS_SQL=27a?= [MySQL] =?ISO-8859-2?Q?Wy=B6wietlenie_kolejnej_pozycji=2C_?==?ISO-8859-2?Q?jak=B1_mia=B3by_dany_rekord=2C_gdybym_czyta=B3 _?==?ISO-8859-2?Q?wg_konkretnych_kryteri=F3w=2E_Da_si=EA_=3F?= =?ISO-8859-2?Q?Narz=EAdzie_do_budowania_zapyta=F1_SQL=2C?==?I SO-8859-2?Q?_PL/PgSQL=2C_PL/SQL=2C_T-SQL?= Jak =?ISO-8859-2?Q?zamieni=E6_dwa_pola_jednej_kolumny_?==?ISO-8859-2?Q?w_dw=F3ch_rekordach_za_pomoc=B1_jednego_zapyt? ==?ISO-8859-2?Q?ania=3F?= [mysql/php] jak =?ISO-8859-2?Q?zliczy=E6_ilo=B6=E6_unikalnyc?==?ISO-8859-2?Q?h_rekord=F3w_w_jednym_zapytaniu=3F?= =?ISO-8859-2?Q?WY=B6wietlenie_rekord=F3w_pocz=B1wszy_od_?==?I SO-8859-2?Q?danej_litery=2E=2E=2E?= =?iso-8859-2?Q?=5BMySQL=5D_Wy=B6wietlenie_wszystkich_rekordow _zawierajacy?==?iso-8859-2?Q?ch_duplikat_a__moze_inna_struktura_bazy_danych ?= [postgresql] kilka =?ISO-8859-2?Q?rekord=F3w_subquery_jako_?==?ISO-8859-2?Q?string?= [mysql] Wyszukanie =?ISO-8859-2?Q?rekord=F3w=28powiazane_tabel?==?ISO-8859-2?Q?e=29?= [MySQL]: Dodanie zliczania =?ISO-8859-2?Q?rekord=F3w_do_rozb?==?ISO-8859-2?Q?udowanego_zapytania?=
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • radioaktywni.htw.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

    Valid HTML 4.01 Transitional

    Free website template provided by freeweblooks.com