Mám jednu transformaci, ktera v MySQL trvá strašně dlouho (klidně proto, že jsem lopata :). Velmi zjednodušený popis:
Tabulka (106489 řádek, <4MB):
Sloupec "id" určuje nějakou událost, "partner" je dodavatel události (třeba nájemce záboru chodníku) a "start" říká, kdy nastala daná událost. Do tabulky doplňuju sloupec, který říká, kdy měl daný partner předchozí událost (pak se ty 2 datumy od sebe odečtou a zjistím, kolik dní uplnyulo od minulé události - partneři se v datech vyskytují opakovaně).
Tohle zpracování dělám v MySQL tímhle scriptem s "nested selectem":
Na AWS server cr1.8xlarge (88ECU, 244GB RAM, SSD) to trvá kolem 3000 vteřin (verze s JOINem (viz níže) přes 2 hodiny). Indexy mám správně :)
Zkusil jsem to samé pustit na HP Vertica, Google BigQuery a AWS Redshift. Na ničem kromě MySQL jsem neladil žádné parametry. Verticu a Redshift jsem do dneška nikdy neviděl, Google BigQuery používám delší dobu.
Nejde mi tam provést nested SELECT, tak jsem to upravil na "verzi s joinem"
Data jsem tam nahrál takhle:
COPY products FROM '/tmp/products.csv' DELIMITER ',' null AS 'null' EXCEPTIONS '/tmp/products.err';
Bez jakéhokoliv ladění to tam trvá 105 vteřin. To je 3.5% času na MySQL. Cool! Vertica (community edition) mi běží na m1.large serveru, což je největší popelnice, která v tomhle "testu" figuruje. Výsledek super!
V BQ jsem vyrobil projekt R&D a nahrál do něj data přímo z CSV:
bq load --noallow_quoted_newlines --max_bad_records 500 --skip_leading_rows=1 rad.products /tmp/products.csv id,partner,start
Spuštění téhle query zabralo 1695 vteřin (!!) a zprocesovalo 2.63MB. Trochu zklamání, něco musím dělat blbě, nechce se mi tomu věřit. Verzi s nested selectem jsem nezkoušel.
Nikdy jsem si s tím pořádně nehrál, četl jsem pár blogů (airbnb, hapyrus, botify) a dost jsem se na tuhle část těšil. Nahodit to je o stisknutí tlačítka, zvolil jsem režim "socky" a spustil single-node instanci dw.hs1.xlarge.
Data se tam nahrávají nejlépe z S3...
COPY products (id, partner, start) FROM 's3://padak-share/products.csv' CREDENTIALS 'aws_access_key_id=xyz;aws_secret_access_key=abc' delimiter ',' REMOVEQUOTES DATEFORMAT AS 'YYYY-MM-DD';
Zkusil jsem query s joinem:
CREATE TABLE out AS SELECT p1.start, p1.partner, p1.id, MAX(p2.start) FROM products p1 LEFT JOIN products p2 ON p1.partner = p2.partner WHERE p1.start > p2.start GROUP BY p1.start, p1.partner, p1.id;
i nested selectem:
SELECT start, partner, id, (SELECT MAX(start) FROM products WHERE start < p1.start AND p1.partner = partner) AS prev FROM products p1;
Varianta přes JOIN trvá 167 vteřin a varianta s nested selectem trvá 17,4 vteřiny (!!).
Potřeboval bych to ještě stejně spustit ve Vertice, kde mi nested select vrací "ERROR 4160: Non-equality correlated subquery expression is not supported", ale nevymyslel jsem kudy na to a víc času jsem tomu nechtěl věnovat. Dokud to nevymyslím, je Redshift největší powa, kterou jsem na tohle našel.
UPDATE 10.8.:
Dostal jsem tip od Kolese, že Vertica umí "INTERPOLATE JOIN". Podle semantiky popsané v dokumentaci to ale myslím nebude fungovat, protože to joinuje předchozí hodnoty pouze v situaci, kdy je z prava výsledek NULL. Já to potřebuju vždycky. Tuším ale, že to tam někde bude :-)