Arvutatud veeru puhul arvutatakse väljas olev väärtus teiste samas reas olevate väärtuste puhul ja salvestatakse kettale.
Sellistest veergudest võib olla kasu koondandmete päringute puhul.
Toon näite PostgreSQL 16 põhjal.
Ülesanne: Tellimuste andmebaasis on tellimused ja tellimuste read. Ülesandeks on leida iga kuu(+aasta) kohta, kus on tehtud mõni tellimus, millised kliendid on teinud selles kuus(+aastas) kõige suuremas mahus tellimusi.
Andmebaasi kontseptuaalne struktuur: [Tellimus]-1-----------1..*-[Tellimuse_rida]
Loon tabelid.
Lisan testandmed.
Katsetan kahte lahendust, millest kummagi puhul on kaks variatsiooni. Variant 1 korral arvutatakse päringus kasutatavad väärtused käigult. Variant 2 korral kasutatakse andmete registreerimisel välja arvutatud ja salvestatud väärtuseid. Töökiiruse leidmiseks kasutan EXPLAIN ANALYZE lauset.
Lahendus 1, variant 1
Lahendus 1, variant 2
Lahendus 2, variant 1
Lahendus 2, variant 2
Töökiiruse tulemused:
Lahendus 1, variant 1: 280 ms
Lahendus 1, variant 2: 166 ms
Lahendus 2, variant 1: 100 ms
Lahendus 2, variant 2: 65 ms
Antud juhul parandavad arvutatud veerud päringute töökiirust.
Sellistest veergudest võib olla kasu koondandmete päringute puhul.
Toon näite PostgreSQL 16 põhjal.
Ülesanne: Tellimuste andmebaasis on tellimused ja tellimuste read. Ülesandeks on leida iga kuu(+aasta) kohta, kus on tehtud mõni tellimus, millised kliendid on teinud selles kuus(+aastas) kõige suuremas mahus tellimusi.
Andmebaasi kontseptuaalne struktuur: [Tellimus]-1-----------1..*-[Tellimuse_rida]
Loon tabelid.
CREATE TABLE Tellimus (tellimus_kood INTEGER NOT NULL,klient_id INTEGER NOT NULL,tellimuse_kp DATE NOT NULL,tellimuse_aasta SMALLINT GENERATED ALWAYS AS (extract(year FROM tellimuse_kp)) STORED NOT NULL,tellimuse_kuu SMALLINT GENERATED ALWAYS AS (extract(month FROM tellimuse_kp)) STORED NOT NULL,CONSTRAINT pk_tellimus PRIMARY KEY (tellimus_kood));CREATE TABLE Tellimuse_rida (tellimus_kood INTEGER NOT NULL,toode_id INTEGER NOT NULL,yhiku_hind INTEGER NOT NULL,kogus INTEGER NOT NULL,summa INTEGER GENERATED ALWAYS AS (kogus * yhiku_hind) STORED NOT NULL,CONSTRAINT pk_tellimuse_rida PRIMARY KEY (tellimus_kood, toode_id),CONSTRAINT fk_tellimuse_rida_tellimus FOREIGN KEY (tellimus_kood)REFERENCES Tellimus (tellimus_kood) ON DELETE CASCADE);Lisan testandmed.
INSERT INTO Tellimus (tellimus_kood, klient_id, tellimuse_kp)SELECT generator AS tellimus_kood,floor(random() * (1_000 - 1 + 1) + 1)::int AS klient_id,'2015-01-01'::date + floor(random() * (current_date - '2015-01-01' + 1) + 1)::int AS tellimuse_kpFROM generate_series(1, 15_000) AS generator;INSERT INTO Tellimuse_rida (tellimus_kood, toode_id, yhiku_hind, kogus)SELECT floor(random() * (1_000 - 1 + 1) + 1)::int AS tellimus_kood,floor(random() * (2_000 - 1 + 1) + 1)::int AS toode_id,floor(random() * (1_000 - 1 + 1) + 1)::int AS yhiku_hind,floor(random() * (10_000 - 1 + 1) + 1)::int AS kogusFROM generate_series(1, 100_000) AS generatorON CONFLICT DO NOTHING;DELETE FROM Tellimus WHERE NOT EXISTS (SELECT *FROM Tellimuse_ridaWHERE Tellimus.tellimus_kood=Tellimuse_rida.tellimus_kood);ANALYZE;Katsetan kahte lahendust, millest kummagi puhul on kaks variatsiooni. Variant 1 korral arvutatakse päringus kasutatavad väärtused käigult. Variant 2 korral kasutatakse andmete registreerimisel välja arvutatud ja salvestatud väärtuseid. Töökiiruse leidmiseks kasutan EXPLAIN ANALYZE lauset.
Lahendus 1, variant 1
EXPLAIN ANALYZE WITH Tellimus_stats AS (SELECT extract(year FROM tellimuse_kp) AS aasta,extract(month FROM tellimuse_kp) AS kuu,klient_id, Sum(yhiku_hind*kogus) AS summaFROM Tellimus INNER JOIN Tellimuse_rida USING (tellimus_kood)GROUP BY aasta, kuu, klient_id)SELECT aasta, kuu, klient_id, summaFROM Tellimus_stats AS TsWHERE summa=(SELECT Max(summa) AS mFROM Tellimus_stats AS Ts2WHERE Ts.aasta=Ts2.aastaAND Ts.kuu=Ts2.kuu);Lahendus 1, variant 2
EXPLAIN ANALYZE WITH Tellimus_stats AS (SELECT tellimuse_aasta AS aasta,tellimuse_kuu AS kuu,klient_id, Sum(summa) AS summaFROM Tellimus INNER JOIN Tellimuse_rida USING (tellimus_kood)GROUP BY aasta, kuu, klient_id)SELECT aasta, kuu, klient_id, summaFROM Tellimus_stats AS TsWHERE summa=(SELECT Max(summa) AS mFROM Tellimus_stats AS Ts2WHERE Ts.aasta=Ts2.aastaAND Ts.kuu=Ts2.kuu);Lahendus 2, variant 1
EXPLAIN ANALYZE WITH Tellimus_stats AS (SELECT extract(year FROM tellimuse_kp) AS aasta,extract(month FROM tellimuse_kp) AS kuu,klient_id, Sum(yhiku_hind*kogus) AS summa,Rank() OVER (PARTITION BY extract(year FROM tellimuse_kp), extract(month FROM tellimuse_kp) ORDER BY Sum(yhiku_hind*kogus) DESC) AS asetusFROM Tellimus INNER JOIN Tellimuse_rida USING (tellimus_kood)GROUP BY aasta, kuu, klient_id)SELECT aasta, kuu, klient_id, summaFROM Tellimus_statsWHERE asetus=1;Lahendus 2, variant 2
EXPLAIN ANALYZE WITH Tellimus_stats AS (SELECT tellimuse_aasta AS aasta, tellimuse_kuu AS kuu, klient_id, Sum(summa) AS summa, Rank() OVER (PARTITION BY tellimuse_aasta, tellimuse_kuu ORDER BY Sum(summa) DESC) AS asetusFROM Tellimus INNER JOIN Tellimuse_rida USING (tellimus_kood)GROUP BY aasta, kuu, klient_id)SELECT aasta, kuu, klient_id, summaFROM Tellimus_statsWHERE asetus=1;Töökiiruse tulemused:
Lahendus 1, variant 1: 280 ms
Lahendus 1, variant 2: 166 ms
Lahendus 2, variant 1: 100 ms
Lahendus 2, variant 2: 65 ms
Antud juhul parandavad arvutatud veerud päringute töökiirust.
Kas postitus oli kasulik? Hinda seda!
Keskmine hinne: Pole veel hinnanguid!