Dalam
artikel sebelumnya
, saya menjelaskan konsep dan implementasi database yang dibangun berdasarkan fungsi, bukan tabel dan bidang seperti dalam database relasional. Ini memberi banyak contoh yang menunjukkan keuntungan dari pendekatan ini dibandingkan klasik. Banyak yang menemukan mereka tidak cukup meyakinkan.
Dalam artikel ini saya akan menunjukkan bagaimana konsep ini memungkinkan Anda untuk dengan cepat dan nyaman menyeimbangkan penulisan dan membaca ke database tanpa ada perubahan dalam logika kerja. Mereka mencoba menerapkan fungsi yang serupa dalam DBMS komersial modern (khususnya, Oracle dan Microsoft SQL Server). Di akhir artikel, saya akan menunjukkan apa yang terjadi pada mereka, secara halus, tidak terlalu.
Deskripsi
Seperti sebelumnya, untuk pemahaman yang lebih baik, saya akan memulai deskripsi dengan contoh-contoh. Misalkan kita perlu menerapkan logika yang akan mengembalikan daftar departemen dengan jumlah karyawan di dalamnya dan total gaji mereka.
Dalam database fungsional, akan terlihat seperti ini:
Kompleksitas menjalankan kueri ini dalam DBMS apa pun akan setara dengan
O (jumlah karyawan) , karena untuk perhitungan ini Anda perlu memindai seluruh tabel karyawan, dan kemudian mengelompokkannya menurut departemen. Akan ada juga penambahan kecil (kami percaya bahwa ada lebih banyak karyawan daripada departemen) tergantung pada rencana yang dipilih
O (jumlah log karyawan) atau
O (jumlah departemen) untuk pengelompokan dan sebagainya.
Jelas bahwa overhead untuk eksekusi dapat berbeda dalam DBMS yang berbeda, tetapi kompleksitasnya tidak akan berubah dengan cara apa pun.
Dalam implementasi yang diusulkan, DBMS fungsional akan membentuk satu subquery, yang akan menghitung nilai yang diperlukan untuk departemen, dan kemudian membuat GABUNG dengan tabel departemen untuk mendapatkan nama. Namun, untuk setiap fungsi, ketika mendeklarasikan, dimungkinkan untuk menentukan marker MATERIALISASI khusus. Sistem akan secara otomatis membuat bidang yang sesuai untuk setiap fungsi tersebut. Ketika nilai fungsi berubah, nilai bidang akan berubah dalam transaksi yang sama. Saat mengakses fungsi ini, banding akan dilakukan ke bidang terhitung.
Secara khusus, jika Anda menempatkan MATERIALISASI untuk fungsi-fungsi yang
dihitung Karyawan dan
gaji , maka dalam tabel dengan daftar departemen, dua bidang ditambahkan di mana jumlah karyawan dan total gaji mereka akan disimpan. Dengan perubahan apa pun pada karyawan, gaji atau afiliasi mereka dengan departemen, sistem akan secara otomatis mengubah nilai-nilai bidang ini. Kueri di atas akan mulai mengakses bidang ini secara langsung dan akan dieksekusi untuk
O (jumlah departemen) .
Apa batasannya? Hanya satu hal: fungsi seperti itu harus memiliki jumlah nilai input yang terbatas yang nilainya didefinisikan. Jika tidak, tidak mungkin untuk membangun tabel yang menyimpan semua nilainya, karena tidak mungkin ada tabel dengan jumlah baris yang tak terbatas.
Contoh:
Fungsi ini didefinisikan untuk jumlah nilai tak terbatas dari angka N (misalnya, nilai negatif apa pun cocok). Oleh karena itu, tidak dapat dimasukkan MATERIALISASI. Dengan demikian, ini adalah batasan logis dan bukan teknis (yaitu, bukan karena kami tidak dapat mengimplementasikan ini). Kalau tidak, tidak ada batasan. Anda dapat menggunakan pengelompokan, pengurutan, DAN dan ATAU, PARTISI, rekursi, dll.
Misalnya, dalam tugas 2.2 artikel sebelumnya, Anda dapat menggunakan MATERIALISASI pada kedua fungsi:
Sistem itu sendiri akan membuat satu tabel dengan kunci tipe
Pelanggan ,
Produk dan
INTEGER , menambahkan dua bidang ke dalamnya dan akan memperbarui nilai bidang di dalamnya dengan perubahan apa pun. Setelah panggilan lebih lanjut ke fungsi-fungsi ini, mereka tidak akan dihitung, tetapi nilai-nilai dari bidang yang sesuai akan dibaca.
Menggunakan mekanisme ini, Anda bisa, misalnya, menyingkirkan rekursi (CTE) dalam kueri. Secara khusus, pertimbangkan grup yang membuat pohon menggunakan hubungan anak / orang tua (setiap grup memiliki tautan ke orang tuanya):
Dalam database fungsional, logika rekursi dapat didefinisikan sebagai berikut:
Karena MATERIALIZED ditempelkan untuk fungsi
isParent , sebuah tabel dengan dua kunci (grup) akan dibuat untuk itu, di mana bidang
isParent akan benar hanya jika kunci pertama adalah turunan dari yang kedua. Jumlah entri dalam tabel ini akan sama dengan jumlah grup dikalikan kedalaman rata-rata pohon. Jika perlu, misalnya, untuk menghitung jumlah keturunan kelompok tertentu, maka Anda dapat mengakses fungsi ini:
Tidak akan ada CTE dalam kueri SQL. Sebagai gantinya, akan ada GROUP BY sederhana.
Dengan menggunakan mekanisme ini, Anda juga dapat dengan mudah mendenormalkan basis data jika perlu:
Saat Anda memanggil fungsi
tanggal untuk baris pesanan, bacaan akan dari tabel dengan baris urutan bidang yang ada indeksnya. Saat mengubah tanggal pesanan, sistem itu sendiri secara otomatis akan menghitung ulang tanggal yang dinon-denalkan di baris.
Manfaatnya
Mengapa seluruh mekanisme ini dibutuhkan? Dalam DBMS klasik, tanpa menulis ulang kueri, pengembang atau DBA hanya dapat mengubah indeks, menentukan statistik, dan memberi tahu perencana kueri bagaimana cara mengeksekusinya (apalagi, HINT hanya tersedia dalam DBMS komersial). Tidak peduli seberapa keras mereka berusaha, mereka tidak akan dapat memenuhi permintaan pertama dalam artikel untuk
O (jumlah departemen) tanpa mengubah permintaan dan menambah pemicu. Dalam skema yang diusulkan, pada tahap pengembangan, Anda tidak perlu memikirkan struktur penyimpanan data dan agregasi mana yang akan digunakan. Semua ini dapat dengan mudah diubah dengan cepat, langsung beroperasi.
Dalam praktiknya, ini adalah sebagai berikut. Beberapa orang mengembangkan logika secara langsung berdasarkan tugas. Mereka tidak berpengalaman dalam algoritme dan kompleksitasnya, atau dalam rencana pelaksanaan, atau dalam jenis join'ov, atau dalam komponen teknis lainnya. Orang-orang ini lebih banyak analis bisnis daripada pengembang. Kemudian, semuanya masuk ke pengujian atau operasi. Log kueri panjang diaktifkan. Ketika permintaan panjang terdeteksi, maka orang lain (lebih teknis - pada kenyataannya DBA) memutuskan untuk memasukkan MATERIALISASI pada beberapa fungsi perantara. Dengan demikian, pencatatan sedikit melambat (karena memperbarui bidang tambahan dalam transaksi diperlukan). Namun, tidak hanya permintaan ini dipercepat secara signifikan, tetapi juga semua orang lain yang menggunakan fungsi ini. Pada saat yang sama, membuat keputusan tentang fungsi tertentu mana yang akan terwujud relatif sederhana. Dua parameter utama: jumlah nilai input yang mungkin (persis berapa banyak rekaman akan berada di tabel yang sesuai), dan seberapa sering digunakan dalam fungsi lain.
Analog
DBMS komersial modern memiliki mekanisme yang serupa: PANDANGAN MATERIALISASI dengan FAST REFRESH (Oracle) dan INDEXED VIEW (Microsoft SQL Server). Dalam PostgreSQL, MATERIALIZED VIEW tidak dapat memperbarui dalam transaksi, tetapi hanya berdasarkan permintaan (dan bahkan dengan batasan yang sangat ketat), jadi kami tidak mempertimbangkannya. Tetapi mereka memiliki beberapa masalah, yang sangat membatasi penggunaannya.
Pertama, Anda dapat mengaktifkan materialisasi hanya jika Anda telah membuat TAMPILAN biasa. Jika tidak, Anda harus menulis ulang permintaan yang tersisa untuk mengakses tampilan yang baru dibuat untuk menggunakan materialisasi ini. Atau biarkan semuanya apa adanya, tetapi setidaknya akan tidak efektif jika ada data tertentu yang sudah dihitung, tetapi banyak pertanyaan tidak selalu menggunakannya, tetapi hitung lagi.
Kedua, mereka memiliki sejumlah besar pembatasan:
Oracle5.3.8.4 Batasan Umum tentang Refresh Cepat
Permintaan definisi tampilan terwujud dibatasi sebagai berikut:
- Tampilan terwujud tidak boleh berisi referensi ke ekspresi tidak berulang seperti
SYSDATE
dan ROWNUM
. - Tampilan terwujud tidak boleh berisi referensi ke tipe data
RAW
atau LONG
RAW
. - Itu tidak dapat berisi subquery daftar
SELECT
. - Itu tidak dapat berisi fungsi analitik (misalnya,
RANK
) dalam klausa SELECT
. - Itu tidak bisa referensi tabel di mana indeks
XMLIndex
didefinisikan. - Itu tidak bisa berisi klausa
MODEL
. - Itu tidak bisa mengandung klausa
HAVING
dengan subquery. - Itu tidak dapat berisi kueri bersarang yang memiliki
ANY
, ALL
, atau NOT
EXISTS
. - Itu tidak boleh mengandung klausa
[START WITH โฆ] CONNECT BY
. - Itu tidak dapat berisi beberapa tabel detail di situs yang berbeda.
ON
COMMIT
tampilan terwujud tidak dapat memiliki tabel detail jarak jauh.- Tampilan terwujud yang bersarang harus memiliki gabungan atau agregat.
- Tampilan gabungan terwujud dan tampilan agregat terwujud dengan klausa
GROUP
BY
tidak dapat memilih dari tabel yang diorganisir indeks.
5.3.8.5 Batasan tentang Perbarui Cepat pada Tampilan Terwujud dengan Hanya Bergabung
Menentukan kueri untuk tampilan terwujud hanya dengan penggabungan dan tidak ada agregat yang memiliki pembatasan penyegaran cepat berikut:
- Semua pembatasan dari " Pembatasan Umum tentang Refresh Cepat ".
- Mereka tidak dapat memiliki klausa atau agregat
GROUP
BY
. - Baris pendek semua tabel dalam daftar
FROM
harus muncul di daftar SELECT
dari kueri. - Log tampilan terwujud harus ada dengan baris baris untuk semua tabel dasar dalam daftar
FROM
dari permintaan. - Anda tidak dapat membuat tampilan terwujud cepat yang dapat disegarkan dari beberapa tabel dengan gabungan sederhana yang menyertakan kolom tipe objek dalam pernyataan
SELECT
.
Juga, metode penyegaran yang Anda pilih tidak akan efisien secara optimal jika:
- Permintaan mendefinisikan menggunakan gabungan luar yang berperilaku seperti gabungan dalam. Jika kueri pendefinisian berisi gabungan seperti itu, pertimbangkan untuk menulis ulang kueri pendefinisian untuk berisi gabungan internal.
- Daftar
SELECT
dari tampilan terwujud berisi ekspresi pada kolom dari beberapa tabel.
5.3.8.6 Pembatasan pada Refresh Cepat pada Tampilan Terwujud dengan Agregat
Menentukan kueri untuk tampilan terwujud dengan agregat atau gabungan memiliki batasan berikut tentang penyegaran cepat:
Penyegaran cepat didukung untuk tampilan terwujud ON
COMMIT
dan ON
DEMAND
, namun pembatasan berikut berlaku:
- Semua tabel dalam tampilan terwujud harus memiliki log tampilan terwujud, dan log tampilan terwujud harus:
- Berisi semua kolom dari tabel yang dirujuk dalam tampilan terwujud.
- Tentukan dengan
ROWID
dan INCLUDING
VALUES
NEW
. - Tentukan klausa
SEQUENCE
jika tabel diharapkan memiliki campuran sisipan / beban langsung, penghapusan, dan pembaruan.
- Hanya
SUM
, COUNT
, AVG
, VARIANCE
, VARIANCE
, MIN
dan MAX
yang didukung untuk penyegaran cepat. COUNT(*)
harus ditentukan.- Fungsi agregat harus terjadi hanya sebagai bagian terluar dari ekspresi. Yaitu, agregat seperti
AVG(AVG(x))
atau AVG(x)
+ AVG(x)
tidak diperbolehkan. - Untuk setiap agregat seperti
AVG(expr)
, COUNT(expr)
harus ada. Oracle merekomendasikan agar SUM(expr)
dicantumkan. - Jika
VARIANCE(expr)
atau STDDEV(expr
) ditentukan, COUNT(expr)
dan SUM(expr)
harus ditentukan. Oracle merekomendasikan agar SUM(expr *expr)
ditentukan. - Kolom
SELECT
dalam kueri mendefinisikan tidak bisa menjadi ekspresi kompleks dengan kolom dari beberapa tabel dasar. Solusi yang mungkin untuk ini adalah dengan menggunakan tampilan terwujud bersarang. - Daftar
SELECT
harus mengandung semua kolom GROUP
BY
. - Tampilan terwujud tidak didasarkan pada satu atau beberapa tabel jarak jauh.
- Jika Anda menggunakan tipe data
CHAR
di kolom filter log tampilan terwujud, set karakter situs master dan tampilan terwujud harus sama. - Jika tampilan terwujud memiliki salah satu dari berikut ini, maka penyegaran cepat hanya didukung pada sisipan DML konvensional dan beban langsung.
- Tampilan
MIN
dengan agregat MIN
atau MAX
- Tampilan
SUM(expr)
yang memiliki SUM(expr)
tetapi tidak ada COUNT(expr)
- Tampilan
COUNT(*)
tanpa COUNT(*)
Pandangan terwujud semacam itu disebut pandangan terwujud hanya sisipan. - Tampilan terwujud dengan
MAX
atau MIN
cepat disegarkan setelah menghapus atau mencampur pernyataan DML jika tidak memiliki klausa WHERE
.
Penyegaran cepat maks / mnt setelah penghapusan atau DML campuran tidak memiliki perilaku yang sama dengan kasus khusus penyisipan. Ini menghapus dan menghitung ulang nilai maks / min untuk grup yang terpengaruh. Anda harus menyadari dampak kinerjanya. - Tampilan terwujud dengan tampilan bernama atau subqueries dalam klausa
FROM
dapat disegarkan dengan cepat asalkan pandangan dapat sepenuhnya digabungkan. Untuk informasi tentang pandangan mana yang akan digabung, lihat Oracle Database SQL Language Reference . - Jika tidak ada gabungan luar, Anda mungkin memiliki pilihan dan bergabung sewenang-wenang dalam klausa
WHERE
. - Tampilan agregat terwujud dengan sambungan luar cepat disegarkan setelah DML konvensional dan beban langsung, asalkan hanya tabel luar yang telah dimodifikasi. Juga, batasan unik harus ada pada kolom gabungan dari tabel gabungan dalam. Jika ada gabungan luar, semua gabungan harus dihubungkan oleh
AND
dan harus menggunakan operator kesetaraan ( =
). - Untuk tampilan terwujud dengan
CUBE
, ROLLUP
, kumpulan pengelompokan, atau gabungannya, batasan berikut ini berlaku:
- Daftar
SELECT
harus berisi pengelompokan pengelompokan yang dapat berupa fungsi GROUPING_ID
pada semua fungsi GROUP
BY
expressions atau GROUPING
untuk setiap ekspresi GROUP
BY
. Misalnya, jika klausa GROUP
BY
dari tampilan material adalah " GROUP
BY
CUBE(a, b)
", maka daftar SELECT
harus mengandung " GROUPING_ID(a, b)
" atau " GROUPING(a)
AND
GROUPING(b)
"agar tampilan terwujud menjadi cepat disegarkan. GROUP
BY
tidak boleh menghasilkan pengelompokan duplikat. Misalnya, " GROUP BY a, ROLLUP(a, b)
" tidak dapat disegarkan dengan cepat karena menghasilkan pengelompokan duplikat " (a), (a, b), AND (a)
".
5.3.8.7 Pembatasan pada Refresh Cepat pada Tampilan Terwujud dengan UNION ALL
Pandangan UNION
set UNION
ALL
operator mendukung opsi REFRESH
FAST
jika kondisi berikut dipenuhi:
- Permintaan yang menentukan harus memiliki operator
UNION
ALL
di tingkat atas.
Operator UNION
ALL
tidak dapat disematkan di dalam subquery, dengan satu pengecualian: UNION
ALL
dapat berada di subquery dalam klausa FROM
asalkan kueri pendefinisiannya adalah dari bentuk SELECT * FROM
(lihat atau subquery dengan UNION
ALL
) seperti berikut ini. contoh:
CREATE VIEW view_with_unionall AS
(PILIH c.rowid crid, c.cust_id, 2 umarker
DARI pelanggan c MANA c.cust_last_name = 'Smith'
UNION ALL
SELECT c.rowid crid, c.cust_id, 3 umarker
DARI pelanggan c MANA c.cust_last_name = 'Jones');
BUAT TAMPILAN MATERIALISASI unionall_inside_view_mv
REFRESH CEPAT PADA PERMINTAAN SEBAGAI
SELECT * FROM view_with_unionall;
Perhatikan bahwa view view_with_unionall
memenuhi persyaratan untuk refresh cepat. - Setiap blok permintaan dalam
UNION
ALL
query harus memenuhi persyaratan tampilan terwujud cepat dengan agregat atau tampilan cepat terwujud dengan bergabung.
Log tampilan terwujud yang sesuai harus dibuat pada tabel seperti yang diperlukan untuk jenis tampilan terwujud cepat yang dapat disegarkan.
Perhatikan bahwa Oracle Database juga memungkinkan kasus khusus dari tampilan satu tabel terwujud dengan bergabung hanya jika kolom ROWID
telah dimasukkan dalam daftar SELECT
dan dalam log tampilan terwujud. Ini ditunjukkan dalam permintaan mendefinisikan view view_with_unionall
. - Daftar
SELECT
dari setiap kueri harus menyertakan penanda UNION
ALL
, dan kolom UNION
ALL
harus memiliki nilai numerik atau string konstan yang berbeda di setiap cabang UNION
ALL
. Selanjutnya, kolom penanda harus muncul di posisi ordinal yang sama di daftar SELECT
dari setiap blok permintaan. Lihat " UNION ALL Marker dan Query Rewrite " untuk informasi lebih lanjut mengenai UNION
ALL
marker. - Beberapa fitur seperti gabungan luar, permintaan tampilan teragregasi hanya menyisipkan agregat dan tabel jarak jauh tidak didukung untuk tampilan terwujud dengan
UNION
ALL
. Perhatikan, bagaimanapun, bahwa pandangan terwujud yang digunakan dalam replikasi, yang tidak mengandung gabungan atau agregat, dapat dengan cepat di-refresh ketika UNION
ALL
atau tabel jarak jauh digunakan. - Parameter inisialisasi kompatibilitas harus diatur ke 9.2.0 atau lebih tinggi untuk membuat tampilan terwujud yang cepat di-refresh dengan
UNION
ALL
.
Saya tidak ingin menyinggung penggemar Oracle, tetapi menilai dari daftar keterbatasan mereka, tampaknya mekanisme ini tidak ditulis dalam kasus umum menggunakan beberapa jenis model, tetapi ribuan orang India, di mana setiap orang diizinkan untuk menulis utas mereka sendiri, dan masing-masing dari mereka bisa dan lakukan. Menggunakan mekanisme ini untuk logika nyata seperti berjalan di ladang ranjau. Kapan saja, Anda bisa mendapatkan tambang, mengenai salah satu batasan yang tidak jelas. Bagaimana ini bekerja juga merupakan masalah yang terpisah, tetapi di luar ruang lingkup artikel ini.
Microsoft SQL ServerPersyaratan tambahan
Selain opsi SET dan persyaratan fungsi deterministik, persyaratan berikut harus dipenuhi:
- Pengguna yang menjalankan
CREATE INDEX
harus menjadi pemilik tampilan. - Saat Anda membuat indeks, opsi
IGNORE_DUP_KEY
harus disetel ke OFF (pengaturan default). - Tabel harus direferensikan dengan nama dua bagian, skema . tablename dalam definisi tampilan.
- Fungsi yang ditentukan pengguna yang dirujuk dalam tampilan harus dibuat dengan menggunakan opsi
WITH SCHEMABINDING
. - Setiap fungsi yang ditentukan pengguna yang dirujuk dalam tampilan harus direferensikan dengan nama dua bagian, <schema> . <fungsi> .
- Properti akses data dari fungsi yang ditentukan pengguna harus
NO SQL
, dan properti akses eksternal harus NO
. - Fungsi runtime bahasa umum (CLR) dapat muncul dalam daftar pilih tampilan, tetapi tidak dapat menjadi bagian dari definisi kunci indeks berkerumun. Fungsi CLR tidak dapat muncul dalam klausa WHERE tampilan atau klausa ON operasi JOIN dalam tampilan.
- Fungsi dan metode CLR tipe CLR yang ditentukan pengguna yang digunakan dalam definisi tampilan harus memiliki properti yang ditetapkan seperti yang ditunjukkan pada tabel berikut.
- Tampilan harus dibuat dengan menggunakan opsi
WITH SCHEMABINDING
. - Tampilan harus merujuk hanya tabel dasar yang ada dalam database yang sama dengan tampilan. Tampilan tidak dapat merujuk tampilan lain.
- Pernyataan SELECT dalam definisi tampilan tidak boleh mengandung elemen Transact-SQL berikut:
1 Tampilan yang diindeks dapat berisi kolom float ; Namun, kolom tersebut tidak dapat dimasukkan dalam kunci indeks berkerumun. - Jika
GROUP BY
ada, definisi VIEW harus mengandung COUNT_BIG(*)
dan tidak boleh mengandung HAVING
. Batasan GROUP BY
ini hanya berlaku untuk definisi tampilan yang diindeks. Kueri dapat menggunakan tampilan yang diindeks dalam rencana pelaksanaannya bahkan jika itu tidak memenuhi batasan GROUP BY
. - Jika definisi tampilan berisi klausa
GROUP BY
, kunci indeks berkerumun unik hanya dapat merujuk kolom yang ditentukan dalam klausa GROUP BY
.
Di sini Anda dapat melihat bahwa orang India tidak tertarik, karena mereka memutuskan untuk melakukan sesuai dengan skema "kita akan berbuat sedikit, tetapi baik." Artinya, mereka memiliki lebih banyak ranjau di lapangan, tetapi lokasi mereka lebih transparan. Hal yang paling menyedihkan adalah batasan ini:
Tampilan harus merujuk hanya tabel dasar yang ada dalam database yang sama dengan tampilan. Tampilan tidak dapat merujuk tampilan lain.
Dalam terminologi kami, ini berarti bahwa suatu fungsi tidak dapat mengakses fungsi terwujud lainnya. Ini memotong seluruh ideologi sejak awal.
Juga, batasan ini (dan selanjutnya dalam teks) sangat mengurangi kasus penggunaan:
Pernyataan SELECT dalam definisi tampilan tidak boleh mengandung elemen Transact-SQL berikut:
GABUNG LUAR, UNION, ORDER OLEH, dan lainnya dilarang. Mungkin lebih mudah untuk menunjukkan apa yang bisa digunakan daripada apa yang tidak. Daftarnya mungkin jauh lebih kecil.
Untuk meringkas: satu set besar pembatasan di masing-masing (saya perhatikan komersial) DBMS vs tidak ada (dengan pengecualian satu logis daripada teknis) dalam teknologi LGPL. Namun, perlu dicatat bahwa menerapkan mekanisme ini dalam logika relasional agak lebih rumit daripada fungsional yang dijelaskan.
Implementasi
Bagaimana cara kerjanya? PostgreSQL digunakan sebagai "mesin virtual". Di dalamnya ada algoritma kompleks yang membangun kueri. Ini
kode sumbernya . Dan tidak hanya ada satu set heuristik dengan sekelompok seandainya. Jadi, jika Anda memiliki beberapa bulan untuk belajar, maka Anda dapat mencoba memahami arsitekturnya.
Apakah ini bekerja secara efisien? Cukup efektif. Sayangnya, membuktikan ini sulit. Saya hanya bisa mengatakan bahwa jika Anda mempertimbangkan ribuan permintaan yang ada dalam aplikasi besar, maka secara rata-rata permintaan itu lebih efektif daripada pengembang yang baik. Seorang programmer SQL yang sangat baik dapat menulis permintaan apa pun dengan lebih efisien, tetapi dengan ribuan pertanyaan, ia tidak akan memiliki motivasi atau waktu untuk melakukan ini. Satu-satunya hal yang dapat saya berikan sebagai bukti keefektifan adalah bahwa berdasarkan platform yang dibangun pada DBMS ini, beberapa proyek
sistem ERP bekerja di mana terdapat ribuan fungsi MATERIALISASI yang berbeda, dengan ribuan pengguna dan basis data terrabyte dengan ratusan juta catatan yang berfungsi pada server prosesor ganda biasa. Namun, siapa pun dapat menguji / menyangkal keefektifannya dengan mengunduh
platform dan PostgreSQL,
mengaktifkan pencatatan query SQL dan mencoba mengubah logika dan data di sana.
Dalam artikel berikut, saya juga akan berbicara tentang bagaimana Anda dapat menggantung pembatasan pada fungsi, bekerja dengan sesi perubahan, dan banyak lagi.