Changes between Version 3 and Version 4 of Phase1_Partitioning


Ignore:
Timestamp:
12/10/25 01:55:56 (3 weeks ago)
Author:
226052
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Phase1_Partitioning

    v3 v4  
    4040    return_date TIMESTAMP,
    4141    last_update TIMESTAMP DEFAULT now() NOT NULL,
    42     PRIMARY KEY (rental_id, rental_date),
    43     CONSTRAINT fk_rental_inventory FOREIGN KEY (inventory_id) REFERENCES inventory(inventory_id) ON UPDATE CASCADE ON DELETE RESTRICT,
    44     CONSTRAINT fk_rental_customer FOREIGN KEY (customer_id) REFERENCES customer(customer_id) ON UPDATE CASCADE ON DELETE RESTRICT,
    45     CONSTRAINT fk_rental_staff FOREIGN KEY (staff_id) REFERENCES staff(staff_id) ON UPDATE CASCADE ON DELETE RESTRICT
     42    PRIMARY KEY (rental_id, rental_date)
    4643)
    4744PARTITION BY RANGE (rental_date);
     
    7774}}}
    7875
     76На крај ги додаваме ограничувањата за надворешни клучеви.
     77{{{
     78ALTER TABLE rental ADD CONSTRAINT fk_rental_inventory FOREIGN KEY (inventory_id) REFERENCES inventory(inventory_id) ON UPDATE CASCADE ON DELETE RESTRICT;
     79ALTER TABLE rental ADD CONSTRAINT fk_rental_customer FOREIGN KEY (customer_id) REFERENCES customer(customer_id) ON UPDATE CASCADE ON DELETE RESTRICT;
     80ALTER TABLE rental ADD CONSTRAINT fk_rental_staff FOREIGN KEY (staff_id) REFERENCES staff(staff_id) ON UPDATE CASCADE ON DELETE RESTRICT;
     81}}}
     82
     83
    7984Сега ќе извршиме пример прашалник на старата табела('''rental_old''') каде што немаме партиции.
    8085
     
    8893[[Image(rental_query.png)]]
    8994
    90 Од тука може да забележиме дека PostgreSQL мора да направи целосен Sequential Scan на табелата и бидејќи табелата не е партиционирана query optimizer - от нема да може да ги прескокне редовите што не припаѓаат на бараниот датумски опсег, па затоа ја скенира цела табела и елеминира повеќе од 8 милиони записи со помош на филтер.
     95Од тука може да забележиме дека PostgreSQL мора да направи целосен Sequential Scan на табелата и бидејќи табелата не е партиционирана query optimizer-от нема да може да ги прескокне редовите што не припаѓаат на бараниот датумски опсег, па затоа ја скенира цела табела и елеминира повеќе од 8 милиони записи со помош на филтер.
    9196
    9297
     
    102107[[Image(rental_query_partition.png)]]
    103108
    104 По партиционирањето, PostgreSQL веќе не ја скенира целата табела, туку со помош на '''partition pruning''' кој што во поновите верзии на PostgreSQL е пуштен по default PostgreSQL не ги скенира партициите во кој што WHERE условот не е исполнет. Ја скенира само конкретната партиција '''rental_2022''' и со тоа наместо да обработуваат 10 милиони редови, се обработуваат само податоците во релевантната партиција, времето на извршување е скоро преполовено и со помош на филтер се елеминираат околу 5 илјади редови наместо 8 милиони.
     109По партиционирањето, PostgreSQL веќе не ја скенира целата табела, туку со помош на '''partition pruning''' кој што во поновите верзии на PostgreSQL е пуштен по default PostgreSQL не ги скенира партициите во кој што WHERE условот не е исполнет. Ја скенира само конкретната партиција '''rental_2022''' и со тоа наместо да обработуваат 10 милиони редови, се обработуваат само податоците во релевантната партиција, времето на извршување е скоро преполовено и со помош на филтер се елиминираат околу 5 илјади редови наместо 8 милиони.
     110
     111=== Партицинориање на payment табелата
     112
     113Постапката е иста како и кај rental табелата.
     114
     115{{{ ALTER TABLE payment RENAME TO payment_old; }}}
     116
     117{{{
     118CREATE TABLE payment (
     119    payment_id BIGINT GENERATED ALWAYS AS IDENTITY,
     120    customer_id BIGINT NOT NULL,
     121    staff_id BIGINT NOT NULL,
     122    rental_id BIGINT NOT NULL,
     123    amount NUMERIC(5,2) NOT NULL,
     124    payment_date TIMESTAMP NOT NULL,
     125    PRIMARY KEY (payment_id, payment_date)
     126)
     127PARTITION BY RANGE (payment_date);
     128}}}
     129
     130Тука правиме партиционирање по месец па така ќе имаме 5 години x 12 месеци = 60 партиции.
     131{{{
     132DO $$
     133DECLARE
     134    y int;
     135    m int;
     136    start_date date;
     137    end_date date;
     138    partition_name text;
     139BEGIN
     140    FOR y IN 2020..2024 LOOP
     141        FOR m IN 1..12 LOOP
     142            start_date := make_date(y, m, 1);
     143            end_date := (make_date(y, m, 1) + interval '1 month')::date;
     144
     145            partition_name := format('payment_%s_%s', y, lpad(m::text, 2, '0'));
     146
     147            EXECUTE format(
     148                'CREATE TABLE %I PARTITION OF payment
     149                 FOR VALUES FROM (%L) TO (%L);',
     150                partition_name,
     151                start_date,
     152                end_date
     153            );
     154        END LOOP;
     155    END LOOP;
     156END $$;
     157}}}
     158
     159{{{
     160INSERT INTO payment (customer_id, staff_id, rental_id, amount, payment_date)
     161SELECT customer_id, staff_id, rental_id, amount, payment_date
     162FROM payment_old;
     163}}}
     164
     165{{{
     166ALTER TABLE payment ADD CONSTRAINT fk_payment_customer FOREIGN KEY (customer_id) REFERENCES customer(customer_id) ON UPDATE CASCADE ON DELETE RESTRICT;
     167ALTER TABLE payment ADD CONSTRAINT fk_payment_staff FOREIGN KEY (staff_id) REFERENCES staff(staff_id) ON UPDATE CASCADE ON DELETE RESTRICT;
     168}}}
    105169
    106170
    107171
     172
     173
     174