DBA: si karti leh u habayso isku xidhka iyo soo dejinta

Si loo habeeyo xogta adag ee xogta waaweyn (kala duwan Nidaamyada ETL: soo dejinta, beddelidda iyo isku-xidhka isha dibadda) inta badan waxaa jira baahi si ku meel gaadh ah "xusuus" oo isla markiiba si dhakhso leh u socodsii wax mug leh.

Hawsha caadiga ah ee noocaan ah badiyaa waxay u egtahay sidan: "Halkan halkan waaxda xisaabaadka laga soo dejiyo bangiga macmiilka Lacagihii ugu dambeeyay ee la helo, waxaad u baahan tahay inaad si dhakhso leh ugu dhejiso websaydhka oo aad ku xidho akoonnadaada"

Laakiin marka mugga "wax" uu bilaabo inuu cabbiro boqollaal megabyte, adeegguna waa inuu sii wadaa inuu la shaqeeyo xogta 24x7, waxyeellooyin badan ayaa soo baxa kuwaas oo burburin doona noloshaada.
DBA: si karti leh u habayso isku xidhka iyo soo dejinta
Si aad wax uga qabato iyaga PostgreSQL (oo aan ku jirin oo keliya), waxaad isticmaali kartaa qaar ka mid ah hagaajinta kuwaas oo kuu oggolaanaya inaad wax walba si dhakhso ah u socodsiiso iyo isticmaalka kheyraadka yar.

1. Halkee laga rari karaa?

Marka hore, aan go'aansanno meesha aan ku dhejin karno xogta aan rabno inaan "ka shaqeyno."

1.1. Miisaska ku meel gaadhka ah (Miisaska ku meel gaadhka ah)

Mabda 'ahaan, miisaska ku meel gaarka ah ee PostgreSQL waxay la mid yihiin kuwa kale. Sidaa darteed, khuraafaadka sida "Wax kasta oo halkaas ku jira waxa lagu kaydiyaa xusuusta oo keliya, wayna dhammaan karaan". Laakiin sidoo kale waxaa jira dhowr farqi oo muhiim ah.

"Spacename" adiga kuu gaar ah oo ku xiran mid kasta oo ku xiran xogta

Haddii laba xiriir isku dayaan in ay isku mar ku xidhmaan CREATE TABLE x, markaas qof ayaa hubaal heli doona qalad aan gaar ahayn walxaha database.

Laakiin haddii labaduba ay isku dayaan inay fuliyaan CREATE TEMPORARY TABLE x, ka dibna labaduba waxay u samayn doonaan si caadi ah, qof walbana wuu heli doonaa nuqulkaaga miisaska. Oo ma jiri doonaan wax iyaga ka dhexeeya.

"Is-burburin" marka la jarayo

Marka xiriirka la xiro, dhammaan miisaska ku meel gaarka ah si toos ah ayaa loo tirtiraa, sidaas darteed gacanta DROP TABLE x ma jirto wax macno ah oo aan ahayn...

Haddii aad ka shaqaynayso pgbouncer qaabka wax kala iibsiga, ka dibna database-ku wuxuu sii wadaa inuu rumaysto in xidhiidhkani uu wali firfircoon yahay, oo uu ku dhex jiro shaxdan ku meel gaadhka ah.

Sidaa darteed, isku dayga in la abuuro mar kale, laga bilaabo xiriir ka duwan pgbouncer, waxay keeni doontaa qalad. Laakiin tan waxaa lagu hareer marin karaa iyadoo la isticmaalayo CREATE TEMPORARY TABLE IF NOT EXISTS x.

Run ahaantii, way fiicantahay inaadan tan samayn, sababtoo ah markaa waxaad "si lama filaan ah" halkaas uga heli kartaa xogta ka hartay "milkiilihii hore". Taa beddelkeeda, waxa aad u fiican in la akhriyo buug-gacmeedka oo la arko in marka la abuurayo miis ay suurtogal tahay in lagu daro ON COMMIT DROP - taas oo ah, marka wax kala iibsiga la dhammeeyo, miiska si toos ah ayaa loo tirtiri doonaa.

Dib-u-noqosho la'aan

Sababtoo ah waxay ka tirsan yihiin oo keliya xiriir gaar ah, miisaska ku meel gaarka ah lama soo koobin. Laakin tani waxay meesha ka saaraysaa baahida loo qabo duubista xogta laba jeer meel tuunsan + WAL, markaa GELI/CUSBOONAYSIINTA/TIIR geliya aad bay u dhakhso badan tahay.

Laakiin maadaama miis ku meel gaadh ahi uu weli yahay miis “ku dhawaad ​​caadi ah”, laguma samayn karo nuqul midna. Ugu yaraan hadda, in kasta oo balastar u dhigma uu wareegayey muddo dheer.

1.2. MIISKA AAN LOOGGELIN

Laakiin maxaad samayn lahayd, tusaale ahaan, haddii aad haysato nooc ka mid ah habka ETL ee dhibka leh oo aan lagu fulin karin hal macaamil, laakiin waxaad weli haysataa. pgbouncer qaabka wax kala iibsiga? ..

Mise socodka xogta ayaa aad u weyn Hal xidhidh oo keliya kuma filna Laga soo bilaabo kaydka xogta (akhri, hal hab oo CPU kasta)?

Ama hawlgalo qaar ayaa socda si aan sinnayn xiriiro kala duwan?..

Waxaa jira hal ikhtiyaar oo kaliya halkan - si ku meel gaar ah u samee miis aan ku meel gaar ahayn. Pun, haa. Taasi waa:

  • abuuray miisaska "anigayga" oo leh magacyo aan kala sooc lahayn si aan cidna ula qabsan
  • Warbixiinta: waxay ka buuxiyeen xog laga helay ilo dibadeed
  • Bedelka: rogrogay, laga buuxiyey goobaha muhiimka ah ee isku xidhka
  • load: ku shubay xog diyaarsan miisaska bartilmaameedka ah
  • miisaska "my" la tirtiray

Oo hadda - duqsi ku jira cadarka. Dhab ahaan, Dhammaan wax lagu qoro PostgreSQL waxay dhacaan laba jeer - marka hore WAL, ka dibna gal miiska / meydadka index. Waxaas oo dhan waxaa loo sameeyaa si loo taageero ACID iyo in la saxo aragtida xogta u dhaxaysa COMMIT'nutty iyo ROLLBACKWax kala iibsi aan jirin.

Laakiin uma baahnin tan! Waxaan leenahay nidaamka oo dhan Ama waxay ahayd mid si buuxda u guulaysatay ama ma aysan ahayn.. Dhib ma leh inta macaamil dhexdhexaad ah oo dhex dhexaad ah ayaa jiri doonta - ma xiisayneyno "inuu ka sii wado geeddi-socodka bartamaha," gaar ahaan marka aysan caddayn halka ay ahayd.

Si tan loo sameeyo, soosaarayaasha PostgreSQL, oo ​​ku soo laabtay nooca 9.1, waxay soo bandhigeen wax sida Miisaska UNLOGGED:

Iyada oo tilmaantan, miiska loo sameeyay sidii aan la qorin. Xogta lagu qoray shaxanka aan la qorin ma soo marto qoraalka hore u qoran (eeg cutubka 29), taasoo keenaysa shaxanka noocaas ah si ka dhakhso badan sidii caadiga ahayd u ​​shaqeyso. Si kastaba ha ahaatee, ma aha kuwo ka badbaado guuldarada; Haddii ay dhacdo in server-ku xumaado ama degdega loo xiro, miis aan la qorin si toos ah loo gooyay. Intaa waxaa dheer, waxa ku jira miiska aan la qorin aan la soo celin si ay u adeegaan. Tusiyaal kasta oo lagu sameeyay miis aan la qorin ayaa si toos ah u noqda kuwa aan diiwaanka gelin

Si kooban, aad bay u dhakhso badan doontaa, laakiin haddii server-ka xogta "soo dhaco", waxay noqon doontaa wax aan fiicnayn. Laakiin intee jeer ayay tani dhacdaa, oo habkaaga ETL ma yaqaanaa sida tan saxda ah loo saxo "laga bilaabo bartamaha" ka dib "dib u soo nooleynta" xogta?

Haddaysan ahayn, oo kiiska kore uu la mid yahay kaaga, isticmaal UNLOGGEDlaakiin marna ha u suurtogelin sifadan miisaska dhabta ah, xogta laga soo xigtay adiga kugu qaali ah.

1.3. XUKUNKA LAGU TIRIRTAY SAFARKA | DEJIYO

Dhismahani wuxuu kuu ogolaanayaa inaad qeexdo dabeecadda tooska ah marka macaamil ganacsi la dhammeeyo marka la abuurayo miis.

on ON COMMIT DROP Horaan u qoray kor, waxay dhalisaa DROP TABLElaakiin leh ON COMMIT DELETE ROWS xaaladdu aad ayay u xiiso badan tahay - halkan ayaa laga soo saaray TRUNCATE TABLE.

Maaddaama dhammaan kaabayaasha kaydinta sharraxa-badan ee miiska ku-meel-gaarka ah ay la mid yihiin kan miiska caadiga ah, ka dibna Abuuritaanka joogtada ah iyo tirtirida miisaska ku meel gaadhka ah waxay keenaysaa "barar" ba'an ee miisaska nidaamka pg_class, pg_sifo, pg_attrdef, pg_ku-tiirsanaan,…

Hadda qiyaas in aad leedahay shaqaale xiriir toos ah la leh database-ka, kaas oo furaya macaamil cusub ilbiriqsi kasta, abuuraa, buuxiya, farsameeyaa oo tirtiraa miis ku meel gaar ah ... Waxaa jiri doona xad-dhaaf ah qashinka lagu ururiyo miisaska nidaamka, iyo tani waxay keenaysaa bareega dheeri ah qalliin kasta.

Guud ahaan, tan ha samayn! Xaaladdan oo kale aad bay waxtar u leedahay CREATE TEMPORARY TABLE x ... ON COMMIT DELETE ROWS ka saar wareegga wax kala iibsiga - ka dibna bilawga macaamil kasta oo cusub jadwalku waa horeba jiri doona (keydiso wac CREATE), laakiin madhnaan doono, mahadsanid TRUNCATE (waxaan sidoo kale keydinay wicitaankeeda) markii la dhameystirayo macaamilkii hore.

1.4. sida... ay ku jiraan...

Waxaan bilowgii hore ku sheegay in mid ka mid ah kiisaska caadiga ah ee loo isticmaalo miisaska ku meel gaadhka ah ay yihiin noocyo kala duwan oo soo dejineed - iyo horumariyayaashu si daal ah ayuu koobi ugu dhejiyaa liiska meelaha miiska la beegsanayo cadeynta ku meel gaarkiisa

Laakin caajisnimadu waa mishiinka horumarka! Taasi waa sababta samee miis cusub "ku salaysan muunad" aad ayey uga fududaan kartaa:

CREATE TEMPORARY TABLE import_table(
  LIKE target_table
);

Maadaama aad markaas soo saari karto xog badan miiskan, ka raadinta waligeed dhakhso uma noqon doonto. Laakiin waxaa jira xal dhaqameed tan - indexes! Iyo, haa, miiska ku meel gaadhka ahi waxa kale oo uu yeelan karaa tusmooyin.

Maadaama, inta badan, tusmooyinka loo baahan yahay ay la socdaan tusmooyinka miiska bartilmaameedka, waxaad si fudud u qori kartaa LIKE target_table INCLUDING INDEXES.

Haddii aad sidoo kale u baahan tahay DEFAULT-qiimaha (tusaale ahaan, si aad u buuxiso qiyamka aasaasiga ah), waxaad isticmaali kartaa LIKE target_table INCLUDING DEFAULTS. Ama si fudud - LIKE target_table INCLUDING ALL - koobiyada khaladka, tusmooyinka, caqabadaha,...

Laakiin halkan waxaad u baahan tahay inaad fahamto haddii aad abuurtay miiska soo dejinta isla markaaba leh tusmooyin, ka dibna xogtu waxay qaadan doontaa waqti dheer in la shuboMarka loo eego haddii aad marka hore buuxiso wax walba, oo kaliya ka dibna duub tusmooyinka - fiiri sida ay tan u sameyso tusaale ahaan pg_daad.

Guud ahaan RTFM!

2. Sidee loo qoraa?

Aan idhaahdo - isticmaal COPY-qulqulka halkii "xirmo" INSERT, dardargelinta mararka qaarkood. Waxaad xitaa si toos ah uga soo qaadan kartaa fayl horay loo soo saaray.

3. Sida loo habeeyo?

Haddaba, aan hordhacayada u eegno sidatan:

  • waxaad haysataa miis ay ku jiraan xogta macmiilka oo ku kaydsan xogtaada 1M diiwaan
  • maalin kasta macmiilku wuxuu kuu soo diri mid cusub buuxa "sawir"
  • waayo-aragnimada waad garanaysaa mar mar wax ka badan 10k diiwaanka lama bedelin

Tusaalaha caadiga ah ee xaaladdan oo kale waa saldhigga KLADR - waxaa jira ciwaanno badan oo wadar ahaan ah, laakiin toddobaad kasta oo la soo geliyo waxaa jira isbeddello aad u yar (magacaabidda degsiimooyinka, isku dhafka waddooyinka, muuqaalka guryaha cusub) xitaa marka la eego heer qaran.

3.1. Algorithm isku-dubarid buuxda

Si fudud, aynu nidhaahno xitaa uma baahnid inaad dib u habeyn ku sameyso xogta - kaliya keen miiska foomka la rabo, kaas oo ah:

  • saaro wax kasta oo aan hadda jirin
  • cusboonaysiin wax kasta oo hore u jiray oo u baahan in la cusbooneysiiyo
  • geli wax kasta oo aan weli dhicin

Maxay tahay sababta hawlgallada sidaan u kala horreeyaan? Sababtoo ah tani waa sida cabbirka miiska uu u kori doono si yar (xasuuso MVCC!).

KA TIRIR Dst

Maya, dabcan waxaad ku heli kartaa laba qalliin oo keliya:

  • saaro (DELETE) wax walba guud ahaan
  • geli oo dhan laga bilaabo sawirka cusub

Laakin isla mar ahaantaana, waxaa mahad leh MVCC. Cabbirka miiska ayaa si sax ah u kordhin doona laba jeer! Helitaanka sawirada +1M ee diiwaanada miiska ku jira sababtuna tahay 10K cusboonaysiintu waa shaqo dhimis...

GUURKA Dst

Horumariye khibrad leh ayaa og in dhammaan kiniinka lagu nadiifin karo si raqiis ah:

  • nadiif ah (TRUNCATE) miiska oo dhan
  • geli oo dhan laga bilaabo sawirka cusub

Habka waa mid waxtar leh, mararka qaarkood aad loo dabaqi karo, laakiin waxaa jirta dhibaato... Waxaan ku dari doonaa diiwaanka 1M muddo dheer, sidaas darteed ma awoodno inaan ka tago miiska madhan wakhtigan oo dhan (sida ay dhici doonto iyada oo aan ku duubin hal macaamil ganacsi).

Taas oo macnaheedu yahay:

  • waanu bilaabaynaa macaamil ganacsi oo dheer
  • TRUNCATE soo rogi Helitaanka Gaarka ah- xannibid
  • Waxaan sameynaa gelinta muddo dheer, iyo qof kasta oo kale waqtigan xataa ma awoodo SELECT

Wax si fiican uma socdo...

Miiska Beddelka… Magacaabid… / Miisaanka Keen…

Beddelku waa in wax walba lagu buuxiyo miis cusub oo gaar ah, ka dibna si fudud loogu beddelo halkii kii hore. Dhowr waxyaalood oo yaryar oo xun:

  • weli sidoo kale Helitaanka Gaarka ah, inkastoo waqti aad u yar
  • Dhammaan qorshooyinka/tirakoobka miiskaan dib ayaa loo dajiyay, u baahan in la sameeyo ANALYZE
  • dhammaan furayaashii shisheeye way jabeen (FK) miiska

Waxaa jiray balastar WIP ah oo ka yimid Simon Riggs oo soo jeediyay samaynta ALTER- qalliin lagu beddelayo jidhka miiska ee heerka faylka, iyada oo aan la taaban tirakoobyada iyo FK, laakiin aan soo ururin kooram.

Tirtir, Cusbooneysii, Geli

Markaa, waxaan dejineynaa ikhtiyaarka xannibaad la'aanta ee saddex hawlgal. Ku dhawaad ​​saddex... Sidee tan ugu waxtarka badan loo sameeyaa?

-- все делаем в рамках транзакции, чтобы никто не видел "промежуточных" состояний
BEGIN;

-- создаем временную таблицу с импортируемыми данными
CREATE TEMPORARY TABLE tmp(
  LIKE dst INCLUDING INDEXES -- по образу и подобию, вместе с индексами
) ON COMMIT DROP; -- за рамками транзакции она нам не нужна

-- быстро-быстро вливаем новый образ через COPY
COPY tmp FROM STDIN;
-- ...
-- .

-- удаляем отсутствующие
DELETE FROM
  dst D
USING
  dst X
LEFT JOIN
  tmp Y
    USING(pk1, pk2) -- поля первичного ключа
WHERE
  (D.pk1, D.pk2) = (X.pk1, X.pk2) AND
  Y IS NOT DISTINCT FROM NULL; -- "антиджойн"

-- обновляем оставшиеся
UPDATE
  dst D
SET
  (f1, f2, f3) = (T.f1, T.f2, T.f3)
FROM
  tmp T
WHERE
  (D.pk1, D.pk2) = (T.pk1, T.pk2) AND
  (D.f1, D.f2, D.f3) IS DISTINCT FROM (T.f1, T.f2, T.f3); -- незачем обновлять совпадающие

-- вставляем отсутствующие
INSERT INTO
  dst
SELECT
  T.*
FROM
  tmp T
LEFT JOIN
  dst D
    USING(pk1, pk2)
WHERE
  D IS NOT DISTINCT FROM NULL;

COMMIT;

3.2. Soo dejinta ka dib habaynta

Isla KLADR-ka, dhammaan diiwaanada la beddelay waa in lagu sii wadaa hab-socod ka dib - caadiyan, ereyada furaha la iftiimiyay, oo lagu dhimo qaab-dhismeedka loo baahan yahay. Laakiin sidee ku garanaysaa - maxaa iska badalayadiga oo aan dhibin koodka wada shaqaynta, sida ugu habboon adiga oo aan taaban haba yaraatee?

Haddii kaliya habkaagu uu leeyahay gelitaanka qoritaanka wakhtiga isku xidhka, markaa waxaad isticmaali kartaa kiciye kaas oo ururin doona dhammaan isbeddelada anaga:

-- целевые таблицы
CREATE TABLE kladr(...);
CREATE TABLE kladr_house(...);

-- таблицы с историей изменений
CREATE TABLE kladr$log(
  ro kladr, -- тут лежат целые образы записей старой/новой
  rn kladr
);

CREATE TABLE kladr_house$log(
  ro kladr_house,
  rn kladr_house
);

-- общая функция логирования изменений
CREATE OR REPLACE FUNCTION diff$log() RETURNS trigger AS $$
DECLARE
  dst varchar = TG_TABLE_NAME || '$log';
  stmt text = '';
BEGIN
  -- проверяем необходимость логгирования при обновлении записи
  IF TG_OP = 'UPDATE' THEN
    IF NEW IS NOT DISTINCT FROM OLD THEN
      RETURN NEW;
    END IF;
  END IF;
  -- создаем запись лога
  stmt = 'INSERT INTO ' || dst::text || '(ro,rn)VALUES(';
  CASE TG_OP
    WHEN 'INSERT' THEN
      EXECUTE stmt || 'NULL,$1)' USING NEW;
    WHEN 'UPDATE' THEN
      EXECUTE stmt || '$1,$2)' USING OLD, NEW;
    WHEN 'DELETE' THEN
      EXECUTE stmt || '$1,NULL)' USING OLD;
  END CASE;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Hadda waxaan codsan karnaa kiciyeyaasha ka hor inta aan la bilaabin isku-dubarid (ama awood u siin iyaga oo isticmaalaya ALTER TABLE ... ENABLE TRIGGER ...):

CREATE TRIGGER log
  AFTER INSERT OR UPDATE OR DELETE
  ON kladr
    FOR EACH ROW
      EXECUTE PROCEDURE diff$log();

CREATE TRIGGER log
  AFTER INSERT OR UPDATE OR DELETE
  ON kladr_house
    FOR EACH ROW
      EXECUTE PROCEDURE diff$log();

Kadibna waxaan si degan uga soo saarnaa dhammaan isbeddellada aan u baahanahay miisaska log-yada waxaanan ku socodsiineynaa maamulayaal dheeraad ah.

3.3. Soo Dejinta Xidhmooyin isku xidhan

Xagga sare waxaynu tixgalinay kiisas marka qaababka xogta meesha iyo meesha loo socdo ay isku mid yihiin. Laakiin ka waran haddii soo dejinta nidaamka dibadda uu leeyahay qaab ka duwan qaab dhismeedka kaydinta ee database our?

Aan tusaale u soo qaadanno kaydinta macaamiisha iyo xisaabaadkooda, ikhtiyaarka caadiga ah ee "mid-ka-mid ah":

CREATE TABLE client(
  client_id
    serial
      PRIMARY KEY
, inn
    varchar
      UNIQUE
, name
    varchar
);

CREATE TABLE invoice(
  invoice_id
    serial
      PRIMARY KEY
, client_id
    integer
      REFERENCES client(client_id)
, number
    varchar
, dt
    date
, sum
    numeric(32,2)
);

Laakin soo dejintu il dibadeed waxay noogu timaadaa qaab ah "dhammaan hal":

CREATE TEMPORARY TABLE invoice_import(
  client_inn
    varchar
, client_name
    varchar
, invoice_number
    varchar
, invoice_dt
    date
, invoice_sum
    numeric(32,2)
);

Sida iska cad, xogta macaamiisha waxaa lagu koobi karaa noocaan, diiwaanka ugu weynna waa "account":

0123456789;Вася;A-01;2020-03-16;1000.00
9876543210;Петя;A-02;2020-03-16;666.00
0123456789;Вася;B-03;2020-03-16;9999.00

Qaabka, waxaanu si fudud gelin doonaa xogtayada tijaabada, laakiin xusuusnow - COPY ka hufan!

INSERT INTO invoice_import
VALUES
  ('0123456789', 'Вася', 'A-01', '2020-03-16', 1000.00)
, ('9876543210', 'Петя', 'A-02', '2020-03-16', 666.00)
, ('0123456789', 'Вася', 'B-03', '2020-03-16', 9999.00);

Marka hore, aan muujino "goynta" kuwaas oo "xaqiiqdayada" ay tixraacayaan. Xaaladeena, qaansheegyadu waxay tixraacaan macaamiisha:

CREATE TEMPORARY TABLE client_import AS
SELECT DISTINCT ON(client_inn)
-- можно просто SELECT DISTINCT, если данные заведомо непротиворечивы
  client_inn inn
, client_name "name"
FROM
  invoice_import;

Si aan si sax ah ugu xidhno xisaabaadka iyo aqoonsiga macmiilka, waxaanu marka hore u baahanahay inaanu ogaano ama aanu soo saarno aqoonsiyadan. Aynu ku darno garoonnada hoostooda:

ALTER TABLE invoice_import ADD COLUMN client_id integer;
ALTER TABLE client_import ADD COLUMN client_id integer;

Aynu isticmaalno habka isku-dubaridka miiska kor lagu sifeeyay oo leh wax-ka-beddel yar - ma cusboonaysiin doono ama tirtiri mayno wax ku jira miiska bartilmaameedka, sababtoo ah waxaan soo dejineynaa macaamiisha "ku- lifaaq-kaliya":

-- проставляем в таблице импорта ID уже существующих записей
UPDATE
  client_import T
SET
  client_id = D.client_id
FROM
  client D
WHERE
  T.inn = D.inn; -- unique key

-- вставляем отсутствовавшие записи и проставляем их ID
WITH ins AS (
  INSERT INTO client(
    inn
  , name
  )
  SELECT
    inn
  , name
  FROM
    client_import
  WHERE
    client_id IS NULL -- если ID не проставился
  RETURNING *
)
UPDATE
  client_import T
SET
  client_id = D.client_id
FROM
  ins D
WHERE
  T.inn = D.inn; -- unique key

-- проставляем ID клиентов у записей счетов
UPDATE
  invoice_import T
SET
  client_id = D.client_id
FROM
  client_import D
WHERE
  T.client_inn = D.inn; -- прикладной ключ

Dhab ahaantii, wax walba waa in invoice_import Hadda waxaan haynaa goobta xiriirka oo la buuxiyay client_id, kaas oo aanu gelin doono qaansheegta.

Source: www.habr.com

Add a comment