Author: depesz
tapeta na dzis
losowy rekord z bazy danych
czy stanęliście kiedyś przed problemem wylosowania rekordu z tabeli? dowolnego rekordu?
oczywistym pomysłem jest:
# SELECT * FROM tabelka ORDER BY random() LIMIT 1;
no ale to jest wolne. wymaga posortowania całej tabeli. co w najlepszym układzie ma złożoność "n log n".
przykładowo u mnie na testowej tabelce trwało to 90 sekund! (1.7 miliona rekordów).
no nie za dobrze.
niektórzy mogą sugerować takie rozwiązanie:
- znajdź maksymalne
- SELECT * FROM tabelka WHERE id <= random() * maksymalne_id limit 1;
na oko jest ok. tzn. akurat nie jest, bo random jest funkcją volatile, i trzeba by raczej … WHERE id <= (select random() * maksymalne_id) LIMIT 1, ale to już szczegół.
czemu to jest złe?
bo wprowadza pewien istotny problem. jeśli numeracja pola id w naszej tabelce zawiera dziury (czyli jest takie id, które jest większe od minimalnego i mniejsze od maksymalnego, dla którego nie ma rekordu) – to te losowane rekordy wcale nie będą dobrze losowane.
jako ekstremalny przykład (ale dobrze pokazujący rzeczywistość) podajmy tabelkę z dwoma rekordami, o id odpowiednio: 1 i 100. rekord z id = 1 będzie wypadał 99 razy częściej niż rekord z id = 100!.
cóż więc pozostaje? siąść i płakać?
nie.
można użyć inteligencji. czyli funkcji/procedury.
przykładowo taka funkcja:
CREATE OR REPLACE FUNCTION random_record() RETURNS tabelka AS $BODY$
DECLARE
id_min INT8;
id_max INT8;
range INT8;
temp_id INT8;
temprec RECORD;
BEGIN
SELECT min(id) INTO id_min FROM tabelka;
SELECT max(id) INTO id_max FROM tabelka;
range:= 1 + ( id_max - id_min );
LOOP
temp_id := id_min + (random() * range::float8)::INT8;
SELECT * INTO temprec FROM tabelka WHERE id = temp_id;
IF found THEN
RETURN temprec;
END IF;
END LOOP;
END;
$BODY$ language 'plpgsql';
co ona robi?zwraca losowy rekord. całkowicie losowy – każdy rekord ma te same szanse bycia wylosowanym.
warunki brzegowe? pole id musi być unikatowe (szokujące, nie?). no i: im więcej dziur w numeracji tym wolniej działa. ale co znaczy wolniej?
ta moja testowa tabelka ma takie dane:
# select min(id), max(id), count(*) from tabelka;
min | max | count
-----+----------+---------
3 | 36574227 | 1721217
(1 row)
czyli jak widać – dziur jest sporo. w szczególności – dziur jest 21 razy więcej niż istniejących rekordów!
przypomnę, że
select * from tabelka order by random() limit 1;
działało na tej tabelce w około 90 sekund.
ile czasu zajmuje to funkcji?
6 kolejnych wywołań. czasy odpowiednio: 124.700, 141.442, 201.708, 94.413, 145.128, 110.076. milisekund!
jak widać – jest szybko.
problemem tej funkcji jest to, że teoretycznie może się zdarzyć, że nigdy się nie skończy. ale w/g mnie jest to gdybanie. zresztą – zawsze można dorobić warunek, że jeśli np. wykonano już 1000 strzałów niecelnych, to zwróćmy pierwszy rekord z brzegu.
i już.
czy można to jakoś dopalić?
tak.
jeśli wiecie, że tabelka w której szukacie ma dużo dziur, to dodajcie do niej jedno pole:
create sequence random_thing_seq;
alter table tabelka add column random_thing int8;
alter table tabelka alter column random_thing set default nextval('random_thing_seq');
update tabelka set random_thing = nextval('random_thing_seq') where random_thing is null;
alter table tabelka alter column random_thing set not null;
create unique index ui_random_thing on tabelka (random_thing);
i potem używajcie w funkcji random_thing a nie id.
cel ćwiczenia?
jak sie pojawi za dużo dziur w numeracji (random_thing też będzie miał dziury) to zawsze możecie:
update tabelka set random_thing = nextval('random_thing_seq');
i już dziur nie ma,
a ponieważ random_thing nie jest do niczego innego używane – jest to w pełni bezpieczne.
oczywiście po takim update'cie dobrze jest zrobić vacuum'a. a najlepiej vacuum full'a.
mikro-dezynfekcja
jak każdy kto ma kuchnię, mam też zlew. przy nim różne gąbki, skrobaczki, myjki czy szczotki.
przeczytałem ostatnio, że w tych gąbkach zbiera się olbrzymia ilość bakterii – ciepło, wilgotno lub mokro non stop. żyć nie umierać.
ludzie którzy to napisali, napisali też, że jest prosta metoda na to by gąbkę pozbawić niechcianego towarzystwa. namoczyć i wstawić do mikrofali na 2 minuty na maksymalną moc.
nawet logiczne.
informacja jest fajna, podchwyciło ją wiele gazet i site'ów. podali.
no i tu zaczyna się haczyk.
część ludzi przeczytała, po czym zastosowała. zapominając o namoczeniu gąbki.
efekt? spalona gąbka, wszędzie pełno dymu, dom śmierdzi jak po paleniu opon. coś ślicznego. tak to po raz kolejny ludzkość udowodniła, że czytanie ze zrozumieniem to umierająca sztuka.
eh. a ja nie mam mikrofalówki 🙁
tapeta na dzis
tapeta na dzis
przełom w bateriach czy kolejna ściema?
eestor – firma o której nikt nigdy nie słyszał, wystąpiła ostatnio o patent na nowy typ baterii opartych o proszek barowo-tytanowy.
zgodnie z ich zapowiedziami do końca roku wejdą na rynek z produktem. a co produkt ma mieć?
- pojemność (przy porównaniu masy) 10 krotnie większą niż baterie ołowiano-kwasowe przy połowie ceny
- brak substancji toksycznych
tu pojawia sie wielkie "łał" i szacun od czytelników.
gdyby nie jedno ale.
wypowiedziało się parę osób ze sporą wiedzą i twierdzą, że zrobienie czegoś takiego jest fizycznie niemożliwe. że baterie (a dokładniej ultra-kondensatory, cokolwiek by to znaczyło) oparte o te technologie istnieją już od dawna, i są używane, ale istnieje jakaś bariera fizyczna której nie da sie pokonać i która uniemożliwia osiągnięcie tego o czym mówi eestor.
z drugiej strony – od zawsze wiadomo, że gdy 1000 ludzi wie, że coś jest niemożliwe, to przyjdzie 1001-a i to zrobi bo nie będzie wiedziała, że tego sie nie da.
co z tego wyjdzie? zobaczymy za jakiś czas.
pozostaje mieć nadzieję, że nie są to puste obietnice, i że słowa richarda weira (współtwórcy i szefa eestor) przełożą się na produkt.
przy tak dużym skoku jakościowo-cenowym możliwości są olbrzymie. zwłaszcza, że podobno produkt ma być stosowalny na każdą skalę: zegarki, laptopy, samochody.
sun na xeonach
sun oficjalnie ogłosił, że zacznie oferować serwery zbudowane w oparciu o procesory intela. jest to dosyć duże nowum. jeszcze nie dawno wszystko było oparte tylko o platformę sparc. potem doszły opterony z amd. teraz – sun musiał dojrzeć do tego, że nie sprzedawanie serwerów z xeonami obcina im potężną część zysków – we wszystkich nowych testach xeony biją na głowę opterony, a amd cały czas zwleka z kontratakiem.
tak czy inaczej – co z tego wyjdzie? większy wybór. i większa konkurencja. co powinno nam wszystkim wyjść na zdrowie 🙂
tani samochód od toyoty
toyota zapowiedziała prace nad ultra-tanim samochodem.
jako bezpośrednią przyczyne podano renault/dacia logan. samochód ten jest bardzo tani (jak na nowy) – kosztuje od 5,000€ (w polsce od 27,000pln).
co chce zrobić toyota? przebić tę ofertę. użyją ultra-tanich materiałów i technologii. jak trzeba, to stworzą coś zupełnie nowego. nie podano ceny nowego samochodu, ale ma być to "przynajmniej taniej niż logan".
pomysł jest mocno interesujący – toyota jest znana z jakości. może się okazać, że znajdą dużą ilość chętnych na takie autko. a stać ich na badania nad nowymi materiałami i technologiami – jeśli nie wydarzy się nic niesamowitego – w tym roku toyota prześcignie general motors i zostanie największym wytwórcą samochodów na świecie.
chyba to połamię
pamiętacie jak w "men in black" "jay" (grany przez wila smitha) dostął od "kay" (tommy lee jones) malutki pistolecik i powiedział: "feel like I'm gonna break this damn thing."?
właśnie takie uczucia budzą we mnie najnowsze telefony samsunga.
niedawno hitem był sgh-x820:
wymiary? 113 x 50 x 6.9mm. 6.9 mm grubości!
a i to im nie wystarczyło.
panowie z terminal.hu wywęszyli najnowszy model samsunga – na razie bez nazwy "numerkowej". znany jest jako "Samsung Ultra Edition 5.9". i ma 5.9 milimetra grubości. tak. o cały milimetr (niby niewiele, ale to prawie o 17% mniej).
a co ma poza anoreksją?
- aparat fotograficzny. 3 megapiksele.
- odtwarzacz mp3
- 80 megabajtów pamięci
- bluetooth
- tryb głośnomówiący
- odtwarzacz video (z 80 mega ramu? długie to te filmy nie będą)
- i wyjście na telewizor.
aargh. powinni do niego dodawać pancerne etui – aby się nie połamał na wietrze. wygląda podobno tak: