PostgreSQL 12 hadir dengan fitur baru yang disebut kolom yang dihasilkan . RDBMSes populer lainnya sudah mendukung kolom yang dihasilkan sebagai "kolom yang dihitung" atau "kolom virtual." Dengan Postgres 12, Anda sekarang dapat menggunakannya di PostgreSQL juga. Baca terus untuk mempelajari lebih lanjut.
Apa itu kolom yang dihasilkan?
Kolom yang dihasilkan seperti tampilan, tetapi untuk kolom. Berikut ini contoh dasarnya:
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=#
Kami membuat tabel t dengan dua kolom reguler yang disebut w dan h , dan kolom yang dihasilkan disebut area . Nilai luas dihitung pada waktu pembuatan, dan disimpan ke dalam disk.
Nilai kolom yang dihasilkan dihitung ulang saat baris diperbarui:
db=# UPDATE t SET w=40;
UPDATE 1
db=# SELECT * FROM t;
w | h | area
----+----+------
40 | 20 | 800
(1 row)
db=#
Fungsionalitas seperti itu sebelumnya biasanya dicapai dengan pemicu, tetapi dengan kolom yang dibuat, ini menjadi jauh lebih elegan dan bersih.
Beberapa poin yang harus Anda ketahui tentang kolom yang dihasilkan:
- Kegigihan :Saat ini, nilai kolom yang dihasilkan harus dipertahankan, dan tidak dapat dihitung dengan cepat pada waktu kueri. Kata kunci “TERSIMPAN” harus ada dalam definisi kolom.
- Ekspresi :Ekspresi yang digunakan untuk menghitung nilai harustidak dapat diubah , yaitu, harus deterministik. Itu dapat bergantung pada kolom lain, tetapi bukan kolom lain yang dihasilkan, dari tabel.
- Indeks :Kolom yang dihasilkan dapat digunakan dalam indeks, tetapi tidak dapat digunakan sebagai kunci partisi untuk tabel yang dipartisi.
- Salin dan pg_dump :Nilai kolom yang dihasilkan dihilangkan dalam output perintah “pg_dump” dan “COPY table”, karena tidak diperlukan. Anda dapat secara eksplisit memasukkannya ke dalam COPY menggunakan
COPY (SELECT * FROM t) TO STDOUT
daripadaCOPY t TO STDOUT
.
Contoh Praktis
Mari tambahkan dukungan pencarian teks lengkap ke tabel menggunakan kolom yang dihasilkan. Berikut tabel yang menyimpan seluruh teks dari semua drama Shakespeare:
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
);
Berikut tampilan datanya:
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)
Kami akan menambahkan kolom yang akan berisi leksem dalam nilai "tubuh".Fungsi to_tsvectormengembalikan leksem yang kita butuhkan:
shakespeare=# SELECT to_tsvector('english', 'move moving moved movable mover movability');
to_tsvector
-------------------------------------
'movabl':4,6 'move':1,2,3 'mover':5
(1 row)
Jenis nilai yang dikembalikan oleh to_tsvector
adalah tsvektor.
Mari kita ubah tabel untuk menambahkan kolom yang dihasilkan:
ALTER TABLE scenes
ADD tsv tsvector
GENERATED ALWAYS AS (to_tsvector('english', body)) STORED;
Anda dapat melihat perubahannya dengan \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)
Dan begitu saja, sekarang Anda dapat melakukan pencarian teks lengkap:
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=#
Baca Selengkapnya
Jika Anda membutuhkan data pra-komputasi / "cache", terutama dengan beban kerja sedikit menulis dan banyak membaca, kolom yang dihasilkan akan sangat membantu menyederhanakan aplikasi / kode sisi server Anda.
Anda dapat membaca dokumentasi v12 dariCREATE TABLEdan ALTER TABLEuntuk melihat sintaks yang diperbarui.