Parathënie, ose si lindi ideja e particionimit
Fillimi i historisĂ« Ă«shtĂ« kĂ«tu: Pasi pothuajse tĂ« gjitha burimet pĂ«r optimizimin e kĂ«rkesĂ«s, nĂ« atĂ« moment, ishin shteruar, u ngrit pyetja â çfarĂ« bĂ«jmĂ« mĂ« tej? KĂ«shtu edhe lindi ideja e particionimit.

Një digresion lirik:
PikĂ«risht ânĂ« atĂ« momentâ, sepse . Faleminderit dhe Habr-it!
Pra, si mund ta bëjmë klientin disi të kënaqur dhe njëkohësisht të përmirësojmë aftësitë tona?
Nëse e thjeshtojmë gjithçka në maksimum, atëherë ka vetëm dy mënyra për të përmirësuar rrënjësisht performancën e bazës së të dhënave:
1) Rruga ekstensivĐ” â shtojmĂ« burimet, ndryshojmĂ« konfigurimin;
2) Rruga intensive â optimizimi i kĂ«rkesave
Meqë, siç e përsëris, në atë moment nuk ishte më e qartë se çfarë tjetër mund të ndryshohej në kërkesë për ta përshpejtuar, u zgjodh rruga e ndryshimit të dizajnit të tabelave.
Pra, lind pyetja kryesore â çfarĂ« dhe si do tĂ« ndryshojmĂ«?
Kushtet fillestare
Së pari, kemi një ERD të tillë (të paraqitur në mënyrë të thjeshtuar me kusht):

Karakteristikat kryesore:
- marrĂ«dhĂ«nie âshumĂ« me shumĂ«â
- tabela tashmë ka një çelës të mundshëm particionimi
Kërkesa fillestare:
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' ;
Rezultatet e ekzekutimit në bazën e të dhënave testuese:
Kosto : 502 997.55
Koha e ekzekutimit: 505 sekonda.
ĂfarĂ« shohim? NjĂ« kĂ«rkesĂ« e zakonshme, sipas njĂ« intervali kohor.
BĂ«jmĂ« njĂ« supozim logjik shumĂ« tĂ« thjeshtĂ«: nĂ«se kemi njĂ« mostĂ«r tĂ« njĂ« prerjeje kohore, çfarĂ« do tĂ« na ndihmojĂ«? SaktĂ« â particionimi.
ĂfarĂ« tĂ« particionohet?
NĂ« pamje tĂ« parĂ«, zgjedhja Ă«shtĂ« e qartĂ« â particionimi deklarativ i tabelĂ«s «shipment» sipas çelĂ«sit «SHIPMENT_DATE» (duke e paraprirĂ« shumĂ« ngjarjet â nĂ« fund nĂ« production doli pak ndryshe).
Si të particionohet?
Edhe kjo pyetje nuk është shumë e vështirë. Për fat, në PostgreSQL 10 tani ekziston një mekanizëm njerëzor particionimi.
Pra:
- RuajmĂ« dump-in e tabelĂ«s burimore â pg_dump source_table
- FshijmĂ« tabelĂ«n burimore â drop table source_table
- KrijojmĂ« tabelĂ«n prind me particionim sipas intervalit â create table source_table
- KrijojmĂ« particionet â create table source_table, create index
- ImportojmĂ« dump-in e krijuar nĂ« hapin 1 â pg_restore
Skriptet për particionim
Për thjeshtësi dhe lehtësi përdorimi, hapat 2, 3, 4 u bashkuan në një skript të vetëm.
Pra:
Ruajmë dump-in e tabelës burimore
pg_dump postgres --file=/dump/shipment.dmp --format=c --table=shipment --verbose > /dump/shipment.log 2>&1Fshijmë tabelën burimore + Krijojmë tabelën prind me particionim sipas intervalit + Krijojmë particionet
--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 'CREATE TEMPORARY TABLE FOR SHIPMENT_DATE';
CREATE TEMP TABLE tmp_shipment_date as select distinct "SHIPMENT_DATE" from shipment order by "SHIPMENT_DATE" ;
RAISE NOTICE 'DROP 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 'CREATE PARTITIONS FOR TABLE 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
--NEW borders only for second and after time
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 ' ) ;
--Drop first time flag
first_flag := false ;
END LOOP;
end
$$;Importojmë dump-in
pg_restore -d postgres --data-only --format=c --table=shipment --verbose shipment.dmp > \/tmp\/data_dump\/shipment_restore.log 2>&1Kontrollojmë rezultatet e particionimit
ĂfarĂ« kemi si pĂ«rfundim? Teksti i plotĂ« i planit tĂ« ekzekutimit Ă«shtĂ« i gjatĂ« dhe i mĂ«rzitshĂ«m, prandaj mund tĂ« kufizohemi te shifrat pĂ«rfundimtare.
Ishte
Kostoja: 502 997.55
Koha e ekzekutimit: 505 sekonda.
U bë
Kostoja: 77 872.36
Koha e ekzekutimit: 79 sekonda.
Një rezultat mjaft i mirë. Ulëm koston dhe kohën e ekzekutimit. Kështu, përdorimi i particionimit jep efektin e pritur dhe, në përgjithësi, pa surpriza.
Ta gëzojmë klientin
Rezultatet e testimit iu paraqitën klientit për shqyrtim. Dhe pas njohjes me to, u dha një verdikt disi i papritur: «Shkëlqyeshëm, particiononi tabelën «data»».
Po, por ne po studionim një tabelë krejt tjetër, «shipment»; tabela «data» nuk ka fushën «SHIPMENT_DATE».
Nuk është problem, shtojeni, ndryshojeni. Kryesorja është që klienti të jetë i kënaqur me rezultatin përfundimtar; hollësitë e zbatimit nuk janë edhe aq të rëndësishme.
Particionojmë tabelën kryesore «data»
Në përgjithësi, nuk pati ndonjë vështirësi të veçantë. Megjithatë, algoritmi i particionimit, natyrisht, ndryshoi disi.
Shtojmë kolonën «SHIPMENT_DATA» në tabelën «data»
psql -h host -U bazë -d përdorues
=> ALTER TABLE data ADD COLUMN "SHIPMENT_DATE" timestamp without time zone ;Plotësojmë vlerat e kolonës «SHIPMENT_DATA» në tabelën «data» me vlerat e kolonës me të njëjtin emër nga tabela «shipment»
-----------------------------
--update_data.sql
--updating for altered table "data" to values of "shipment_data" from the table "shipment"
--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 'Total %',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 'row count = % , from %',row_count,total_rows;
END LOOP;
end
$$;Ruajmë dump-in e tabelës «data»
pg_dump postgres --file=/dump/data.dmp --format=c --table=data --verbose > /dump/data.log 2>&1</sourceRikrijojmë tabelën e particionuar «data»
--create_partition_data.sql
--krijo particione për tabelën "wafer data" sipas kolonës së intervalit "shipment_data" me kohëzgjatje një mujore
--versioni 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 'KRIJO TABELĂ TĂ PĂRKOHSHME PĂR SHIPMENT_DATE';
CREATE TEMP TABLE tmp_shipment_date as select distinct "SHIPMENT_DATE" from shipment order by "SHIPMENT_DATE" ;
RAISE NOTICE 'FSHI TABELĂN data';
drop table data cascade ;
RAISE NOTICE 'KRIJO TABELĂN E PARTICIONUAR 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 'KRIJO PARTICIONE PĂR TABELĂN 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") ;
--Inicializo kufijtë
IF begin_year = '0' THEN
RAISE NOTICE '***Inicializo kufijtë';
first_flag := true ; --flamur për herën e parë
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;
-- Kontrollo datën aktuale brenda kufijve, JO për herën e parë
RAISE NOTICE 'Të dhënat aktuale = %',to_char( to_date( current_year||'.'||current_month, 'YYYY.MM'), 'YYYY.MM');
RAISE NOTICE 'Të dhënat e fillimit = %',to_char( to_date( begin_year||'.'||begin_month, 'YYYY.MM'), 'YYYY.MM');
RAISE NOTICE 'Të dhënat pasuese = %',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 '***VAZHDO';
CONTINUE ;
ELSE
--Kufij të RINJ vetëm nga hera e dytë e tutje
RAISE NOTICE '***KUFIJ TĂ RINJ';
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 'NUMRI I PARTICIONIT % , EMRI I TABELĂS =%',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 'EMRI I INDEKSIT =%',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 'EMRI I INDEKSIT =%',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 'EMRI I INDEKSIT =%',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 'EMRI I INDEKSIT =%',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 'EMRI I INDEKSIT =%',index_name;
EXECUTE format('CREATE INDEX ' || quote_ident(index_name) || ' ON '|| quote_ident(partition_name) ||' USING btree ("SHIPMENT_DATE") TABLESPACE pg_default ' ) ;
--Hiq flamurin e herës së parë
first_flag := false ;
END LOOP;
end
$$;
Ngarkojmë dump-in e krijuar në hapin 3.
pg_restore -h Ń
ĐŸŃŃ -ŃĐ·Đ”Ń -d база --data-only --format=c --table=data --verbose data.dmp > data_restore.log 2>&1KrijojmĂ« njĂ« seksion tĂ« veçantĂ« pĂ«r tĂ« dhĂ«nat e vjetra
---------------------------------------------------
--create_partition_for_old_dates.sql
--create partitions for keeping old dates
--version 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 'Old date is %',rec_shipment_date.min_date ;
partition_name := 'data_old_dates' ;
RAISE NOTICE 'PARTITION NAME IS %',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
$$;Rezultatet përfundimtare:
Ishte
Kostoja: 502 997.55
Koha e ekzekutimit: 505 sekonda.
U bë
Kostoja: 68 533.70
Koha e ekzekutimit: 69 sekonda
ShumĂ« mirĂ«, vĂ«rtet shumĂ« mirĂ«. Sidomos duke pasur parasysh se gjatĂ« procesit arritĂ«m tĂ« kuptojmĂ« pak a shumĂ« edhe mekanizmin e particionimit nĂ« PostgreSQL 10 â rezultat i shkĂ«lqyer.
Një hapje lirikë
A mund tĂ« bĂ«het edhe mĂ« mirĂ« â PO, MUND TĂ BĂHET!PĂ«r kĂ«tĂ« duhet tĂ« pĂ«rdoret 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 ;
E rishkruajmë edhe një herë kërkesën:
Kërkesë duke përdorur materialized view
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."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';
Dhe marrim edhe një rezultat përfundimtar:
Ishte
Kostoja: 502 997.55
Koha e ekzekutimit: 505 sekonda
U bë
Kostoja: 42 481.16
Koha e ekzekutimit: 43 sekonda.
Megjithëse, sigurisht, ky rezultat kaq premtues është mashtrues, sepse pamjet duhen rifreskuar. Kështu që koha përfundimtare e marrjes së të dhënave nuk do të ndihmojë edhe aq shumë. Por si eksperiment, është mjaft interesante.
Në fakt, siç doli, edhe një herë faleminderit dhe Habr !-
Pasthënie
Pra, klienti është i kënaqur. Dhe të shtoni një kolonë të re - asnjë problem, më poshtë është një zgjidhje e thjeshtë një-linjëshe. Zgjidhja është evolucioni i skemës! të përfitojmë nga situata.
DetyrĂ« e re: ĂfarĂ« mund tĂ« shpikim qĂ« ta thellojmĂ« dhe zgjerojmĂ«?
Dhe kĂ«tu kujtojmĂ« â djema, ne nĂ« fakt nuk kemi monitorim tĂ« bazave tona tĂ« tĂ« dhĂ«nave PostgreSQL.
Të themi të drejtën, një lloj monitorimi në formën e Cloud Watch në AWS gjithsesi ekziston. Por çfarë dobie ka ky monitorim për DBA? Në thelb, pothuajse asnjë.
NĂ«se tĂ« Ă«shtĂ« dhĂ«nĂ« mundĂ«sia tĂ« bĂ«sh diçka tĂ« dobishme dhe interesante edhe pĂ«r veten, nuk mund tĂ« mos e shfrytĂ«zosh njĂ« mundĂ«si tĂ« tillĂ« âŠ
SEPSE

Kështu iu afruam pjesës më interesante:
3 Dhjetor 2018.
Marrja e vendimit për të nisur punën për studimin e mundësive ekzistuese të monitorimit të performancës së kërkesave PostgreSQL.
Por kjo është tashmë një histori krejt tjetër.
Vazhdimi pasonâŠ
Burimi: habr.com
