PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Nowość w PostgreSQL 12:Wygenerowane kolumny

PostgreSQL 12 zawiera nową funkcję o nazwie generowane kolumny . Inne popularne RDBMSy obsługują już wygenerowane kolumny jako „kolumny obliczane” lub „kolumny wirtualne”. Dzięki Postgres 12 możesz teraz używać go również w PostgreSQL. Czytaj dalej, aby dowiedzieć się więcej.

Co to jest wygenerowana kolumna?

Wygenerowana kolumna jest trochę jak widok, ale dla kolumn. Oto podstawowy przykład:

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=#

Stworzyliśmy tabelę t z dwiema zwykłymi kolumnami o nazwie w i h i wygenerowana kolumna o nazwie obszar . Wartość obszaru obliczany jest czas utworzenia wiersza i jest utrwalany na dysku.

Wartość wygenerowanych kolumn jest przeliczana po zaktualizowaniu wiersza:

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

db=#

Taka funkcjonalność była wcześniej zazwyczaj osiągana za pomocą wyzwalaczy, ale dzięki generowanym kolumnom staje się to znacznie bardziej eleganckie i czystsze.

Kilka punktów, które powinieneś wiedzieć o generowanych kolumnach:

  • Trwałość :Obecnie wartość generowanych kolumn musi być utrwalona i nie można jej obliczyć w locie w czasie zapytania. Słowo kluczowe „STORED” musi znajdować się w definicji kolumny.
  • Wyrażenie :wyrażenie użyte do obliczenia wartości musi byćniezmienne czyli musi być deterministyczny. Może zależeć od innych kolumn tabeli, ale nie od innych wygenerowanych kolumn.
  • Indeksy :Wygenerowane kolumny mogą być używane w indeksach, ale nie mogą być używane jako klucz partycji dla tabel partycjonowanych.
  • Kopiuj i pg_dump :Wartości wygenerowanych kolumn są pomijane w danych wyjściowych poleceń „pg_dump” i „COPY table”, ponieważ nie jest to konieczne. Możesz jawnie dołączyć je do COPY za pomocą COPY (SELECT * FROM t) TO STDOUT zamiast COPY t TO STDOUT .

Praktyczny przykład

Dodajmy obsługę wyszukiwania pełnotekstowego do tabeli za pomocą wygenerowanych kolumn. Oto tabela, w której przechowywany jest cały tekst wszystkich sztuk Szekspira:

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
);

Oto jak wyglądają dane:

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)

Dodamy kolumnę, która będzie zawierała leksemy w wartości „body”. Funkcja to_tsvector zwraca potrzebne leksemy:

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

Typ wartości zwracanej przez to_tsvector to wektor.

Zmieńmy tabelę, aby dodać wygenerowaną kolumnę:

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

Możesz zobaczyć zmianę za pomocą \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)

I tak po prostu, możesz teraz wykonywać wyszukiwanie pełnotekstowe:

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=#

Czytaj więcej

Jeśli potrzebujesz danych wstępnie obliczonych / „z pamięci podręcznej”, szczególnie przy obciążeniu kilkoma zapisami i wieloma odczytami, wygenerowane kolumny powinny znacznie uprościć aplikację / kod po stronie serwera.

Aby zobaczyć zaktualizowaną składnię, możesz przeczytać dokumentację w wersji 12 na temat CREATE TABLE i ALTER TABLE.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Postępy w aktualizacji online

  2. Projekt bazy danych do tworzenia tabel w locie

  3. Błąd połączenia z Postgresem w Spring Boot

  4. Jak Atand() działa w PostgreSQL

  5. postgresql generuje sekwencję bez przerw