sql >> Database teknologi >  >> RDS >> PostgreSQL

Nyt i PostgreSQL 12:Genererede kolonner

PostgreSQL 12 kommer med en ny funktion kaldet genererede kolonner . Andre populære RDBMS'er understøtter allerede genererede kolonner som "beregnede kolonner" eller "virtuelle kolonner." Med Postgres 12 kan du nu også bruge det i PostgreSQL. Læs videre for at lære mere.

Hvad er en genereret kolonne?

En genereret kolonne ligner en visning, men for kolonner. Her er et grundlæggende eksempel:

db=# CREATE TABLE t (w real, h real, area real GENERATED ALWAYS AS (w*h) STORED);
CREATE TABLE
db=# INSERT INTO t (w, h) VALUES (10, 20);
INSERT 0 1
db=# SELECT * FROM t;
 w  | h  | area
----+----+------
 10 | 20 |  200
(1 row)

db=#

Vi oprettede en tabel t med to regulære kolonner kaldet w og h ,og en genereret kolonne kaldet område . Værdien af ​​areal er beregnet til oprettelsestidspunkt for rækken, og bevares på disken.

Værdien af ​​genererede kolonner beregnes igen, når rækken opdateres:

db=# UPDATE t SET w=40;
UPDATE 1
db=# SELECT * FROM t;
 w  | h  | area
----+----+------
 40 | 20 |  800
(1 row)

db=#

Sådan funktionalitet blev tidligere normalt opnået med triggere, men med genererede kolonner bliver dette meget mere elegant og renere.

Et par punkter, du bør vide om genererede kolonner:

  • Vedholdenhed :I øjeblikket skal værdien af ​​genererede kolonner vedblive og kan ikke beregnes direkte på forespørgselstidspunktet. "LAGET"-søgeordet skal være til stede i kolonnedefinitionen.
  • Udtrykket :Udtrykket, der bruges til at beregne værdien, skal væreuforanderligt , det vil sige, det skal være deterministisk. Det kan afhænge af andre kolonner, men ikke andre genererede kolonner, i tabellen.
  • Indekser :Genererede kolonner kan bruges i indekser, men kan ikke bruges som en partitionsnøgle til partitionerede tabeller.
  • Kopiér og pg_dump :Værdierne af genererede kolonner udelades i outputtet af “pg_dump” og “COPY table” kommandoer, da det er unødvendigt. Du kan udtrykkeligt inkludere dem i COPY ved at bruge COPY (SELECT * FROM t) TO STDOUT i stedet for COPY t TO STDOUT .

Et praktisk eksempel

Lad os tilføje fuldtekstsøgningsstøtte til en tabel ved hjælp af genererede kolonner. Her er en tabel, der gemmer hele teksten i alle Shakespeares skuespil:

CREATE TABLE scenes (
    workid text,       -- denotes the name of the play (like "macbeth")
    act integer,       -- the act (like 1)
    scene integer,     -- the scene within the act (like 7)
    description text,  -- short desc of the scene (like "Macbeth's castle.")
    body text          -- full text of the scene
);

Sådan ser dataene ud:

shakespeare=# SELECT workid, act, scene, description, left(body, 200) AS body_start
shakespeare-# FROM scenes WHERE workid='macbeth' AND act=1 AND scene=1;
 workid  | act | scene |   description   |                  body_start
---------+-----+-------+-----------------+----------------------------------------------
 macbeth |   1 |     1 | A desert place. | [Thunder and lightning. Enter three Witches]+
         |     |       |                 |                                             +
         |     |       |                 | First Witch: When shall we three meet again +
         |     |       |                 | In thunder, lightning, or in rain?          +
         |     |       |                 |                                             +
         |     |       |                 | Second Witch: When the hurlyburly's done,   +
         |     |       |                 | When the battle's lost and won.             +
         |     |       |                 |
(1 row)

Vi tilføjer en kolonne, der vil indeholde leksemerne i værdien "body". Funktionen to_tsvector returnerer de leksemer, vi har brug for:

shakespeare=# SELECT to_tsvector('english', 'move moving moved movable mover movability');
             to_tsvector
-------------------------------------
 'movabl':4,6 'move':1,2,3 'mover':5
(1 row)

Typen af ​​værdien returneret af to_tsvector er tsvector.

Lad os ændre tabellen for at tilføje en genereret kolonne:

ALTER TABLE scenes
  ADD tsv tsvector
    GENERATED ALWAYS AS (to_tsvector('english', body)) STORED;

Du kan se ændringen med \d :

shakespeare=# \d scenes
                                                Table "public.scenes"
   Column    |   Type   | Collation | Nullable |                               Default
-------------+----------+-----------+----------+----------------------------------------------------------------------
 workid      | text     |           | not null |
 act         | integer  |           | not null |
 scene       | integer  |           | not null |
 description | text     |           |          |
 body        | text     |           |          |
 tsv         | tsvector |           |          | generated always as (to_tsvector('english'::regconfig, body)) stored
Indexes:
    "scenes_pkey" PRIMARY KEY, btree (workid, act, scene)

Og bare sådan kan du nu lave fuldtekstsøgninger:

shakespeare=# SELECT
  workid, act, scene, ts_headline(body, q)
FROM (
  SELECT
    workid, act, scene, body, ts_rank(tsv, q) as rank, q
  FROM
    scenes, plainto_tsquery('uneasy head') q
  WHERE
    tsv @@ q
  ORDER BY
    rank DESC
  LIMIT
    5
) p
ORDER BY
  rank DESC;
  workid  | act | scene |                        ts_headline
----------+-----+-------+-----------------------------------------------------------
 henry4p2 |   3 |     1 | <b>Uneasy</b> lies the <b>head</b> that wears a crown.   +
          |     |       |                                                          +
          |     |       |    Enter WARWICK and Surrey                              +
          |     |       |                                                          +
          |     |       | Earl of Warwick
 henry5   |   2 |     2 | <b>head</b> assembled them?                              +
          |     |       |                                                          +
          |     |       | Lord Scroop: No doubt, my liege, if each man do his best.+
          |     |       |                                                          +
          |     |       | Henry V: I doubt not that; since we are well persuaded   +
          |     |       | We carry not a heart with us from hence
(2 rows)

shakespeare=#

Læs mere

Hvis du har et behov for forudberegnet / "cachelagret" data, især med en arbejdsbyrde på få skrivninger og masser af læsninger, burde genererede kolonner hjælpe med at forenkle din applikation / server-side kode meget.

Du kan læse v12-dokumentationen af ​​CREATE TABLE og ALTER TABLE for at se den opdaterede syntaks.


  1. Fuldtekstsøgning virker ikke, hvis stopord er inkluderet, selvom stopordlisten er tom

  2. SQLite Connection lækket, selvom alt lukkede

  3. SQL Server-ydelse TOP IO-forespørgsel -2

  4. Hvordan rettes fejl i pg_dump-versionen?