5 rzeczy których nie chcieliście wiedzieć i nigdy o nie nie pytaliście.

co najmniej 3 osoby mnie naznaczyły (elf, ata i tmarc), więc lecimy:

  1. w 4 czy 5 klasie podstawówki przyniosłem do szkoły penthouse'a. koledzy mieli radochę, ja opierdziel.
  2. wyrzucono mnie ze szkoły (liceum) za to że namalowałem grafitti na korytarzu. tyle, że tego nie zrobiłem.
  3. mam kilka świetnych pomysłów na zarabianie kasy. i jedynie nie potrafię się zebrać w sobie i zabrać za to by je zrealizować. i tak od kilku lat. a pomysłów przybywa.
  4. nie mam w ogóle pamięci do twarzy czy nazwisk. jestem w stanie całkowicie bezstresowo nie zauważyć bądź nie poznać na ulicy osoby z którą pracuję od lat. co gorsza – nie robię tego celowo.
  5. nie czytam książek informatycznych. żadnych. niby jako programista/bazodanowiec powinienem, ale nudzą mnie. uważam, że jest z nimi jak ze świnkami morskimi – ani to świnka ani morska.

co do kolejnych ofiar:

  1. ads
  2. arim
  3. illi
  4. jarek zabiełło
  5. smoku

nowości w postgresie 8.3 – prompt

weszlo do cvs'a, wiec już chyba mogę opisać.

rzecz jest prosta.

od jakiegoś czasu w psql'u można używać zmiennych. przykład:

# \set a 123
# \set b '''depesz'''
# select :a, ':b';
?column? | ?column?
----------+----------
123 | depesz
(1 row)

zastosowanie jest oczywiste – prostsze pisanie sql'i z jakimiś zmiennymi.

minusy są dwa – utrudniona składnia do definiowania zmiennych tekstowych (potrójne apostrofy). i dwa – skoro i tak można tu ustawić tylko w skrypcie sql to funkcjonalność znikoma.

tak było do teraz.

ostatnio pojawił się patch na psql'a (i wszedł do cvs'a) dodający polecenie \prompt.

polecenie to pyta (zadanym tekstem) po czym odpowiedź użytkownika zapisuje do podanej zmiennej.

perfekcyjna sprawa gdy chcemy np. sparametryzować patch-bazodanowy.

przykład:

# \prompt 'Numeryczny identyfikator backupu? ' backup_id
Numeryczny identyfikator backupu? 123
# \echo :backup_id
123
# create table backup_:backup_id as select * from pg_proc;
SELECT
# select count(*) from backup_123;
count
-------
2007
(1 row)

sweet 🙂

zarabianie na linuksie

firmą która nieoczekiwanie (dla niej samej też) zaczęła nieźle zarabiać na linuksie okazało się hp.

w sierpniu 2005 roku ogłosili, że debian sarge będzie w pełni supportowany na ich serwerach. efekt? w roku rozliczeniowym 2006 okazało się, że mają sprzedaż za $25 milionów – sprzedaż która jest bezpośrednio powiązana z faktem istnienia tego supportu.

szefostwo hp'ka jest dosyć mocno zadowolone (też bym był) i zamierzają to dalej rozwijać. w toku jest ewaluacja etch'a (do tej pory supportem objęty jest jedynie sarge).

co ciekawe – debian nie jest pierwsza supportowana dystrybucja – wcześniej były suse i redhat, ale debian jest pierwszą całkowicie darmową. supportem objęte były jedynie komercyjne wersje suse i redhata.

tak czy inaczej – mnie to cieszy. używamy sporo hp'ków i fakt, że poważnie podchodzą do używania debiana bardzo mnie cieszy. a że na tym zarabiają – super, w końcu nie są organizacją charytatywną.

25 startupów

panowie z “business 2.0" napisali artykuł nt. 25 startupów web 2.0 które w/g nich mają największe szanse na sukces. warto spojrzeć – można znaleźć coś czego się nie znało, a jest fajne, lub po prostu jako podpowiedź przy inwestowaniu w akcje – w końcu każda z tych firm albo upadnie albo wejdzie na giełdę.

co wpływa na awarie dysków?

google przeprowadził na sporą skalę testy awaryjności dysków – stestowano ogółem 100,000 dysków o pojemnościach od 80 do 400 giga. dyski te były wcześniej używane przez google'a, więc (zgodnie z polityką google) nie były to jakieś cuda, tylko standardowe dyski dostępne w sklepach.

rezaultaty? przede wszystkim – brak powiązania między częstotliwością używania dysku a awaryjnością. to samo tyczy temperatury – niby wysoka temperatura szkodzi, ale w rzeczywistości tak nie jest.

jedynynie bardzo młode i bardzo stare dyski zachowują się zgodnie z popularnymi wierzeniami. dyski które nie padły od razu – trzymają się dobrze długo.

warto przeczytać cały tekst – daje kilka ciekawych informacji nt. symptomów i prawdopodobieństwa.

świetny biznes czy nieetyczne badanie rynku?

w stanach objawiła się firm citizenrē. coś co oferuje jest cudowne. wspaniałe. i (według wielu) nierealne.

co oferują?

jeśli podpiszesz z nimi umowę dostajesz za darmo instalację na swoim dachu ogniw fotoelektrycznych, po czym możesz korzystać z generowanego przez nie prądu bo niskich stawkach – poniżej stawek za standardowy prąd z elektrowni.

żadnych kosztów dodatkowych poza wpłatą zabezpieczającą – $500. sprzęt i instalacja gratis (sprzęt nie jest własnością klienta – zostaje własnością firmy, tak jak przy leasingu).

same zyski.

podobno instalacje mają się zacząć we wrześniu. firma twierdzi, że ma pieniądze na inwestycje ($650 milionów) i że w celu cięcia kosztów wybuduje własną fabrykę ogniw. największą na świecie.

pomysł nie jest nowy, wykonanie w sumie też nie – są firmy które coś takiego oferują klientom biznesowym. problemem jest tu skala przedsięwzięcia. sporo osób wątpi czy  citizenrē ma wystarczające fundusze by pokryć koszt instalacji tego wszystkiego dla wszystkich chętnych. w szczególności – część osób wątpi czy te fundusze w ogóle istnieją.

oliwy do ognia dolewa aura tajemnicy wokół firmy, oraz użyty przez nią schemat sprzedaży – znany z firmy typu amway czy oriflame – multi-level marketing.

na razie “handlowcy" nie dostają żadnej kasy i nikt nic nie wpłaca. stąd pojawiło się podejrzenie (wśród tych którzy nie wierzą w realność biznesplanu), że jest to po prostu darmowe badanie rynku na przyszłość. czy tak jest? nie wiadomo. wiem jedno – gdyby firma wystartowała i faktycznie robiła to co obiecuje – trzeba by ją natychmiast ściągnąć też do polski. choć z drugiej strony – u nas jest mało słońca. ale … może dorzucić do tego mały “wiatraczek"?

case study: join, subselect, indeksy + pomysł na “aliasy” wyliczanych stałych

kolega pokazał mi pewną sytuację. miał taką tabelę:

                 TABLE "public.staty"
COLUMN  |              Type              | Modifiers
---------+--------------------------------+-----------
DATA    | timestamp(0) without time zone | NOT NULL
size    | integer                        | NOT NULL
proto   | integer                        | NOT NULL
macfrom | integer                        | NOT NULL
macto   | integer                        | NOT NULL
Indexes:
"blah123" PRIMARY KEY, btree (macto, DATA, proto, macfrom)
"dupa" btree (DATA)
"f1" btree (macfrom)
"f2" btree (macto)
"fs" btree (size)
CHECK constraints:
"proto check" CHECK (proto < 65536 AND proto > -1)
Foreign-KEY constraints:
"staty_fk" FOREIGN KEY (macto) REFERENCES macs(id)
"staty_fk1" FOREIGN KEY (macfrom) REFERENCES macs(id)

z 3 milionami rekordów. i na tym zapytanie:

SELECT a.i AS dupa, sum(coalesce(b.size, 0)) AS to_, sum(coalesce(f.size, 0)) AS FROM
FROM (SELECT
((current_timestamp-'1 month'::INTERVAL) + INTERVAL '1 second'*c.it) AS inter,
i
FROM(
SELECT i, i * ((extract(epoch FROM NOW())::integer
-extract(epoch FROM (now()-'1 month'::interval))::integer)/600)
AS it FROM generate_series(0,599) i
) AS c
) AS a
LEFT JOIN
(SELECT  DATA, size FROM staty WHERE macto='$mac' ) b
ON (
b.DATA > (a.inter-(((extract(epoch FROM NOW())::integer
-extract(epoch FROM (now()-'1 month'::interval))::integer)/600)||' second')::interval )
AND
b.DATA < a.inter
)
LEFT JOIN
(SELECT  DATA, size FROM staty WHERE macfrom='$mac' ) f
ON(
f.DATA > (a.inter-(((extract(epoch FROM NOW())::integer
-extract(epoch FROM (now()-'1 month'::interval))::integer)/600)||' second')::interval )
AND
f.DATA < a.inter
)
GROUP BY a.i ORDER BY a.i

iiiś. poza “urodą" zapytania powalał czas: 120-200 sekund!

no muszę przyznać, że miałem bardzo duży problem by zrozumieć.

pierwsza rzecz – stwierdziłem, że przepiszę to zapytanie do postaci czytelnej.

i tu pojawił sie problem – w kodzie wielokrotnie występują pewne stałe wyliczane – now() – ‘1 month' czy to samo dzielone na 600.

jak będę je powtarzał za każdym razem to czytelność szlag trafi. na szczęście przypomniało mi się, że takie rzeczy można łatwo obejść aliasami.

chwila pisania i mamy zapytanie:

SELECT
g.i,
sum(coalesce(f.size, 0)) AS from_,
sum(coalesce(t.size, 0)) AS to_
FROM
generate_series(0,599) g(i),
staty f,
staty t,
(
SELECT
now() - '1 month'::INTERVAL AS start,
'1 second'::INTERVAL * extract(epoch FROM (now() - (now() - '1 month'::INTERVAL)))/600 as div
) x
WHERE
f.macfrom = '$mac'
AND t.macto = '$mac'
AND f.DATA BETWEEN (x.start + g.i * x.div) AND (x.start + (g.i + 1) * x.div)
AND t.DATA BETWEEN (x.start + g.i * x.div) AND (x.start + (g.i + 1) * x.div)
GROUP BY
g.i

(tu zwracam uwagę na subselect () x – to on robi za aliasy do stałych wyliczanych.

odtrąbiłem sukces. ale przedwcześnie. zapytanie wykonywało się w zasadniczo tym samym czasie = 128 – 160 sekund.

powiedziałem koledze by pozakładał indeksy wielopolowe:

create index some_name on staty (macfrom, data);
create index some_other_name on staty (macto, data);

te dwa indeksy i vacuum później (oj, dużo później) mamy efekt. zerowy. moje zapytanie nadal jest wolne. co ciekawe – oryginalne zapytanie nagle przyspieszyło do około 3.7 sekundy.

zastanowiłem się czemu. i nagle – olśnienie. zapytanie (w całości) operuje na dokładnie wszystkich danych z tabeli – tzn. ten miesiąc dla którego agregujemy dane to więcej niż danych jest w bazie – podobno koło tygodnia.

co oznacza, że musimy wyselectować całość. a że maszyna ma mało ramu, to szybciej sobie radzi z liczeniem popaczkowanym w małe części niż całości na raz.

tak więc kolejny rewrite:

SELECT
g.i,
(
SELECT sum(size) FROM staty WHERE macfrom = '$mac' AND data BETWEEN (x.start + g.i * x.div) AND (x.start + (g.i + 1) * x.div)
) as from_,
(
SELECT sum(size) FROM staty WHERE macto = '$mac' AND data BETWEEN (x.start + g.i * x.div) AND (x.start + (g.i + 1) * x.div)
) as to_
FROM
generate_series(0,599) g(i),
(
SELECT
now() - '1 month'::INTERVAL as start,
'1 second'::INTERVAL * extract(epoch FROM (now() - (now() - '1 month'::INTERVAL)))/600 as div
) x

i mamy czas – 170ms.

refleksje na przyszłość:

  • joiny są szybkie, chyba, że operujemy na dużych zbiorach danych na maszynach z małą ilością ramu
  • subselecty nie zawsze są wolne. zazwyczaj tak. ale w tym przypadku – gdzie tak naprawdę nic nie łączy danych z dwóch kopii tabeli staty – działają super
  • subselect jako metoda aliasowania wartości – czad. upraszcza pisanie, trochę przyspiesza i ułatwia zrozumienie kodu 🙂