EessÔna vÔi kuidas tekkis ideoloogia sektsioneerimise kohta
Loo algus siin: P pĂ€rast seda, kui peaaegu kĂ”ik ressursid pĂ€ringu optimeerimiseks olid toona vĂ€ljapeetud, tuli kĂŒsimus â mis edasi? Nii tekkis idee sektsioneerimisest.

LĂŒhiĂŒlevaade:
Just 'toona', kuna . AitÀh ja Habrule!
Nii, kuidas veel vÔiks klienti Ônnelikuks teha, ja samal ajal oma oskusi parandada?
Kui kÔik vÔimalikult lihtsaks teha, siis on kaks peamist teed, kuidas midagi radikaalselt parandada andmebaasi jÔudluses:
1) Ekstensiivne tee â suurendame ressursse, muudame konfiguratsiooni;
2) Intensiivne tee â pĂ€ringute optimeerimine
Kuna, kordustan, toona ei olnud selge, mida veel pĂ€ringus muuta kiirusel, valiti tee â tabelite disaini muutmine.
Nii â tĂ”useb peamine kĂŒsimus â mida ja kuidas me muudame?
Algtingimused
Esiteks, on olemas selline ERD (nÀidatud tinglikult-lihtsustatud):

PÔhiomadused:
- suhted "palju paljude" vahel
- tabelil on juba potentsiaalne sektsioneerimise vÔti
Algne pÀring:
SELECT
p."PARAMETER_ID" as parameter_id,
pc."PC_NAME" AS pc_name,
pc."CUSTOMER_PARTNUMBER" AS customer_partnumber,
w."LASERMARK" AS lasermark,
w."LOTID" AS lotid,
w."REPORTED_VALUE" AS reported_value,
w."LOWER_SPEC_LIMIT" AS lower_spec_limit,
w."UPPER_SPEC_LIMIT" AS upper_spec_limit,
p."TYPE_CALCUL" AS type_calcul,
s."SHIPMENT_NAME" AS shipment_name,
s."SHIPMENT_DATE" AS shipment_date,
extract(year from s."SHIPMENT_DATE") AS year,
extract(month from s."SHIPMENT_DATE") as month,
s."REPORT_NAME" AS report_name,
p."SPARAM_NAME" AS SPARAM_name,
p."CUSTOMERPARAM_NAME" AS customerparam_name
FROM data w INNER JOIN shipment s ON s."SHIPMENT_ID" = w."SHIPMENT_ID"
INNER JOIN parameters p ON p."PARAMETER_ID" = w."PARAMETER_ID"
INNER JOIN shipment_pc sp ON s."SHIPMENT_ID" = sp."SHIPMENT_ID"
INNER JOIN pc pc ON pc."PC_ID" = sp."PC_ID"
INNER JOIN ( SELECT w2."LASERMARK" , MAX(s2."SHIPMENT_DATE") AS "SHIPMENT_DATE"
FROM shipment s2 INNER JOIN data w2 ON s2."SHIPMENT_ID" = w2."SHIPMENT_ID"
GROUP BY w2."LASERMARK"
) md ON md."SHIPMENT_DATE" = s."SHIPMENT_DATE" AND md."LASERMARK" = w."LASERMARK"
WHERE
s."SHIPMENT_DATE" >= '2018-07-01' AND s."SHIPMENT_DATE" <= '2018-09-30' ;
Testandme tulemuste tÀitmine testandmebaasis:
Maksumus : 502 997.55
TĂ€ideviimise aeg: 505 sekundit.
Mida me nÀeme? Tavaline pÀring ajavahemiku jÀrgi.
Teeme lihtsa loogilise oletuse: kui on valik ajalisest lĂ”igust, kas see aitab meid? Ăige â sektsioneerimine.
Mida sektsioneerida?
Esmapilgul tundub valik ilmne â deklaratiivne sektsioneerimine tabeli âshipmentâ jĂ€rgi vĂ”tme âSHIPMENT_DATEâ jĂ€rgi (liialt ette ruttamata â lĂ”puks tuli tootmises vĂ€lja veidi teistmoodi).
Kuidas sektsioneerida?
See kĂŒsimus ei ole samuti liiga keeruline. Ănneks on PostgreSQL 10-s nĂŒĂŒd inimlik sektsioneerimise mehhanism.
Nii:
- Salvestame algse tabeli dump'i â pg_dump source_table
- Kustutame algse tabeli â drop table source_table
- Loome vanemtabeli, sektsioneerides selle vahemiku jĂ€rgi â create table source_table
- Loome sektsioonid â create table source_table, create index
- Importime dump'i, mis loodi 1. sammus â pg_restore
Sektsioneerimise skriptid
Lihtsuse ja mugavuse huvides on 2, 3, 4. sammud koondatud ĂŒhte skripti.
Nii:
Salvestame algse tabeli dump'i
pg_dump postgres --file=\/dump\/shipment.dmp --format=c --table=shipment --verbose > \/dump\/shipment.log 2>&1Kustutame algse tabeli + Loome vanemtabeli, sektsioneerides selle vahemiku jÀrgi + Loome sektsioonid
--create_partition_shipment.sql
do language plpgsql $$
declare
rec_shipment_date RECORD ;
partition_name varchar;
index_name varchar;
current_year varchar ;
current_month varchar ;
begin_year varchar ;
begin_month varchar ;
next_year varchar ;
next_month varchar ;
first_flag boolean ;
i integer ;
begin
RAISE NOTICE 'Loo TEMP TABLE SHIPMENT_DATE';
CREATE TEMP TABLE tmp_shipment_date as select distinct "SHIPMENT_DATE" from shipment order by "SHIPMENT_DATE" ;
RAISE NOTICE 'KUSTUTA TABLE shipment';
drop table shipment cascade ;
CREATE TABLE public.shipment
(
"SHIPMENT_ID" integer NOT NULL DEFAULT nextval('shipment_shipment_id_seq'::regclass),
"SHIPMENT_NAME" character varying(30) COLLATE pg_catalog."default",
"SHIPMENT_DATE" timestamp without time zone,
"REPORT_NAME" character varying(40) COLLATE pg_catalog."default"
)
PARTITION BY RANGE ("SHIPMENT_DATE")
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
RAISE NOTICE 'LOO PARTITSIOONID TABLE FOR shipment';
current_year:='0';
current_month:='0';
begin_year := '0' ;
begin_month := '0' ;
next_year := '0' ;
next_month := '0' ;
FOR rec_shipment_date IN SELECT * FROM tmp_shipment_date LOOP
RAISE NOTICE 'SHIPMENT_DATE=%',rec_shipment_date."SHIPMENT_DATE";
current_year := date_part('year' ,rec_shipment_date."SHIPMENT_DATE");
current_month := date_part('month' ,rec_shipment_date."SHIPMENT_DATE") ;
IF to_number(current_month,'99') = to_date( begin_year||'.'||begin_month, 'YYYY.MM') AND
to_date( current_year||'.'||current_month, 'YYYY.MM') < to_date( next_year||'.'||next_month, 'YYYY.MM') AND
NOT first_flag
THEN
CONTINUE ;
ELSE
--UUED piirded ainult teisel ja hiljem
begin_year := current_year ;
begin_month := current_month ;
IF current_month = '12' THEN
next_year := date_part('year' ,rec_shipment_date."SHIPMENT_DATE" + interval '1 year') ;
ELSE
next_year := current_year ;
END IF;
next_month := date_part('month' ,rec_shipment_date."SHIPMENT_DATE" + interval '1 month') ;
END IF;
partition_name := 'shipment_shipment_date_'||begin_year||'-'||begin_month||'-01-'|| next_year||'-'||next_month||'-01' ;
EXECUTE format('CREATE TABLE ' || quote_ident(partition_name) || ' PARTITION OF shipment FOR VALUES FROM ( %L ) TO ( %L ) ' , current_year||'-'||current_month||'-01' , next_year||'-'||next_month||'-01' ) ;
index_name := partition_name||'_shipment_id_idx';
RAISE NOTICE 'INDEX NAME =%',index_name;
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("SHIPMENT_ID") TABLESPACE pg_default ' ) ;
--Kustuta esmakordne lipp
first_flag := false ;
END LOOP;
end
$$;Impordime dump
pg_restore -d postgres --data-only --format=c --table=shipment --verbose shipment.dmp > /tmp/data_dump/shipment_restore.log 2>&1Kontrollime sektsioneerimise tulemusi
Mida me siis tulemuseks saime? Plaani tÀisteksti tÀitmine on suur ja igav, seega saab piirduda lÔpnumbritega.
See oli
Kulu: 502 997.55
TĂ€itev aeg: 505 sekundit.
Muutus
Kulu: 77 872.36
TĂ€itev aeg: 79 sekundit.
Kohati hea tulemus. VĂ€henes kulu ja tĂ€itmise aeg. Seega annab sektsioneerimise kasutamine oodatud efekti ja ĂŒldiselt â ilma ĂŒllatusteta.
Tellija rÔÔmustamine
Testimise tulemused esitati tellijale tutvumiseks. Ja pĂ€rast tutvumist anti vĂ€lja mitmeti ĂŒllatav otsus: "SuurepĂ€rane, sektsioneerige tabel 'data'."
Jah, aga me uurisime hoopis teist tabelit 'shipment', tabel 'data' ei sisalda vÀlja 'SHIPMENT_DATE'.
Ei ole probleemi, lisage ja muutke. Peaasi, et tellijat rahuldab see, mis tulemuseks saab, teostuse detailid ei ole vÀga olulised.
Sektsioneerime pÔhitaabelit 'data'
KokkuvÔttes ei tekkinud mingeid erilisi raskusi. Kuigi, sektsioneerimise algoritm on muidugi natuke muutunud.
Lisame veeru 'SHIPMENT_DATA' tabelisse 'data'
psql -h host -U baasi -d kasutaja
=> ALTER TABLE data ADD COLUMN "SHIPMENT_DATE" timestamp without time zone ;TÀidame veeru 'SHIPMENT_DATA' tabelis 'data' sama nimega veeru vÀÀrtustega tabelist 'shipment'
-----------------------------
--update_data.sql
--tÀiendamine muudetud tabeli "data" jaoks vÀÀrtustega tabelist "shipment_data"
--version 1.0
do language plpgsql $$
declare
rec_shipment_data RECORD ;
shipment_date timestamp without time zone ;
row_count integer ;
total_rows integer ;
begin
select count(*) into total_rows from shipment ;
RAISE NOTICE 'Kokku %',total_rows;
row_count:= 0 ;
FOR rec_shipment_data IN SELECT * FROM shipment LOOP
update data set "SHIPMENT_DATE" = rec_shipment_data."SHIPMENT_DATE" where "SHIPMENT_ID" = rec_shipment_data."SHIPMENT_ID";
row_count:= row_count +1 ;
RAISE NOTICE 'read arvu = % , kokku %',row_count,total_rows;
END LOOP;
end
$$;Salvestame tabeli 'data' dump'i
pg_dump postgres --file=\/dump\/data.dmp --format=c --table=data --verbose > \/dump\/data.log 2>&1<\/sourceLoome sektsioneeritud tabeli 'data' uuesti
--create_partition_data.sql
--looge partitsioonid tabelile "wafer data" vahemiku veeru "shipment_data" alusel, mille kestus on ĂŒks kuu
--versioon 1.0
do language plpgsql $$
declare
rec_shipment_date RECORD ;
partition_name varchar;
index_name varchar;
current_year varchar ;
current_month varchar ;
begin_year varchar ;
begin_month varchar ;
next_year varchar ;
next_month varchar ;
first_flag boolean ;
i integer ;
begin
RAISE NOTICE 'LOO TEMPORARY TABLE SHIPMENT_DATE';
CREATE TEMP TABLE tmp_shipment_date as select distinct "SHIPMENT_DATE" from shipment order by "SHIPMENT_DATE" ;
RAISE NOTICE 'KUSTUTA TABLE data';
drop table data cascade ;
RAISE NOTICE 'LOO PARTITSIONEID TABELILE data';
CREATE TABLE public.data
(
"RUN_ID" integer,
"LASERMARK" character varying(20) COLLATE pg_catalog."default" NOT NULL,
"LOTID" character varying(80) COLLATE pg_catalog."default",
"SHIPMENT_ID" integer NOT NULL,
"PARAMETER_ID" integer NOT NULL,
"INTERNAL_VALUE" character varying(75) COLLATE pg_catalog."default",
"REPORTED_VALUE" character varying(75) COLLATE pg_catalog."default",
"LOWER_SPEC_LIMIT" numeric,
"UPPER_SPEC_LIMIT" numeric ,
"SHIPMENT_DATE" timestamp without time zone
)
PARTITION BY RANGE ("SHIPMENT_DATE")
WITH (
OIDS = FALSE
)
TABLESPACE pg_default ;
RAISE NOTICE 'LOO PARTITSIOONEID TABELILE data';
current_year:='0';
current_month:='0';
begin_year := '0' ;
begin_month := '0' ;
next_year := '0' ;
next_month := '0' ;
i := 1;
FOR rec_shipment_date IN SELECT * FROM tmp_shipment_date LOOP
RAISE NOTICE 'SHIPMENT_DATE=%',rec_shipment_date."SHIPMENT_DATE";
current_year := date_part('year' ,rec_shipment_date."SHIPMENT_DATE");
current_month := date_part('month' ,rec_shipment_date."SHIPMENT_DATE") ;
--Initsiaalne piir
IF begin_year = '0' THEN
RAISE NOTICE '***Initsiaalne piir';
first_flag := true ; --esmakordne lipp
begin_year := current_year ;
begin_month := current_month ;
IF current_month = '12' THEN
next_year := date_part('year' ,rec_shipment_date."SHIPMENT_DATE" + interval '1 year') ;
ELSE
next_year := current_year ;
END IF;
next_month := date_part('month' ,rec_shipment_date."SHIPMENT_DATE" + interval '1 month') ;
END IF;
-- RAISE NOTICE 'current_year=% , current_month=% ',current_year,current_month;
-- RAISE NOTICE 'begin_year=% , begin_month=% ',begin_year,begin_month;
-- RAISE NOTICE 'next_year=% , next_month=% ',next_year,next_month;
-- Kontrolli praegust kuupÀeva piirides mitte esmakordse jaoks
RAISE NOTICE 'Praegune kuupÀev = %',to_char( to_date( current_year||'.'||current_month, 'YYYY.MM'), 'YYYY.MM');
RAISE NOTICE 'AlguskuupÀev = %',to_char( to_date( begin_year||'.'||begin_month, 'YYYY.MM'), 'YYYY.MM');
RAISE NOTICE 'JÀrgmine kuupÀev = %',to_char( to_date( next_year||'.'||next_month, 'YYYY.MM'), 'YYYY.MM');
IF to_date( current_year||'.'||current_month, 'YYYY.MM') >= to_date( begin_year||'.'||begin_month, 'YYYY.MM') AND
to_date( current_year||'.'||current_month, 'YYYY.MM') < to_date( next_year||'.'||next_month, 'YYYY.MM') AND
NOT first_flag
THEN
RAISE NOTICE '***JATKA';
CONTINUE ;
ELSE
--Uued piirid ainult teisel ja hilisemal korral
RAISE NOTICE '***UUED PIIRID';
begin_year := current_year ;
begin_month := current_month ;
IF current_month = '12' THEN
next_year := date_part('year' ,rec_shipment_date."SHIPMENT_DATE" + interval '1 year') ;
ELSE
next_year := current_year ;
END IF;
next_month := date_part('month' ,rec_shipment_date."SHIPMENT_DATE" + interval '1 month') ;
END IF;
IF to_number(current_month,'99') < 10 THEN
current_month := '0'||current_month ;
END IF ;
IF to_number(begin_month,'99') < 10 THEN
begin_month := '0'||begin_month ;
END IF ;
IF to_number(next_month,'99') < 10 THEN
next_month := '0'||next_month ;
END IF ;
RAISE NOTICE 'current_year=% , current_month=% ',current_year,current_month;
RAISE NOTICE 'begin_year=% , begin_month=% ',begin_year,begin_month;
RAISE NOTICE 'next_year=% , next_month=% ',next_year,next_month;
partition_name := 'data_'||begin_year||begin_month||'01_'||next_year||next_month||'01' ;
RAISE NOTICE 'PARTITSIOONI NUMBER % , TABELI NIME =%',i , partition_name;
EXECUTE format('CREATE TABLE ' || quote_ident(partition_name) || ' PARTITION OF data FOR VALUES FROM ( %L ) TO ( %L ) ' , begin_year||'-'||begin_month||'-01' , next_year||'-'||next_month||'-01' ) ;
index_name := partition_name||'_shipment_id_parameter_id_idx';
RAISE NOTICE 'INDEXI NIMI =%',index_name;
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("SHIPMENT_ID", "PARAMETER_ID") TABLESPACE pg_default ' ) ;
index_name := partition_name||'_lasermark_idx';
RAISE NOTICE 'INDEXI NIMI =%',index_name;
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("LASERMARK" COLLATE pg_catalog."default") TABLESPACE pg_default ' ) ;
index_name := partition_name||'_shipment_id_idx';
RAISE NOTICE 'INDEXI NIMI =%',index_name;
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("SHIPMENT_ID") TABLESPACE pg_default ' ) ;
index_name := partition_name||'_parameter_id_idx';
RAISE NOTICE 'INDEXI NIMI =%',index_name;
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("PARAMETER_ID") TABLESPACE pg_default ' ) ;
index_name := partition_name||'_shipment_date_idx';
RAISE NOTICE 'INDEXI NIMI =%',index_name;
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("SHIPMENT_DATE") TABLESPACE pg_default ' ) ;
--Kustuta esmakordne lipp
first_flag := false ;
END LOOP;
end
$$;
Laadime faile, mis loodi sammul 3.
pg_restore -h host -user -d database --data-only --format=c --table=data --verbose data.dmp > data_restore.log 2>&1Loome eraldi sektsiooni vanade andmete jaoks
---------------------------------------------------
--create_partition_for_old_dates.sql
--loome sektsioone vanade kuupÀevade hoidmiseks
--versioon 1.0
do language plpgsql $$
declare
rec_shipment_date RECORD ;
partition_name varchar;
index_name varchar;
begin
SELECT min("SHIPMENT_DATE") AS min_date INTO rec_shipment_date from data ;
RAISE NOTICE 'Vana kuupÀev on %', rec_shipment_date.min_date ;
partition_name := 'data_old_dates' ;
RAISE NOTICE 'SEKTSIOONI NIMI ON %', partition_name;
EXECUTE format('CREATE TABLE ' || quote_ident(partition_name) || ' PARTITION OF data FOR VALUES FROM ( %L ) TO ( %L ) ', '1900-01-01',
to_char(rec_shipment_date.min_date,'YYYY')||'-'||to_char(rec_shipment_date.min_date,'MM')||'-01' ) ;
index_name := partition_name||'_shipment_id_parameter_id_idx';
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("SHIPMENT_ID", "PARAMETER_ID") TABLESPACE pg_default ' ) ;
index_name := partition_name||'_lasermark_idx';
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("LASERMARK" COLLATE pg_catalog."default") TABLESPACE pg_default ' ) ;
index_name := partition_name||'_shipment_id_idx';
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("SHIPMENT_ID") TABLESPACE pg_default ' ) ;
index_name := partition_name||'_parameter_id_idx';
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("PARAMETER_ID") TABLESPACE pg_default ' ) ;
index_name := partition_name||'_shipment_date_idx';
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("SHIPMENT_DATE") TABLESPACE pg_default ' ) ;
end
$$;LÔppjÀreldused:
See oli
Kulu: 502 997.55
TĂ€ideviimise aeg: 505 sekundit.
Muutus
Kulu: 68 533.70
TĂ€itev aeg: 69 sekundit
AuvÀÀrne, tĂ€iesti auvÀÀrne. Arvestades, et teel Ă”ppisime rohkem-vĂ”i vĂ€hem PostgreSQL 10 sektsioneerimise mehhanismi â SuurepĂ€rane tulemus.
LĂŒhiĂŒhendus
Kas saab veel paremini teha â JAH, SAAB!Selleks on vaja kasutada MATERIALIZED VIEW.
CREATE MATERIALIZED VIEW LASERMARK_VIEW
CREATE MATERIALIZED VIEW LASERMARK_VIEW
AS
SELECT w."LASERMARK" , MAX(s."SHIPMENT_DATE") AS "SHIPMENT_DATE"
FROM shipment s INNER JOIN data w ON s."SHIPMENT_ID" = w."SHIPMENT_ID"
GROUP BY w."LASERMARK" ;
CREATE INDEX lasermark_vw_shipment_date_ind on lasermark_view USING btree ("SHIPMENT_DATE") TABLESPACE pg_default;
analyze lasermark_view ;
Kordame uuesti pÀringut:
PĂ€ring kasutades materialized view
VALI
p."PARAMETER_ID" as parameter_id,
pc."PC_NAME" AS pc_name,
pc."CUSTOMER_PARTNUMBER" AS customer_partnumber,
w."LASERMARK" AS lasermark,
w."LOTID" AS lotid,
w."REPORTED_VALUE" AS reported_value,
w."LOWER_SPEC_LIMIT" AS lower_spec_limit,
w."UPPER_SPEC_LIMIT" AS upper_spec_limit,
p."TYPE_CALCUL" AS type_calcul,
s."SHIPMENT_NAME" AS shipment_name,
s."SHIPMENT_DATE" AS shipment_date,
extract(year from s."SHIPMENT_DATE") AS year,
extract(month from s."SHIPMENT_DATE") as month,
s."REPORT_NAME" AS report_name,
p."STC_NAME" AS STC_name,
p."CUSTOMERPARAM_NAME" AS customerparam_name
FROM data w INNER JOIN shipment s ON s."SHIPMENT_ID" = w."SHIPMENT_ID"
INNER JOIN parameters p ON p."PARAMETER_ID" = w."PARAMETER_ID"
INNER JOIN shipment_pc sp ON s."SHIPMENT_ID" = sp."SHIPMENT_ID"
INNER JOIN pc pc ON pc."PC_ID" = sp."PC_ID"
INNER JOIN LASERMARK_VIEW md ON md."SHIPMENT_DATE" = s."SHIPMENT_DATE" AND md."LASERMARK" = w."LASERMARK"
WHERE
s."SHIPMENT_DATE" >= '2018-07-01' AND s."SHIPMENT_DATE" <= '2018-09-30';
Ja saame veel ĂŒhe kokkuvĂ”tte:
See oli
Kulu: 502 997.55
TĂ€ideviimise aeg: 505 sekundit
Muutus
Kulu: 42 481.16
TĂ€itev aeg: 43 sekundit.
Ehkki see nii palju lubav tulemus vÔib olla petlik, tuleb esitlusi vÀrskendada. Seega ei aita lÔplik andmete saamise aeg palju. Kuid eksperimendina on see igati huvitav.
Tegelikult, nagu selgus, veel kord aitÀh ja Habrule!-
EessÔna
Nii et tellija on rahul. Ja vajalik kasutada olukorda.
Uus ĂŒlesanne: Mis vĂ”iks meil sellist vĂ€lja mĂ”elda, et sĂŒvendada ja laiendada?
Ja siin tuleb meelde â poisid, meil pole meie PostgreSQL andmebaaside jĂ€lgimist.
Asetades kĂ€e sĂŒdamele, on omad jĂ€lgimisvĂ”imalused AWS Cloud Watchis siiski olemas. Kuid kui palju kasu on sellest jĂ€lgimisest DBA-le? Ăldiselt on seda praktiliselt ĂŒldse mitte.
Kui on vĂ”imalus teha endale kasulik ja huvitav, ei saa sellisest vĂ”imalusest loobuda âŠ
SEST

Nii jÔudsime huvitavale teemale:
3. detsember 2018.
Otsus alustada töödega PostgreSQL pÀringute jÔudluse jÀlgimise vÔimaluste uurimiseks.
Aga see on juba hoopis muu lugu.
JĂ€tkub...
Allikas: habr.com
