Menyeimbangkan penulisan dan pembacaan dalam database

Menyeimbangkan penulisan dan pembacaan dalam database
Di sebelumnya Artikel Saya menjelaskan konsep dan implementasi database yang dibangun berdasarkan fungsi, bukan tabel dan bidang seperti pada database relasional. Laporan ini memberikan banyak contoh yang menunjukkan keunggulan pendekatan ini dibandingkan pendekatan klasik. Banyak yang menganggapnya tidak cukup meyakinkan.

Pada artikel ini, saya akan menunjukkan bagaimana konsep ini memungkinkan Anda dengan cepat dan mudah menyeimbangkan penulisan dan pembacaan ke database tanpa perubahan apa pun dalam logika pengoperasian. Fungsi serupa telah dicoba untuk diterapkan dalam DBMS komersial modern (khususnya Oracle dan Microsoft SQL Server). Di akhir artikel saya akan menunjukkan bahwa apa yang mereka lakukan, secara halus, tidak berjalan dengan baik.

ОписаниС

Seperti sebelumnya, untuk pemahaman yang lebih baik saya akan memulai uraian dengan contoh. Katakanlah 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:

CLASS Department β€˜ΠžΡ‚дСл’;
name β€˜ΠΠ°ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½ΠΈΠ΅β€™ = DATA STRING[100] (Department);

CLASS Employee β€˜Π‘отрудник’;
department β€˜ΠžΡ‚дСл’ = DATA Department (Employee);
salary β€˜Π—арплата’ =  DATA NUMERIC[10,2] (Employee);

countEmployees β€˜ΠšΠΎΠ»-Π²ΠΎ ΡΠΎΡ‚рудников’ (Department d) = 
    GROUP SUM 1 IF department(Employee e) = d;
salarySum β€˜Π‘уммарная Π·Π°Ρ€ΠΏΠ»Π°Ρ‚а’ (Department d) = 
    GROUP SUM salary(Employee e) IF department(e) = d;

SELECT name(Department d), countEmployees(d), salarySum(d);

Kompleksitas menjalankan kueri ini di DBMS mana pun akan setara O(jumlah karyawan)karena perhitungan ini memerlukan pemindaian seluruh tabel karyawan dan kemudian mengelompokkannya berdasarkan departemen. Juga akan ada tambahan kecil (kami yakin jumlah karyawan lebih banyak daripada departemen) tergantung pada paket yang dipilih O(catat jumlah karyawan) ΠΈΠ»ΠΈ O(jumlah departemen) untuk pengelompokan dan sebagainya.

Jelas bahwa overhead eksekusi mungkin berbeda di DBMS yang berbeda, tetapi kompleksitasnya tidak akan berubah sama sekali.

Dalam implementasi yang diusulkan, DBMS fungsional akan menghasilkan satu subquery yang akan menghitung nilai yang diperlukan untuk departemen tersebut, dan kemudian membuat GABUNG dengan tabel departemen untuk mendapatkan nama. Namun, untuk setiap fungsi, saat mendeklarasikan, dimungkinkan untuk menyetel penanda MATERIALIZED khusus. Sistem akan secara otomatis membuat kolom yang sesuai untuk setiap fungsi tersebut. Saat mengubah nilai suatu fungsi, nilai bidang juga akan berubah dalam transaksi yang sama. Saat mengakses fungsi ini, bidang yang telah dihitung sebelumnya akan diakses.

Khususnya, jika Anda menyetel MATERIALIZED untuk fungsi menghitungKaryawan ΠΈ jumlah gaji, kemudian dua kolom akan ditambahkan ke tabel dengan daftar departemen, yang akan menyimpan jumlah karyawan dan total gaji mereka. Setiap kali ada perubahan pada karyawan, gaji, atau afiliasi departemennya, sistem akan secara otomatis mengubah nilai kolom tersebut. Kueri di atas akan mengakses bidang ini secara langsung dan akan dieksekusi O(jumlah departemen).

Apa saja batasannya? Hanya satu hal: fungsi seperti itu harus memiliki sejumlah nilai masukan yang terbatas yang nilainya ditentukan. Jika tidak, tidak mungkin membuat tabel yang menyimpan semua nilainya, karena tidak mungkin ada tabel dengan jumlah baris yang tidak terbatas.

Contoh:

employeesCount β€˜ΠšΠΎΠ»ΠΈΡ‡Π΅ΡΡ‚Π²ΠΎ ΡΠΎΡ‚Ρ€ΡƒΠ΄Π½ΠΈΠΊΠΎΠ² Ρ Π·Π°Ρ€ΠΏΠ»Π°Ρ‚ΠΎΠΉ > N’ (Department d, NUMERIC[10,2] N) = 
    GROUP SUM salary(Employee e) IF department(e) = d AND salary(e) > N;

Fungsi ini didefinisikan untuk jumlah nilai N yang tak terhingga (misalnya, nilai negatif apa pun bisa digunakan). Oleh karena itu, Anda tidak dapat menempatkan MATERIALIZED di atasnya. Jadi ini adalah batasan logis, bukan batasan teknis (yaitu, bukan karena kami tidak dapat menerapkannya). Jika tidak, tidak ada batasan. Anda dapat menggunakan pengelompokan, pengurutan, AND dan OR, PARTITION, rekursi, dll.

Misalnya, pada soal 2.2 artikel sebelumnya, Anda dapat meletakkan MATERIALIZED pada kedua fungsi:

bought 'ΠšΡƒΠΏΠΈΠ»' (Customer c, Product p, INTEGER y) = 
    GROUP SUM sum(Detail d) IF 
        customer(order(d)) = c AND 
        product(d) = p AND 
        extractYear(date(order(d))) = y MATERIALIZED;
rating 'Π Π΅ΠΉΡ‚ΠΈΠ½Π³' (Customer c, Product p, INTEGER y) = 
    PARTITION SUM 1 ORDER DESC bought(c, p, y), p BY c, y MATERIALIZED;
SELECT contactName(Customer c), name(Product p) WHERE rating(c, p, 1997) < 3;

Sistem itu sendiri akan membuat satu tabel dengan kunci tipe Pelanggan, Produk ΠΈ BILANGAN BULAT, akan menambahkan dua bidang ke dalamnya dan akan memperbarui nilai bidang di dalamnya dengan perubahan apa pun. Ketika panggilan lebih lanjut ke fungsi-fungsi ini dilakukan, fungsi-fungsi tersebut tidak akan dihitung, melainkan nilainya akan dibaca dari bidang terkait.

Dengan menggunakan mekanisme ini, Anda dapat, misalnya, menghilangkan rekursi (CTE) dalam kueri. Secara khusus, pertimbangkan grup yang membentuk pohon menggunakan hubungan anak/induk (setiap grup memiliki tautan ke induknya):

parent = DATA Group (Group);

Dalam database fungsional, logika rekursi dapat ditentukan sebagai berikut:

level (Group child, Group parent) = RECURSION 1l IF child IS Group AND parent == child
                                                             STEP 2l IF parent == parent($parent);
isParent (Group child, Group parent) = TRUE IF level(child, parent) MATERIALIZED;

Karena untuk fungsinya adalah orang tua ditandai MATERIALISASI, maka tabel dengan dua kunci (grup) akan dibuat untuk itu, di mana bidangnya adalah orang tua akan benar hanya jika kunci pertama adalah turunan dari kunci kedua. Jumlah entri dalam tabel ini akan sama dengan jumlah kelompok dikalikan dengan rata-rata kedalaman pohon. Jika Anda perlu, misalnya, menghitung jumlah keturunan suatu grup tertentu, Anda dapat menggunakan fungsi ini:

childrenCount (Group g) = GROUP SUM 1 IF isParent(Group child, g);

Tidak akan ada CTE dalam kueri SQL. Sebaliknya akan ada GROUP BY yang sederhana.

Dengan menggunakan mekanisme ini, Anda juga dapat dengan mudah mendenormalisasi database jika diperlukan:

CLASS Order 'Π—Π°ΠΊΠ°Π·';
date 'Π”Π°Ρ‚Π°' = DATA DATE (Order);

CLASS OrderDetail 'Π‘Ρ‚Ρ€ΠΎΠΊΠ° Π·Π°ΠΊΠ°Π·Π°';
order 'Π—Π°ΠΊΠ°Π·' = DATA Order (OrderDetail);
date 'Π”Π°Ρ‚Π°' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;

Saat memanggil suatu fungsi tanggal untuk garis pesanan, bidang yang ada indeksnya akan dibaca dari tabel dengan garis pesanan. Ketika tanggal pemesanan berubah, sistem akan secara otomatis menghitung ulang tanggal denormalisasi di baris.

Keuntungan

Untuk apa seluruh mekanisme ini? Dalam DBMS klasik, tanpa menulis ulang kueri, pengembang atau DBA hanya dapat mengubah indeks, menentukan statistik, dan memberi tahu perencana kueri cara menjalankannya (dan PETUNJUK hanya tersedia di DBMS komersial). Tidak peduli seberapa keras mereka mencoba, mereka tidak akan dapat menyelesaikan kueri pertama dalam artikel tersebut O (jumlah departemen) tanpa mengubah kueri atau menambahkan 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 dalam pengoperasian.

Dalam prakteknya terlihat seperti ini. Beberapa orang mengembangkan logika secara langsung berdasarkan tugas yang ada. Mereka tidak memahami algoritme dan kompleksitasnya, rencana eksekusi, jenis gabungan, atau komponen teknis lainnya. Orang-orang ini lebih merupakan analis bisnis daripada pengembang. Kemudian, semua ini dimasukkan ke dalam pengujian atau pengoperasian. Mengaktifkan pencatatan kueri yang sudah berjalan lama. Ketika kueri panjang terdeteksi, maka orang lain (lebih teknis - pada dasarnya DBA) memutuskan untuk mengaktifkan MATERIALIZED pada beberapa fungsi perantara. Ini sedikit memperlambat pencatatan (karena memerlukan pembaruan bidang tambahan dalam transaksi). Namun, tidak hanya kueri ini yang dipercepat secara signifikan, tetapi juga semua kueri lain yang menggunakan fungsi ini. Pada saat yang sama, memutuskan fungsi mana yang akan diwujudkan relatif mudah. Dua parameter utama: jumlah nilai input yang mungkin (ini adalah jumlah record yang akan ada di tabel terkait), dan seberapa sering digunakan dalam fungsi lain.

Analoginya

DBMS komersial modern memiliki mekanisme serupa: MATERIALIZED VIEW dengan FAST REFRESH (Oracle) dan INDEXED VIEW (Microsoft SQL Server). Di PostgreSQL, MATERIALIZED VIEW tidak dapat diperbarui dalam suatu transaksi, tetapi hanya berdasarkan permintaan (dan bahkan dengan batasan yang sangat ketat), jadi kami tidak mempertimbangkannya. Namun mereka mempunyai beberapa masalah yang secara signifikan membatasi penggunaannya.

Pertama, Anda hanya dapat mengaktifkan materialisasi jika Anda telah membuat VIEW 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, namun setidaknya tidak efektif jika ada data tertentu yang sudah dihitung sebelumnya, namun banyak query yang tidak selalu menggunakannya, melainkan menghitung ulang.

Kedua, mereka memiliki banyak batasan:

Peramal

5.3.8.4 Batasan Umum pada Fast Refresh

Kueri yang menentukan tampilan terwujud dibatasi sebagai berikut:

  • Tampilan yang terwujud tidak boleh mengandung referensi ke ekspresi yang tidak berulang seperti SYSDATE dan ROWNUM.
  • Pandangan yang terwujud tidak boleh mengandung referensi ke RAW or LONG RAW tipe data.
  • Tidak boleh memuat a SELECT daftar subkueri.
  • Itu tidak boleh berisi fungsi analitis (misalnya, RANK) Di SELECT ayat.
  • Itu tidak bisa mereferensikan tabel di mana an XMLIndex indeks ditentukan.
  • Tidak boleh memuat a MODEL ayat.
  • Tidak boleh memuat a HAVING klausa dengan subquery.
  • Itu tidak dapat berisi kueri bersarang yang memiliki ANY, ALL, atau NOT EXISTS.
  • Tidak boleh memuat a [START WITH …] CONNECT BY ayat.
  • Itu tidak boleh berisi beberapa tabel detail di situs berbeda.
  • ON COMMIT tampilan terwujud tidak dapat memiliki tabel detail jarak jauh.
  • Tampilan material yang disarangkan harus memiliki gabungan atau agregat.
  • Tampilan gabungan yang terwujud dan tampilan agregat yang terwujud dengan a GROUP BY klausa tidak dapat memilih dari tabel yang disusun berdasarkan indeks.

5.3.8.5 Pembatasan Penyegaran Cepat pada Tampilan Terwujud dengan Hanya Gabungan

Mendefinisikan kueri untuk tampilan terwujud dengan gabungan saja dan tanpa agregat memiliki batasan pada penyegaran cepat berikut:

  • Semua batasan dari Β«Batasan Umum pada Penyegaran Cepat".
  • Mereka tidak bisa memilikinya GROUP BY klausa atau agregat.
  • Rowids dari semua tabel di FROM daftar harus muncul di SELECT daftar kueri.
  • Log tampilan yang terwujud harus ada dengan baris untuk semua tabel dasar di FROM daftar kueri.
  • Anda tidak dapat membuat tampilan terwujud yang dapat disegarkan dengan cepat dari beberapa tabel dengan gabungan sederhana yang menyertakan kolom tipe objek di dalamnya SELECT pernyataan.

Selain itu, metode penyegaran yang Anda pilih tidak akan efisien secara optimal jika:

  • Kueri yang menentukan menggunakan gabungan luar yang berperilaku seperti gabungan dalam. Jika kueri penentu berisi gabungan seperti itu, pertimbangkan untuk menulis ulang kueri penentu untuk memuat gabungan dalam.
  • Grafik SELECT daftar tampilan terwujud berisi ekspresi pada kolom dari beberapa tabel.

5.3.8.6 Pembatasan Penyegaran Cepat pada Tampilan Terwujud dengan Agregat

Mendefinisikan kueri untuk tampilan terwujud dengan agregat atau gabungan memiliki batasan penyegaran cepat berikut:

Penyegaran cepat didukung untuk keduanya ON COMMIT dan ON DEMAND pandangan yang terwujud, namun batasan berikut ini berlaku:

  • Semua tabel dalam tampilan materialisasi harus memiliki log tampilan materialisasi, dan log tampilan materialisasi harus:
    • Berisi semua kolom dari tabel yang direferensikan dalam tampilan terwujud.
    • Tentukan dengan ROWID dan INCLUDING NEW VALUES.
    • Tentukan SEQUENCE klausa jika tabel diharapkan memiliki campuran penyisipan/pemuatan langsung, penghapusan, dan pembaruan.

  • Hanya SUM, COUNT, AVG, STDDEV, VARIANCE, MIN dan MAX didukung untuk penyegaran cepat.
  • COUNT(*) harus ditentukan.
  • Fungsi agregat harus muncul hanya pada bagian terluar dari ekspresi. Artinya, agregat seperti AVG(AVG(x)) or AVG(x)+ AVG(x) tidak diizinkan.
  • Untuk setiap agregat seperti AVG(expr), yang sesuai COUNT(expr) harus hadir. Oracle merekomendasikan hal itu SUM(expr) ditentukan.
  • If VARIANCE(expr) or STDDEV(expr) ditentukan, COUNT(expr) dan SUM(expr) harus ditentukan. Oracle merekomendasikan hal itu SUM(expr *expr) ditentukan.
  • Grafik SELECT kolom dalam kueri penentu tidak boleh berupa ekspresi kompleks dengan kolom dari beberapa tabel dasar. Solusi yang mungkin untuk mengatasi hal ini adalah dengan menggunakan tampilan materialisasi bersarang.
  • Grafik SELECT daftar harus berisi semua GROUP BY kolom.
  • Tampilan terwujud tidak didasarkan pada satu atau lebih tabel jarak jauh.
  • Jika Anda menggunakan CHAR tipe data di kolom filter log tampilan material, kumpulan karakter situs master dan tampilan material harus sama.
  • Jika tampilan terwujud memiliki salah satu hal berikut, maka penyegaran cepat hanya didukung pada penyisipan DML konvensional dan pemuatan langsung.
    • Pandangan terwujud dengan MIN or MAX agregat
    • Pandangan terwujud yang dimiliki SUM(expr) tapi tidak COUNT(expr)
    • Pandangan terwujud tanpa COUNT(*)

    Pandangan yang terwujud seperti itu disebut pandangan yang terwujud hanya sisipkan.

  • Pandangan terwujud dengan MAX or MIN dapat disegarkan dengan cepat setelah menghapus atau mencampurkan pernyataan DML jika tidak memiliki a WHERE ayat.
    Penyegaran cepat maks/mnt setelah penghapusan atau DML campuran tidak memiliki perilaku yang sama dengan kasus penyisipan saja. Ini menghapus dan menghitung ulang nilai maks/min untuk grup yang terpengaruh. Anda perlu menyadari dampak kinerjanya.
  • Tampilan terwujud dengan tampilan atau subkueri bernama di FROM klausa dapat dengan cepat disegarkan asalkan tampilan dapat digabungkan sepenuhnya. Untuk informasi tentang tampilan mana yang akan digabungkan, lihat Referensi Bahasa SQL Database Oracle.
  • Jika tidak ada gabungan luar, Anda mungkin memiliki pilihan dan gabungan sewenang-wenang di dalam WHERE ayat.
  • Tampilan agregat yang terwujud dengan gabungan luar dapat disegarkan dengan cepat setelah DML konvensional dan pemuatan langsung, asalkan hanya tabel luar yang dimodifikasi. Selain itu, batasan unik harus ada pada kolom gabungan pada tabel gabungan dalam. Jika terdapat gabungan luar, maka semua gabungan tersebut harus dihubungkan oleh ANDs dan harus menggunakan persamaan (=) operator.
  • Untuk pandangan terwujud dengan CUBE, ROLLUP, kumpulan pengelompokan, atau penggabungannya, batasan berikut berlaku:
    • Grafik SELECT daftar harus berisi pembeda pengelompokan yang dapat berupa a GROUPING_ID berfungsi pada semua GROUP BY ekspresi atau GROUPING berfungsi satu untuk masing-masing GROUP BY ekspresi. Misalnya, jika GROUP BY klausa dari pandangan yang terwujud adalah "GROUP BY CUBE(a, b)", lalu SELECT daftar harus berisi "GROUPING_ID(a, b)" atau "GROUPING(a) AND GROUPING(b)Β» agar tampilan yang terwujud dapat disegarkan dengan cepat.
    • 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 Penyegaran Cepat pada Pandangan Terwujud dengan UNION ALL

Pandangan terwujud dengan UNION ALL set dukungan operator REFRESH FAST pilihan jika kondisi berikut dipenuhi:

  • Kueri yang menentukan harus memiliki UNION ALL operator di tingkat atas.

    Grafik UNION ALL Operator tidak dapat disematkan di dalam subquery, dengan satu pengecualian: The UNION ALL bisa di subquery di FROM klausa asalkan kueri yang menentukan berbentuk SELECT * FROM (lihat atau subkueri dengan UNION ALL) seperti pada contoh berikut:

    BUAT LIHAT view_with_unionall AS (PILIH c.rowid crid, c.cust_id, 2 umarker FROM pelanggan c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM pelanggan c WHERE c.cust_last_name = 'Jones'); BUAT TAMPILAN TERMATERI unionall_inside_view_mv REFRESH CEPAT SESUAI PERMINTAAN SEBAGAI PILIH * DARI view_with_unionall;
    

    Perhatikan bahwa pandangan view_with_unionall memenuhi persyaratan untuk penyegaran cepat.

  • Setiap blok kueri di UNION ALL kueri harus memenuhi persyaratan tampilan terwujud yang dapat disegarkan dengan cepat dengan agregat atau tampilan terwujud yang dapat disegarkan dengan cepat dengan gabungan.

    Log tampilan materialisasi yang sesuai harus dibuat pada tabel sebagaimana diperlukan untuk jenis tampilan materialisasi cepat yang dapat disegarkan.
    Perhatikan bahwa Oracle Database juga mengizinkan kasus khusus dari tampilan tabel tunggal yang terwujud dengan gabungan hanya disediakan ROWID kolom telah dimasukkan ke dalam SELECT daftar dan dalam log tampilan terwujud. Hal ini ditunjukkan dalam kueri penentu tampilan view_with_unionall.

  • Grafik SELECT daftar setiap kueri harus menyertakan a UNION ALL penanda, dan UNION ALL kolom harus memiliki nilai numerik atau string konstan yang berbeda di setiap kolom UNION ALL cabang. Selanjutnya, kolom penanda harus muncul pada posisi ordinal yang sama di SELECT daftar setiap blok kueri. Melihat "UNION ALL Penanda dan Penulisan Ulang KueriΒ» untuk informasi lebih lanjut mengenai UNION ALL spidol.
  • Beberapa fitur seperti gabungan luar, kueri tampilan materialisasi agregat hanya penyisipan, dan tabel jarak jauh tidak didukung untuk tampilan materialisasi UNION ALL. Namun perlu diperhatikan bahwa tampilan material yang digunakan dalam replikasi, yang tidak berisi gabungan atau agregat, dapat disegarkan dengan cepat 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 dapat disegarkan dengan cepat UNION ALL.

Saya tidak ingin menyinggung penggemar Oracle, tetapi dilihat dari daftar batasan mereka, tampaknya mekanisme ini ditulis bukan dalam kasus umum, menggunakan semacam model, tetapi oleh ribuan orang India, di mana setiap orang diberi kesempatan untuk melakukannya. menulis cabang mereka sendiri, dan masing-masing dari mereka melakukan apa yang dia bisa. Menggunakan mekanisme ini untuk logika nyata seperti berjalan melewati ladang ranjau. Anda bisa mendapatkan tambang kapan saja dengan memenuhi salah satu batasan yang tidak jelas. Cara kerjanya juga merupakan pertanyaan terpisah, namun berada di luar cakupan artikel ini.

Microsoft SQL Server

Persyaratan tambahan

Selain opsi SET dan persyaratan fungsi deterministik, persyaratan berikut harus dipenuhi:

  • Pengguna yang mengeksekusi CREATE INDEX harus menjadi pemilik tampilan.
  • Saat Anda membuat indeks, IGNORE_DUP_KEY opsi harus disetel ke OFF (pengaturan default).
  • Tabel harus direferensikan dengan nama dua bagian, skema.nama tabel dalam definisi tampilan.
  • Fungsi yang ditentukan pengguna yang direferensikan dalam tampilan harus dibuat dengan menggunakan WITH SCHEMABINDING .
  • Setiap fungsi yang ditentukan pengguna yang direferensikan dalam tampilan harus direferensikan dengan nama dua bagian, ..
  • Properti akses data dari fungsi yang ditentukan pengguna harus berupa NO SQL, dan properti akses eksternal harus NO.
  • Fungsi runtime bahasa umum (CLR) dapat muncul dalam daftar pilihan tampilan, namun tidak dapat menjadi bagian dari definisi kunci indeks berkerumun. Fungsi CLR tidak dapat muncul dalam klausa WHERE pada tampilan atau klausa ON pada operasi GABUNG pada tampilan.
  • Fungsi CLR dan metode tipe yang ditentukan pengguna CLR yang digunakan dalam definisi tampilan harus memiliki properti yang ditetapkan seperti yang ditunjukkan dalam tabel berikut.

    Milik
    Note

    DETERMINISTIK = BENAR
    Harus dideklarasikan secara eksplisit sebagai atribut metode Microsoft .NET Framework.

    TEPAT = BENAR
    Harus dideklarasikan secara eksplisit sebagai atribut metode .NET Framework.

    AKSES DATA = TANPA SQL
    Ditentukan dengan menyetel atribut DataAccess ke DataAccessKind.None dan atribut SystemDataAccess ke SystemDataAccessKind.None.

    AKSES EKSTERNAL = TIDAK
    Properti ini defaultnya adalah NO untuk rutinitas CLR.

  • Tampilan harus dibuat dengan menggunakan WITH SCHEMABINDING .
  • Tampilan harus mereferensikan hanya tabel dasar yang berada dalam database yang sama dengan tampilan. Tampilan tidak dapat mereferensikan tampilan lain.
  • Pernyataan SELECT dalam definisi tampilan tidak boleh berisi elemen Transact-SQL berikut:

    COUNT
    fungsi ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, DAN OPENXML)
    OUTER bergabung (LEFT, RIGHT, atau FULL)

    Tabel turunan (ditentukan dengan menentukan a SELECT pernyataan di FROM ayat)
    Bergabung sendiri
    Menentukan kolom dengan menggunakan SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARP, atau AVG
    Ekspresi tabel umum (CTE)

    mengapung1, teks, nteks, gambar, XML, atau aliran file kolom
    Subkueri
    OVER klausa, yang mencakup fungsi jendela peringkat atau agregat

    Predikat teks lengkap (CONTAINS, FREETEXT)
    SUM fungsi yang mereferensikan ekspresi nullable
    ORDER BY

    Fungsi agregat yang ditentukan pengguna CLR
    TOP
    CUBE, ROLLUP, atau GROUPING SETS operator

    MIN, MAX
    UNION, EXCEPT, atau INTERSECT operator
    TABLESAMPLE

    Variabel tabel
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Kumpulan kolom jarang
    Fungsi bernilai tabel inline (TVF) atau multi-pernyataan (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Tampilan yang diindeks dapat berisi mengapung kolom; namun, kolom tersebut tidak dapat dimasukkan dalam kunci indeks berkerumun.

  • If GROUP BY hadir, definisi VIEW harus mengandung COUNT_BIG(*) dan tidak boleh mengandung HAVING. Ini GROUP BY pembatasan hanya berlaku untuk definisi tampilan yang diindeks. Kueri dapat menggunakan tampilan yang diindeks dalam rencana eksekusinya meskipun tidak memenuhi hal tersebut GROUP BY pembatasan.
  • Jika definisi tampilan berisi a GROUP BY klausa, kunci indeks berkerumun unik hanya dapat mereferensikan kolom yang ditentukan dalam GROUP BY ayat.

Jelas di sini bahwa orang-orang India tidak terlibat, karena mereka memutuskan untuk melakukannya sesuai dengan skema β€œkami tidak akan berbuat banyak, tapi baiklah.” Artinya, mereka memiliki lebih banyak ranjau di lapangan, namun lokasinya lebih transparan. Hal yang paling mengecewakan adalah batasan ini:

Tampilan harus mereferensikan hanya tabel dasar yang berada dalam database yang sama dengan tampilan. Tampilan tidak dapat mereferensikan tampilan lain.

Dalam terminologi kami, ini berarti suatu fungsi tidak dapat mengakses fungsi material lainnya. Hal ini menghancurkan semua ideologi sejak awal.
Selain itu, batasan ini (dan selanjutnya dalam teks) sangat mengurangi kasus penggunaan:

Pernyataan SELECT dalam definisi tampilan tidak boleh berisi elemen Transact-SQL berikut:

COUNT
fungsi ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, DAN OPENXML)
OUTER bergabung (LEFT, RIGHT, atau FULL)

Tabel turunan (ditentukan dengan menentukan a SELECT pernyataan di FROM ayat)
Bergabung sendiri
Menentukan kolom dengan menggunakan SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARP, atau AVG
Ekspresi tabel umum (CTE)

mengapung1, teks, nteks, gambar, XML, atau aliran file kolom
Subkueri
OVER klausa, yang mencakup fungsi jendela peringkat atau agregat

Predikat teks lengkap (CONTAINS, FREETEXT)
SUM fungsi yang mereferensikan ekspresi nullable
ORDER BY

Fungsi agregat yang ditentukan pengguna CLR
TOP
CUBE, ROLLUP, atau GROUPING SETS operator

MIN, MAX
UNION, EXCEPT, atau INTERSECT operator
TABLESAMPLE

Variabel tabel
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Kumpulan kolom jarang
Fungsi bernilai tabel inline (TVF) atau multi-pernyataan (MSTVF)
OFFSET

CHECKSUM_AGG

OUTER JOINS, UNION, ORDER BY dan lain-lain dilarang. Mungkin akan lebih mudah untuk menentukan apa yang bisa digunakan daripada apa yang tidak bisa digunakan. Daftarnya mungkin jauh lebih pendek.

Ringkasnya: sejumlah besar batasan di setiap DBMS (perhatikan komersial) vs tidak ada batasan sama sekali (dengan pengecualian satu logika, bukan teknis) dalam teknologi LGPL. Namun, perlu dicatat bahwa penerapan mekanisme ini dalam logika relasional agak lebih sulit daripada logika fungsional yang dijelaskan.

Implementasi

Bagaimana itu bekerja? PostgreSQL digunakan sebagai "mesin virtual". Ada algoritma kompleks di dalamnya yang membangun kueri. Di Sini sumber. Dan yang ada bukan sekadar sekumpulan besar heuristik dengan sekumpulan asumsi. Jadi, jika Anda punya waktu beberapa bulan untuk belajar, Anda bisa mencoba memahami arsitektur.

Apakah ini bekerja secara efektif? Cukup efektif. Sayangnya, hal ini sulit dibuktikan. Saya hanya bisa mengatakan bahwa jika Anda mempertimbangkan ribuan kueri yang ada di aplikasi besar, maka rata-rata kueri tersebut lebih efisien daripada kueri yang dimiliki pengembang yang baik. Seorang pemrogram SQL yang hebat dapat menulis kueri apa pun dengan lebih efisien, tetapi dengan seribu kueri, dia tidak memiliki motivasi atau waktu untuk melakukannya. Satu-satunya hal yang sekarang dapat saya kutip sebagai bukti keefektifannya adalah bahwa beberapa proyek sedang berjalan pada platform yang dibangun di atas DBMS ini sistem ERP, yang memiliki ribuan fungsi MATERIALISASI berbeda, dengan ribuan pengguna dan database terabyte dengan ratusan juta catatan yang berjalan pada server dua prosesor biasa. Namun, siapa pun dapat memeriksa/menyangkal keefektifannya dengan mengunduh Π°Ρ‚Ρ„ΠΎΡ€ΠΌΡƒ dan PostgreSQL, dihidupkan mencatat kueri SQL dan mencoba mengubah logika dan data di sana.

Dalam artikel berikut, saya juga akan membahas tentang bagaimana Anda dapat mengatur batasan fungsi, bekerja dengan sesi perubahan, dan banyak lagi.

Sumber: www.habr.com

Tambah komentar