Anailísíocht oibriúcháin san ailtireacht mhicriseirbhíse: cuidigh le Postgres FDW agus cuir leid

Tá buntáistí agus míbhuntáistí ag baint le hailtireacht microservice, cosúil le gach rud sa saol seo. Éiríonn roinnt próiseas níos fusa leis, agus cinn eile níos deacra. Agus ar mhaithe le luas an athraithe agus scalability níos fearr, ní mór duit íobairtí a dhéanamh. Ceann acu is ea castacht na hanailíse. Más rud é i monolith is féidir gach anailísíocht oibriúcháin a laghdú go fiosruithe SQL go macasamhail anailíseach, ansin in ailtireacht ilseirbhíse tá a bunachar sonraí féin ag gach seirbhís agus is cosúil nach leor ceist amháin (nó b'fhéidir go mbeidh?). Dóibh siúd a bhfuil suim acu sa chaoi ar réitigh muid fadhb na hanailísíochta oibriúcháin inár gcuideachta agus conas a d'fhoghlaim muid maireachtáil leis an réiteach seo - fáilte roimh chách.

Anailísíocht oibriúcháin san ailtireacht mhicriseirbhíse: cuidigh le Postgres FDW agus cuir leid
Pavel Sivash is ainm dom, ag DomClick Oibrím i bhfoireann atá freagrach as an stóras sonraí anailíse a chothabháil. Go traidisiúnta, is féidir ár ngníomhaíochtaí a chur i leith innealtóireacht sonraí, ach, i ndáiríre, tá raon na dtascanna i bhfad níos leithne. Tá innealtóireacht sonraí caighdeánach ETL / ELT, tacaíocht agus oiriúnú uirlisí anailíse sonraí agus forbairt a n-uirlisí féin. Go háirithe, maidir le tuairisciú oibríochta, bheartaíomar “a ligean orainn” go bhfuil monolith againn agus bunachar sonraí amháin a thabhairt d’anailísithe ina mbeidh na sonraí go léir a theastaíonn uathu.

Go ginearálta, mheasamar roghanna éagsúla. Bhíothas in ann stór lán-chuimsitheach a thógáil - rinneamar iarracht fiú, ach, le bheith macánta, ní raibh muid in ann cairde a dhéanamh le hathruithe measartha minic sa loighic le próiseas sách mall chun stór a thógáil agus athruithe a dhéanamh air ( dá n-éireodh le duine, scríobh isteach na tuairimí conas). D’fhéadfá a rá le hanailísithe: “A bhuachaillí, foghlaim python agus téigh go línte anailíse,” ach is riachtanas earcaíochta breise é seo, agus ba chosúil gur cheart é seo a sheachaint más féidir. Shocraigh muid triail a bhaint as teicneolaíocht FDW (Foreign Data Wrapper): i ndáiríre, is dblink caighdeánach é seo, atá i gcaighdeán SQL, ach lena chomhéadan i bhfad níos áisiúla. Ar a bhonn, rinneamar cinneadh, rud a ghlac fréamhú sa deireadh, shocraigh muid air. Tá a chuid sonraí mar ábhar airteagal ar leith, agus b'fhéidir níos mó ná ceann amháin, mar ba mhaith liom labhairt faoi go leor: ó sioncrónaithe scéimre bunachar sonraí chun rochtain a rialú agus díphearsanta sonraí pearsanta. Ba chóir a thabhairt faoi deara freisin nach bhfuil an réiteach seo in ionad bunachair shonraí agus stórtha anailíse fíor, ní réitíonn sé ach fadhb shonrach.

Ag an leibhéal is airde tá sé mar seo:

Anailísíocht oibriúcháin san ailtireacht mhicriseirbhíse: cuidigh le Postgres FDW agus cuir leid
Tá bunachar sonraí PostgreSQL ann inar féidir le húsáideoirí a gcuid sonraí oibre a stóráil, agus níos tábhachtaí fós, tá macasamhla anailíseacha de na seirbhísí go léir ceangailte leis an mbunachar sonraí seo trí FDW. Fágann sé seo gur féidir ceist a scríobh chuig bunachair shonraí éagsúla, agus is cuma cad é: PostgreSQL, MySQL, MongoDB nó rud éigin eile (comhad, API, más rud é go tobann nach bhfuil fillteán oiriúnach ann, is féidir leat do chuid féin a scríobh). Bhuel, is cosúil go bhfuil gach rud iontach! Ag briseadh suas?

Dá dtiocfadh deireadh le gach rud chomh gasta agus chomh simplí sin, ansin, is dócha, ní bheadh ​​an t-alt ann.

Tá sé tábhachtach a bheith soiléir faoin gcaoi a láimhseálann postgres iarratais chuig cianfhreastalaithe. Is cosúil go bhfuil sé seo loighciúil, ach is minic nach dtugann daoine aird air: roinneann postgres an cheist i gcodanna a fhorghníomhaítear go neamhspleách ar fhreastalaithe iargúlta, bailíonn sé na sonraí seo, agus déanann sé na ríomhanna deiridh féin, mar sin beidh luas forghníomhaithe an fhiosrúcháin ag brath go mór ar conas tá sé scríofa. Ba chóir a thabhairt faoi deara freisin: nuair a thagann na sonraí ó chianfhreastalaí, níl innéacsanna acu a thuilleadh, níl aon rud a chabhróidh leis an sceidealóir, mar sin, ní féidir ach linne féin cabhrú agus é a mholadh. Agus sin cad ba mhaith liom a labhairt faoi níos mine.

Iarratas simplí agus plean leis

Chun a thaispeáint conas a cheistíonn Postgres tábla ró-6 milliún ar fhreastalaí cianda, breathnaímid ar phlean simplí.

explain analyze verbose  
SELECT count(1)
FROM fdw_schema.table;

Aggregate  (cost=418383.23..418383.24 rows=1 width=8) (actual time=3857.198..3857.198 rows=1 loops=1)
  Output: count(1)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.00..402376.14 rows=6402838 width=0) (actual time=4.874..3256.511 rows=6406868 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Remote SQL: SELECT NULL FROM fdw_schema.table
Planning time: 0.986 ms
Execution time: 3857.436 ms

Trí úsáid a bhaint as an ráiteas VERBOSE is féidir leat an cheist a sheolfar chuig an gcianfhreastalaí agus na torthaí a gheobhaimid le haghaidh próiseála breise a fheiceáil (teaghrán RemoteSQL).

A ligean ar dul beagán níos faide agus cuir roinnt scagairí lenár gceist: ceann ar aghaidh Boole réimse, ceann ar iontráil stampa ama in aghaidh an eatraimh agus ceann i ndiaidh jsonb.

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table 
WHERE is_active is True
AND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month' 
AND CURRENT_DATE - INTERVAL '6 month'
AND meta->>'source' = 'test';

Aggregate  (cost=577487.69..577487.70 rows=1 width=8) (actual time=27473.818..25473.819 rows=1 loops=1)
  Output: count(1)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.00..577469.21 rows=7390 width=0) (actual time=31.369..25372.466 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Filter: (("table".is_active IS TRUE) AND (("table".meta ->> 'source'::text) = 'test'::text) AND ("table".created_dt >= (('now'::cstring)::date - '7 mons'::interval)) AND ("table".created_dt <= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))
        Rows Removed by Filter: 5046843
        Remote SQL: SELECT created_dt, is_active, meta FROM fdw_schema.table
Planning time: 0.665 ms
Execution time: 27474.118 ms

Seo an áit a luíonn an nóiméad, ar gá duit aird a thabhairt air agus tú ag scríobh ceisteanna. Níor aistríodh na scagairí chuig an gcianfhreastalaí, rud a chiallaíonn go dtarraingíonn Postgres na 6 mhilliún sraith ar fad chun iad a scagadh go háitiúil níos déanaí (an líne Scagaire) agus comhiomlánú a dhéanamh. Is í an eochair do rathúlacht ná ceist a scríobh ionas go dtarchuirfear na scagairí chuig an gcian-inneall, agus ní fhaighimid agus ní dhéanaimid ach na sraitheanna riachtanacha a chomhiomlánú.

Sin roinnt booleanshit

Le réimsí boolean, tá gach rud simplí. Sa bhuncheist, ba é an t-oibreoir ba chúis leis an bhfadhb is. Má táimid ina ionad le =, ansin faighimid an toradh seo a leanas:

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table
WHERE is_active = True
AND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month' 
AND CURRENT_DATE - INTERVAL '6 month'
AND meta->>'source' = 'test';

Aggregate  (cost=508010.14..508010.15 rows=1 width=8) (actual time=19064.314..19064.314 rows=1 loops=1)
  Output: count(1)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.00..507988.44 rows=8679 width=0) (actual time=33.035..18951.278 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Filter: ((("table".meta ->> 'source'::text) = 'test'::text) AND ("table".created_dt >= (('now'::cstring)::date - '7 mons'::interval)) AND ("table".created_dt <= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))
        Rows Removed by Filter: 3567989
        Remote SQL: SELECT created_dt, meta FROM fdw_schema.table WHERE (is_active)
Planning time: 0.834 ms
Execution time: 19064.534 ms

Mar a fheiceann tú, d'eitil an scagaire chuig an gcianfhreastalaí, agus laghdaíodh an t-am forghníomhaithe ó 27 go 19 soicind.

Ba chóir a thabhairt faoi deara go bhfuil an t-oibreoir is difriúil ón oibreoir = an ceann is féidir a oibriú leis an luach Null. Ciallaíonn sé sin nach bhfuil Fíor sa scagaire fágfaidh na luachanna Bréagach agus Neamhní, agus != Fíor fágfar luachanna bréagacha amháin. Dá bhrí sin, nuair a athsholáthar an t-oibreoir Níl ba cheart duit dhá choinníoll a chur ar aghaidh chuig an scagaire leis an oibreoir OR, mar shampla, CÁ (col! = Fíor) NÓ (Col is null).

Le boolean figured amach, ag bogadh ar aghaidh. Idir an dá linn, cuirimis an scagaire ar ais de réir luach boolean chuig a bhunfhoirm chun éifeacht athruithe eile a mheas go neamhspleách.

stampa ama? hz

Go ginearálta, is minic a chaithfidh tú triail a bhaint as conas ceist a scríobh i gceart a bhaineann le cianfhreastalaí, agus gan ach ansin míniú a lorg ar an bhfáth go bhfuil sé seo ag tarlú. Is beag eolas faoi seo atá le fáil ar an Idirlíon. Mar sin, i dturgnaimh, fuaireamar amach go n-eitiltíonn scagaire dáta socraithe chuig cianfhreastalaí le bang, ach nuair is mian linn an dáta a shocrú go dinimiciúil, mar shampla, anois() nó CURRENT_DATE, ní tharlaíonn sé seo. Inár sampla, tá scagaire curtha leis againn ionas go mbeidh sonraí sa cholún Create_at ar feadh 1 mhí go díreach san am a chuaigh thart (Idir CURRENT_DATE - INTERVAL '7 mí' AGUS CURRENT_DATE - INTERVAL '6 mhí'). Cad a rinne muid sa chás seo?

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table 
WHERE is_active is True
AND created_dt >= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 month') 
AND created_dt <(SELECT CURRENT_DATE::timestamptz - INTERVAL '6 month')
AND meta->>'source' = 'test';

Aggregate  (cost=306875.17..306875.18 rows=1 width=8) (actual time=4789.114..4789.115 rows=1 loops=1)
  Output: count(1)
  InitPlan 1 (returns $0)
    ->  Result  (cost=0.00..0.02 rows=1 width=8) (actual time=0.007..0.008 rows=1 loops=1)
          Output: ((('now'::cstring)::date)::timestamp with time zone - '7 mons'::interval)
  InitPlan 2 (returns $1)
    ->  Result  (cost=0.00..0.02 rows=1 width=8) (actual time=0.002..0.002 rows=1 loops=1)
          Output: ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.02..306874.86 rows=105 width=0) (actual time=23.475..4681.419 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Filter: (("table".is_active IS TRUE) AND (("table".meta ->> 'source'::text) = 'test'::text))
        Rows Removed by Filter: 76934
        Remote SQL: SELECT is_active, meta FROM fdw_schema.table WHERE ((created_dt >= $1::timestamp with time zone)) AND ((created_dt < $2::timestamp with time zone))
Planning time: 0.703 ms
Execution time: 4789.379 ms

Spreagamar an pleanálaí an dáta a ríomh roimh ré san fhocheist agus an athróg ullmhaithe cheana féin a chur ar aghaidh chuig an scagaire. Agus thug an leid seo toradh iontach dúinn, d'éirigh an cheist beagnach 6 huaire níos tapúla!

Arís, tá sé tábhachtach a bheith cúramach anseo: ní mór an cineál sonraí sa subquery a bheith mar an gcéanna leis an réimse ag a bhfuil muid ag scagadh, nó beidh an pleanálaí a chinneadh go ós rud é go bhfuil na cineálacha éagsúla agus is gá a fháil ar an gcéad dul síos go léir. sonraí agus é a scagadh go háitiúil.

Cuirimis an scagaire de réir dáta ar ais chuig a bhunluach.

Freddy vs. jsonb

Go ginearálta, chuir réimsí agus dátaí Boole dlús leordhóthanach lenár bhfiosrúchán cheana féin, ach bhí cineál sonraí amháin eile ann. Níl deireadh leis an gcath le scagadh a dhéanamh, le bheith macánta, cé go bhfuil éachtaí anseo freisin. Mar sin, seo conas a d'éirigh linn an scagaire a chur ar aghaidh jsonb réimse chuig freastalaí iargúlta.

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table 
WHERE is_active is True
AND created_dt BETWEEN CURRENT_DATE - INTERVAL '7 month' 
AND CURRENT_DATE - INTERVAL '6 month'
AND meta @> '{"source":"test"}'::jsonb;

Aggregate  (cost=245463.60..245463.61 rows=1 width=8) (actual time=6727.589..6727.590 rows=1 loops=1)
  Output: count(1)
  ->  Foreign Scan on fdw_schema."table"  (cost=1100.00..245459.90 rows=1478 width=0) (actual time=16.213..6634.794 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Filter: (("table".is_active IS TRUE) AND ("table".created_dt >= (('now'::cstring)::date - '7 mons'::interval)) AND ("table".created_dt <= ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)))
        Rows Removed by Filter: 619961
        Remote SQL: SELECT created_dt, is_active FROM fdw_schema.table WHERE ((meta @> '{"source": "test"}'::jsonb))
Planning time: 0.747 ms
Execution time: 6727.815 ms

In ionad oibreoirí a scagadh, ní mór duit láithreacht oibreora amháin a úsáid. jsonb i difriúil. 7 soicind in ionad an 29 bunaidh. Go dtí seo, is é seo an t-aon rogha rathúil chun scagairí a tharchur thar jsonb chuig cianfhreastalaí, ach anseo tá sé tábhachtach teorainn amháin a chur san áireamh: úsáidimid leagan 9.6 den bhunachar sonraí, ach faoi dheireadh mhí Aibreáin tá sé beartaithe againn na tástálacha deiridh a chríochnú agus bogadh go dtí leagan 12. Chomh luath agus a thabharfaimid cothrom le dáta, scríobhfaimid conas a chuaigh sé i bhfeidhm, toisc go bhfuil go leor athruithe ann a bhfuil go leor dóchais ann: json_path, iompar CTE nua, brúigh síos (atá ann cheana féin ó leagan 10). Ba mhaith liom triail a bhaint as go luath.

Críochnaigh dó

Sheiceáil muid conas a théann gach athrú i bhfeidhm ar an luas fiosrúcháin ina n-aonar. Féachaimis anois cad a tharlaíonn nuair a scríobhtar na trí scagairí i gceart.

explain analyze verbose
SELECT count(1)
FROM fdw_schema.table 
WHERE is_active = True
AND created_dt >= (SELECT CURRENT_DATE::timestamptz - INTERVAL '7 month') 
AND created_dt <(SELECT CURRENT_DATE::timestamptz - INTERVAL '6 month')
AND meta @> '{"source":"test"}'::jsonb;

Aggregate  (cost=322041.51..322041.52 rows=1 width=8) (actual time=2278.867..2278.867 rows=1 loops=1)
  Output: count(1)
  InitPlan 1 (returns $0)
    ->  Result  (cost=0.00..0.02 rows=1 width=8) (actual time=0.010..0.010 rows=1 loops=1)
          Output: ((('now'::cstring)::date)::timestamp with time zone - '7 mons'::interval)
  InitPlan 2 (returns $1)
    ->  Result  (cost=0.00..0.02 rows=1 width=8) (actual time=0.003..0.003 rows=1 loops=1)
          Output: ((('now'::cstring)::date)::timestamp with time zone - '6 mons'::interval)
  ->  Foreign Scan on fdw_schema."table"  (cost=100.02..322041.41 rows=25 width=0) (actual time=8.597..2153.809 rows=1360025 loops=1)
        Output: "table".id, "table".is_active, "table".meta, "table".created_dt
        Remote SQL: SELECT NULL FROM fdw_schema.table WHERE (is_active) AND ((created_dt >= $1::timestamp with time zone)) AND ((created_dt < $2::timestamp with time zone)) AND ((meta @> '{"source": "test"}'::jsonb))
Planning time: 0.820 ms
Execution time: 2279.087 ms

Sea, tá cuma níos casta ar an gceist, is praghas éigean é, ach tá an luas forghníomhaithe 2 soicind, atá níos mó ná 10 n-uaire níos tapúla! Agus táimid ag caint faoi cheist shimplí ar thacar sách beag sonraí. Ar iarratais iarbhír, fuaireamar méadú suas le cúpla céad uair.

Mar achoimre: má tá PostgreSQL in úsáid agat le FDW, seiceáil i gcónaí an seoltar na scagairí go léir chuig an gcianfhreastalaí agus beidh tú sásta... Ar a laghad go dtí go bhfaigheann tú naisc idir táblaí ó fhreastalaithe éagsúla. Ach sin scéal d’alt eile.

Go raibh maith agat as do aird! Ba bhreá liom ceisteanna, tuairimí, agus scéalta a chloisteáil faoi do thaithí sna tuairimí.

Foinse: will.com

Add a comment