Mengimbangi menulis dan membaca dalam pangkalan data
Dalam sebelumnya artikel Saya menerangkan konsep dan pelaksanaan pangkalan data yang dibina berdasarkan fungsi, bukannya jadual dan medan seperti dalam pangkalan data hubungan. Ia memberikan banyak contoh yang menunjukkan kelebihan pendekatan ini berbanding pendekatan klasik. Ramai mendapati mereka tidak cukup meyakinkan.
Dalam artikel ini, saya akan menunjukkan bagaimana konsep ini membolehkan anda mengimbangi penulisan dan membaca dengan cepat dan mudah ke pangkalan data tanpa sebarang perubahan dalam logik operasi. Fungsi yang serupa telah cuba dilaksanakan dalam DBMS komersial moden (khususnya, Oracle dan Microsoft SQL Server). Pada penghujung artikel saya akan menunjukkan bahawa apa yang mereka lakukan, secara sederhana, tidak berjaya dengan baik.
ΠΠΏΠΈΡΠ°Π½ΠΈΠ΅
Seperti sebelum ini, untuk pemahaman yang lebih baik saya akan memulakan penerangan dengan contoh. Katakan kita perlu melaksanakan logik yang akan mengembalikan senarai jabatan dengan bilangan pekerja di dalamnya dan jumlah gaji mereka.
Dalam pangkalan data berfungsi ia akan kelihatan 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;
Kerumitan melaksanakan pertanyaan ini dalam mana-mana DBMS akan bersamaan dengan O(bilangan pekerja)kerana pengiraan ini memerlukan pengimbasan keseluruhan jadual pekerja dan kemudian mengumpulkan mereka mengikut jabatan. Terdapat juga beberapa tambahan kecil (kami percaya terdapat lebih ramai pekerja daripada jabatan) bergantung pada pelan yang dipilih O(nombor log pekerja) atau O(bilangan jabatan) untuk berkumpulan dan sebagainya.
Adalah jelas bahawa overhed pelaksanaan mungkin berbeza dalam DBMS yang berbeza, tetapi kerumitan tidak akan berubah dalam apa jua cara.
Dalam pelaksanaan yang dicadangkan, DBMS berfungsi akan menjana satu subquery yang akan mengira nilai yang diperlukan untuk jabatan, dan kemudian membuat JOIN dengan jadual jabatan untuk mendapatkan nama. Walau bagaimanapun, untuk setiap fungsi, apabila mengisytiharkan, adalah mungkin untuk menetapkan penanda MATERIALIZED khas. Sistem secara automatik akan mencipta medan yang sepadan untuk setiap fungsi tersebut. Apabila menukar nilai fungsi, nilai medan juga akan berubah dalam transaksi yang sama. Apabila mengakses fungsi ini, medan pra-kira akan diakses.
Khususnya, jika anda menetapkan MATERIALIZED untuk fungsi kiraPekerja ΠΈ gajiSum, kemudian dua medan akan ditambah ke jadual dengan senarai jabatan, yang akan menyimpan bilangan pekerja dan jumlah gaji mereka. Setiap kali terdapat perubahan dalam pekerja, gaji atau gabungan jabatan mereka, sistem secara automatik akan menukar nilai bidang ini. Pertanyaan di atas akan mengakses medan ini secara langsung dan akan dilaksanakan dalam O(bilangan jabatan).
Apakah sekatan? Hanya satu perkara: fungsi sedemikian mesti mempunyai bilangan terhingga nilai input yang mana nilainya ditentukan. Jika tidak, adalah mustahil untuk membina jadual yang menyimpan semua nilainya, kerana tidak boleh ada jadual dengan bilangan baris yang tidak terhingga.
Contoh:
employeesCount βΠΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΡΠΎΡΡΡΠ΄Π½ΠΈΠΊΠΎΠ² Ρ Π·Π°ΡΠΏΠ»Π°ΡΠΎΠΉ > Nβ (Department d, NUMERIC[10,2] N) =
GROUP SUM salary(Employee e) IF department(e) = d AND salary(e) > N;
Fungsi ini ditakrifkan untuk bilangan nilai N yang tidak terhingga (contohnya, sebarang nilai negatif adalah sesuai). Oleh itu, anda tidak boleh meletakkan MATERIALIZED padanya. Jadi ini adalah batasan logik, bukan teknikal (iaitu, bukan kerana kami tidak dapat melaksanakannya). Jika tidak, tiada sekatan. Anda boleh menggunakan pengumpulan, pengisihan, DAN dan ATAU, PARTITION, rekursi, dsb.
Sebagai contoh, dalam masalah 2.2 artikel sebelumnya, anda boleh meletakkan MATERIALIZED pada kedua-dua 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 jadual dengan kekunci jenis Pelanggan, Produk ΠΈ INTEGER, akan menambah dua medan padanya dan akan mengemas kini nilai medan di dalamnya dengan sebarang perubahan. Apabila panggilan lanjut ke fungsi ini dibuat, ia tidak akan dikira, sebaliknya nilai akan dibaca dari medan yang sepadan.
Menggunakan mekanisme ini, anda boleh, sebagai contoh, menyingkirkan rekursi (CTE) dalam pertanyaan. Khususnya, pertimbangkan kumpulan yang membentuk pokok menggunakan perhubungan anak/ibu bapa (setiap kumpulan mempunyai pautan kepada induknya):
parent = DATA Group (Group);
Dalam pangkalan data berfungsi, logik rekursi boleh ditentukan seperti 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;
Sejak untuk fungsi isParent ditanda MATERIALIZED, maka jadual dengan dua kekunci (kumpulan) akan dibuat untuknya, di mana medan isParent akan benar hanya jika kunci pertama ialah anak kepada kunci kedua. Bilangan entri dalam jadual ini akan sama dengan bilangan kumpulan yang didarab dengan purata kedalaman pokok. Jika anda perlu, sebagai contoh, untuk mengira bilangan keturunan kumpulan tertentu, anda boleh menggunakan fungsi ini:
childrenCount (Group g) = GROUP SUM 1 IF isParent(Group child, g);
Tidak akan ada CTE dalam pertanyaan SQL. Sebaliknya akan ada GROUP BY yang mudah.
Menggunakan mekanisme ini, anda juga boleh menyahnormalkan pangkalan data dengan mudah jika perlu:
CLASS Order 'ΠΠ°ΠΊΠ°Π·';
date 'ΠΠ°ΡΠ°' = DATA DATE (Order);
CLASS OrderDetail 'Π‘ΡΡΠΎΠΊΠ° Π·Π°ΠΊΠ°Π·Π°';
order 'ΠΠ°ΠΊΠ°Π·' = DATA Order (OrderDetail);
date 'ΠΠ°ΡΠ°' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;
Apabila memanggil fungsi tarikh untuk baris pesanan, medan yang terdapat indeks akan dibaca dari jadual dengan baris pesanan. Apabila tarikh pesanan berubah, sistem itu sendiri secara automatik akan mengira semula tarikh tidak normal dalam baris.
Kelebihan
Untuk apa keseluruhan mekanisme ini? Dalam DBMS klasik, tanpa menulis semula pertanyaan, pembangun atau DBA hanya boleh menukar indeks, menentukan statistik dan memberitahu perancang pertanyaan cara melaksanakannya (dan PETUNJUK hanya tersedia dalam DBMS komersial). Tidak kira seberapa keras mereka mencuba, mereka tidak akan dapat menyelesaikan pertanyaan pertama dalam artikel dalam O (bilangan jabatan) tanpa mengubah pertanyaan atau menambah pencetus. Dalam skim yang dicadangkan, pada peringkat pembangunan anda tidak perlu memikirkan tentang struktur storan data dan pengagregatan yang hendak digunakan. Semua ini boleh ditukar dengan mudah dengan cepat, terus beroperasi.
Dalam amalan ia kelihatan seperti ini. Sesetengah orang membangunkan logik secara langsung berdasarkan tugas yang ada. Mereka tidak memahami algoritma dan kerumitannya, mahupun rancangan pelaksanaan, mahupun jenis cantuman, mahupun komponen teknikal lain. Mereka ini lebih banyak penganalisis perniagaan daripada pemaju. Kemudian, semua ini masuk ke dalam ujian atau operasi. Membolehkan pengelogan pertanyaan yang telah lama dijalankan. Apabila pertanyaan panjang dikesan, maka orang lain (lebih teknikal - pada asasnya DBA) memutuskan untuk mendayakan MATERIALIZED pada beberapa fungsi perantaraan. Ini melambatkan sedikit rakaman (kerana ia memerlukan mengemas kini medan tambahan dalam transaksi). Walau bagaimanapun, bukan sahaja pertanyaan ini dipercepatkan dengan ketara, tetapi juga semua orang lain yang menggunakan fungsi ini. Pada masa yang sama, memutuskan fungsi mana yang hendak direalisasikan agak mudah. Dua parameter utama: bilangan nilai input yang mungkin (ini ialah bilangan rekod dalam jadual yang sepadan), dan kekerapan ia digunakan dalam fungsi lain.
Analog
DBMS komersil moden mempunyai mekanisme yang serupa: MATERIALIZED VIEW dengan FAST REFRESH (Oracle) dan INDEXED VIEW (Microsoft SQL Server). Dalam PostgreSQL, MATERIALIZED VIEW tidak boleh dikemas kini dalam transaksi, tetapi hanya atas permintaan (dan walaupun dengan sekatan yang sangat ketat), jadi kami tidak menganggapnya. Tetapi mereka mempunyai beberapa masalah yang mengehadkan penggunaannya dengan ketara.
Pertama, anda hanya boleh mendayakan pewujudan jika anda telah membuat VIEW biasa. Jika tidak, anda perlu menulis semula permintaan yang tinggal untuk mengakses paparan yang baru dibuat untuk menggunakan pewujudan ini. Atau biarkan segala-galanya seperti sedia ada, tetapi ia akan menjadi sekurang-kurangnya tidak berkesan jika terdapat data tertentu yang telah dikira sebelumnya, tetapi banyak pertanyaan tidak selalu menggunakannya, tetapi mengira semula.
Kedua, mereka mempunyai sejumlah besar sekatan:
Oracle
5.3.8.4 Sekatan Umum pada Muat Semula Cepat
Pertanyaan mentakrifkan pandangan terwujud adalah terhad seperti berikut:
Pandangan terwujud tidak boleh mengandungi rujukan kepada ungkapan tidak berulang seperti SYSDATE and ROWNUM.
Pandangan yang diwujudkan mestilah tidak mengandungi rujukan kepada RAW or LONGRAW jenis data.
Ia tidak boleh mengandungi a SELECT senarai subquery.
Ia tidak boleh mengandungi fungsi analisis (contohnya, RANK) di dalam SELECT Klausa.
Ia tidak boleh merujuk jadual di mana an XMLIndex indeks ditakrifkan.
Ia tidak boleh mengandungi a MODEL Klausa.
Ia tidak boleh mengandungi a HAVING klausa dengan subkueri.
Ia tidak boleh mengandungi pertanyaan bersarang yang mempunyai ANY, ALL, Atau NOTEXISTS.
Ia tidak boleh mengandungi a [START WITH β¦] CONNECT BY Klausa.
Ia tidak boleh mengandungi berbilang jadual butiran di tapak yang berbeza.
ONCOMMIT pandangan terwujud tidak boleh mempunyai jadual butiran jauh.
Paparan terwujud bersarang mesti mempunyai gabungan atau agregat.
Pandangan bergabung terwujud dan pandangan agregat terwujud dengan a GROUPBY klausa tidak boleh memilih daripada jadual tersusun indeks.
5.3.8.5 Sekatan ke atas Muat Semula Pantas pada Paparan Terwujud dengan Gabungan Sahaja
Mentakrifkan pertanyaan untuk paparan terwujud dengan gabungan sahaja dan tiada agregat mempunyai sekatan berikut pada muat semula pantas:
Mereka tidak boleh mempunyai GROUPBY klausa atau agregat.
Rowid semua jadual dalam FROM senarai mesti muncul dalam SELECT senarai pertanyaan.
Log paparan terwujud mesti wujud dengan rowids untuk semua jadual asas dalam FROM senarai pertanyaan.
Anda tidak boleh mencipta paparan terwujud yang boleh dimuat semula dengan pantas daripada berbilang jadual dengan cantuman ringkas yang menyertakan lajur jenis objek dalam SELECT kenyataan.
Selain itu, kaedah muat semula yang anda pilih tidak akan cekap secara optimum jika:
Pertanyaan penentuan menggunakan sambung luar yang berkelakuan seperti sambung dalam. Jika pertanyaan penentu mengandungi sambungan sedemikian, pertimbangkan untuk menulis semula pertanyaan penentuan untuk mengandungi sambung dalam.
. SELECT senarai paparan terwujud mengandungi ungkapan pada lajur daripada berbilang jadual.
5.3.8.6 Sekatan ke atas Muat Semula Pantas pada Paparan Terwujud dengan Agregat
Mentakrifkan pertanyaan untuk paparan terwujud dengan agregat atau gabungan mempunyai sekatan berikut pada muat semula pantas:
Penyegaran pantas disokong untuk kedua-duanya ONCOMMIT and ONDEMAND pandangan terwujud, namun sekatan berikut dikenakan:
Semua jadual dalam paparan terwujud mesti mempunyai log paparan terwujud, dan log paparan terwujud mesti:
Mengandungi semua lajur daripada jadual yang dirujuk dalam paparan terwujud.
Nyatakan dengan ROWID and INCLUDINGNEWVALUES.
nyatakan SEQUENCE klausa jika jadual dijangka mempunyai campuran sisipan/pemuatan langsung, pemadaman dan kemas kini.
Hanya SUM, COUNT, AVG, STDDEV, VARIANCE, MIN and MAX disokong untuk penyegaran pantas.
COUNT(*) mesti dinyatakan.
Fungsi agregat mesti berlaku hanya sebagai bahagian paling luar ungkapan. Iaitu, agregat seperti AVG(AVG(x)) or AVG(x)+ AVG(x) adalah tidak dibenarkan.
Bagi setiap agregat seperti AVG(expr), yang sepadan COUNT(expr) mesti hadir. Oracle mengesyorkan itu SUM(expr) dinyatakan.
If VARIANCE(expr) or STDDEV(expr) dinyatakan, COUNT(expr) and SUM(expr) mesti dinyatakan. Oracle mengesyorkan itu SUM(expr *expr) dinyatakan.
. SELECT lajur dalam pertanyaan penentuan tidak boleh menjadi ungkapan kompleks dengan lajur daripada berbilang jadual asas. Penyelesaian yang mungkin untuk ini adalah dengan menggunakan pandangan terwujud bersarang.
. SELECT senarai mesti mengandungi semua GROUPBY lajur.
Pandangan terwujud tidak berdasarkan satu atau lebih jadual jauh.
Sekiranya anda menggunakan a CHAR jenis data dalam lajur penapis log paparan terwujud, set aksara tapak induk dan paparan terwujud mestilah sama.
Jika paparan terwujud mempunyai salah satu daripada yang berikut, maka muat semula pantas hanya disokong pada sisipan DML konvensional dan beban langsung.
Pandangan terwujud dengan MIN or MAX agregat
Pandangan terwujud yang mempunyai SUM(expr) tetapi tidak COUNT(expr)
Pandangan terwujud tanpa COUNT(*)
Pandangan terwujud sedemikian dipanggil pandangan terwujud sisipan sahaja.
Pandangan terwujud dengan MAX or MIN boleh dimuat semula dengan pantas selepas memadam atau mencampurkan kenyataan DML jika ia tidak mempunyai a WHERE Klausa.
Muat semula pantas maks/min selepas pemadaman atau DML bercampur tidak mempunyai gelagat yang sama seperti kes sisipan sahaja. Ia memadam dan mengira semula nilai maks/min untuk kumpulan yang terjejas. Anda perlu sedar tentang kesan prestasinya.
Pandangan terwujud dengan paparan dinamakan atau subquery dalam FROM klausa boleh dimuat semula dengan cepat dengan syarat pandangan boleh digabungkan sepenuhnya. Untuk maklumat tentang pandangan yang akan digabungkan, lihat Rujukan Bahasa SQL Pangkalan Data Oracle.
Jika tiada cantuman luar, anda mungkin mempunyai pilihan dan cantuman sewenang-wenangnya dalam WHERE Klausa.
Paparan agregat terwujud dengan cantuman luar boleh dimuat semula dengan pantas selepas DML konvensional dan beban langsung, dengan syarat hanya jadual luar telah diubah suai. Selain itu, kekangan unik mesti wujud pada lajur sambung jadual sambung dalam. Jika terdapat cantuman luar, semua cantuman mesti disambungkan oleh ANDs dan mesti menggunakan kesamarataan (=) pengendali.
Untuk pandangan terwujud dengan CUBE, ROLLUP, set kumpulan atau gabungannya, sekatan berikut dikenakan:
. SELECT senarai harus mengandungi pembeza kumpulan yang boleh menjadi a GROUPING_ID berfungsi pada semua GROUPBY ungkapan atau GROUPING berfungsi satu untuk setiap satu GROUPBY ungkapan. Sebagai contoh, jika GROUPBY klausa pandangan terwujud ialah "GROUPBYCUBE(a, b)", kemudian SELECT senarai hendaklah mengandungi sama ada "GROUPING_ID(a, b)Β» atau Β«GROUPING(a)ANDGROUPING(b)Β» untuk paparan yang diwujudkan supaya boleh dimuat semula dengan pantas.
GROUPBY tidak seharusnya menghasilkan sebarang kumpulan pendua. Sebagai contoh, "GROUP BY a, ROLLUP(a, b)" tidak boleh dimuat semula dengan pantas kerana ia menghasilkan kumpulan pendua "(a), (a, b), AND (a)".
5.3.8.7 Sekatan ke atas Muat Semula Pantas pada Paparan Terwujud dengan UNION ALL
Pandangan terwujud dengan UNIONALL set operator menyokong REFRESHFAST pilihan jika syarat berikut dipenuhi:
Pertanyaan yang menentukan mesti mempunyai UNIONALL operator di peringkat atasan.
. UNIONALL operator tidak boleh dibenamkan di dalam subkueri, dengan satu pengecualian: The UNIONALL boleh berada dalam subquery dalam FROM klausa dengan syarat pertanyaan yang menentukan adalah dalam bentuk SELECT * FROM (lihat atau subquery dengan UNIONALL) seperti contoh berikut:
CIPTA VIEW view_with_unionall AS (PILIH c.rowid crid, c.cust_id, 2 umarker DARI pelanggan c WHERE c.cust_last_name = 'Smith' UNION SEMUA PILIH c.rowid crid, c.cust_id, 3 umarker DARI pelanggan c WHERE c.cust_last_name 'Jones'); CIPTA PANDANGAN TERBENTUK unionall_inside_view_mv SEMAKAN CEPAT ATAS PERMINTAAN SEBAGAI PILIHAN * DARI view_with_unionall;
Perhatikan bahawa pandangan view_with_unionall memenuhi keperluan untuk penyegaran pantas.
Setiap blok pertanyaan dalam UNIONALL pertanyaan mesti memenuhi keperluan paparan terwujud yang boleh dimuat semula dengan pantas dengan agregat atau paparan terwujud yang boleh dimuat semula pantas dengan gabungan.
Log paparan terwujud yang sesuai mesti dibuat pada jadual seperti yang diperlukan untuk jenis paparan terwujud yang boleh dimuat semula pantas yang sepadan.
Ambil perhatian bahawa Pangkalan Data Oracle juga membenarkan kes khas paparan terwujud jadual tunggal dengan gabungan hanya dengan syarat ROWID lajur telah dimasukkan ke dalam SELECT senarai dan dalam log paparan terwujud. Ini ditunjukkan dalam pertanyaan penentu pandangan view_with_unionall.
. SELECT senarai setiap pertanyaan mesti mengandungi a UNIONALL penanda, dan UNIONALL lajur mesti mempunyai nilai angka atau rentetan malar yang berbeza dalam setiap lajur UNIONALL cawangan. Selanjutnya, lajur penanda mesti muncul dalam kedudukan ordinal yang sama dalam SELECT senarai setiap blok pertanyaan. Lihat"KESATUAN SEMUA Penanda dan Tulis Semula PertanyaanΒ» untuk maklumat lanjut mengenai UNIONALL penanda.
Sesetengah ciri seperti sambung luar, pertanyaan paparan terwujud agregat sisip sahaja dan jadual jauh tidak disokong untuk paparan terwujud dengan UNIONALL. Walau bagaimanapun, ambil perhatian bahawa pandangan terwujud yang digunakan dalam replikasi, yang tidak mengandungi cantuman atau agregat, boleh dimuat semula dengan pantas apabila UNIONALL atau meja jauh digunakan.
Parameter permulaan keserasian mesti ditetapkan kepada 9.2.0 atau lebih tinggi untuk mencipta paparan terwujud yang boleh dimuat semula dengan pantas dengan UNIONALL.
Saya tidak mahu menyinggung perasaan peminat Oracle, tetapi berdasarkan senarai sekatan mereka, nampaknya mekanisme ini ditulis bukan dalam kes umum, menggunakan beberapa jenis model, tetapi oleh beribu-ribu orang India, di mana semua orang diberi peluang untuk menulis cabang mereka sendiri, dan masing-masing melakukan apa yang dia mampu. Menggunakan mekanisme ini untuk logik sebenar adalah seperti berjalan melalui medan ranjau. Anda boleh mendapatkan lombong pada bila-bila masa dengan memukul salah satu sekatan yang tidak jelas. Cara ia berfungsi juga merupakan soalan yang berasingan, tetapi ia di luar skop artikel ini.
Microsoft SQL Server
Keperluan tambahan
Sebagai tambahan kepada pilihan SET dan keperluan fungsi deterministik, keperluan berikut mesti dipenuhi:
Pengguna yang melaksanakan CREATE INDEX mestilah pemilik pandangan.
Apabila anda mencipta indeks, IGNORE_DUP_KEY pilihan mesti ditetapkan kepada MATI (tetapan lalai).
Jadual mesti dirujuk dengan nama dua bahagian, skim.nama jadual dalam definisi pandangan.
Fungsi yang ditentukan pengguna yang dirujuk dalam paparan mesti dibuat dengan menggunakan WITH SCHEMABINDING pilihan.
Mana-mana fungsi yang ditentukan pengguna yang dirujuk dalam paparan mesti dirujuk dengan nama dua bahagian, ..
Sifat capaian data bagi fungsi yang ditentukan pengguna mestilah NO SQL, dan sifat akses luaran mestilah NO.
Fungsi masa jalan bahasa biasa (CLR) boleh muncul dalam senarai pilihan paparan, tetapi tidak boleh menjadi sebahagian daripada definisi kunci indeks berkelompok. Fungsi CLR tidak boleh muncul dalam klausa WHERE pandangan atau klausa ON operasi JOIN dalam paparan.
Fungsi dan kaedah CLR jenis yang ditentukan pengguna CLR yang digunakan dalam definisi paparan mesti mempunyai sifat yang ditetapkan seperti yang ditunjukkan dalam jadual berikut.
Harta
Nota
DETERMINISTIK = BENAR
Mesti diisytiharkan secara eksplisit sebagai atribut kaedah Microsoft .NET Framework.
TEPAT = BENAR
Mesti diisytiharkan secara eksplisit sebagai atribut kaedah .NET Framework.
AKSES DATA = TIADA SQL
Ditentukan dengan menetapkan atribut DataAccess kepada DataAccessKind.None dan atribut SystemDataAccess kepada SystemDataAccessKind.None.
AKSES LUAR = NO
Harta ini lalai kepada TIDAK untuk rutin CLR.
Pandangan mesti dibuat dengan menggunakan WITH SCHEMABINDING pilihan.
Paparan mesti merujuk hanya jadual asas yang berada dalam pangkalan data yang sama dengan paparan. Pandangan tidak boleh merujuk pandangan lain.
Pernyataan SELECT dalam definisi paparan tidak boleh mengandungi elemen Transact-SQL berikut:
COUNT
fungsi ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, DAN OPENXML) OUTER menyertai (LEFT, RIGHT, Atau FULL)
Jadual terbitan (ditakrifkan dengan menyatakan a SELECT penyataan di FROM fasal)
Bergabung sendiri
Menentukan lajur dengan menggunakan SELECT * or SELECT <table_name>.*
DISTINCT STDEV, STDEVP, VAR, VARP, Atau AVG
Ungkapan jadual biasa (CTE)
terapung1, teks, nteks, gambar, XML, Atau aliran fail lajur
Subkueri OVER klausa, yang merangkumi fungsi tetingkap kedudukan atau agregat
Predikat teks penuh (CONTAINS, FREETEXT) SUM fungsi yang merujuk kepada ungkapan nullable ORDER BY
Fungsi agregat yang ditentukan pengguna CLR TOP CUBE, ROLLUP, Atau GROUPING SETS pengendali
MIN, MAX UNION, EXCEPT, Atau INTERSECT pengendali TABLESAMPLE
Pemboleh ubah jadual OUTER APPLY or CROSS APPLY PIVOT, UNPIVOT
Set lajur jarang
Sebaris (TVF) atau fungsi bernilai jadual berbilang penyata (MSTVF) OFFSET
CHECKSUM_AGG
1 Pandangan diindeks boleh mengandungi terapung lajur; walau bagaimanapun, lajur tersebut tidak boleh disertakan dalam kunci indeks berkelompok.
If GROUP BY hadir, definisi VIEW mesti mengandungi COUNT_BIG(*) dan tidak boleh mengandungi HAVING. Ini GROUP BY sekatan hanya terpakai pada definisi paparan diindeks. Pertanyaan boleh menggunakan paparan diindeks dalam pelan pelaksanaannya walaupun ia tidak memenuhinya GROUP BY sekatan.
Jika definisi paparan mengandungi a GROUP BY klausa, kunci indeks berkelompok unik boleh merujuk hanya lajur yang dinyatakan dalam GROUP BY Klausa.
Jelas di sini bahawa orang India tidak terlibat, kerana mereka memutuskan untuk melakukannya mengikut skema "kami akan melakukan sedikit, tetapi baik." Iaitu, mereka mempunyai lebih banyak lombong di lapangan, tetapi lokasi mereka lebih telus. Perkara yang paling mengecewakan ialah had ini:
Paparan mesti merujuk hanya jadual asas yang berada dalam pangkalan data yang sama dengan paparan. Pandangan tidak boleh merujuk pandangan lain.
Dalam istilah kami, ini bermakna fungsi tidak boleh mengakses fungsi terwujud lain. Ini mengurangkan semua ideologi dalam tunas.
Selain itu, had ini (dan seterusnya dalam teks) sangat mengurangkan kes penggunaan:
Pernyataan SELECT dalam definisi paparan tidak boleh mengandungi elemen Transact-SQL berikut:
COUNT
fungsi ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, DAN OPENXML) OUTER menyertai (LEFT, RIGHT, Atau FULL)
Jadual terbitan (ditakrifkan dengan menyatakan a SELECT penyataan di FROM fasal)
Bergabung sendiri
Menentukan lajur dengan menggunakan SELECT * or SELECT <table_name>.*
DISTINCT STDEV, STDEVP, VAR, VARP, Atau AVG
Ungkapan jadual biasa (CTE)
terapung1, teks, nteks, gambar, XML, Atau aliran fail lajur
Subkueri OVER klausa, yang merangkumi fungsi tetingkap kedudukan atau agregat
Predikat teks penuh (CONTAINS, FREETEXT) SUM fungsi yang merujuk kepada ungkapan nullable ORDER BY
Fungsi agregat yang ditentukan pengguna CLR TOP CUBE, ROLLUP, Atau GROUPING SETS pengendali
MIN, MAX UNION, EXCEPT, Atau INTERSECT pengendali TABLESAMPLE
Pemboleh ubah jadual OUTER APPLY or CROSS APPLY PIVOT, UNPIVOT
Set lajur jarang
Sebaris (TVF) atau fungsi bernilai jadual berbilang penyata (MSTVF) OFFSET
CHECKSUM_AGG
OUTER JOIN, UNION, ORDER BY dan lain-lain adalah dilarang. Mungkin lebih mudah untuk menentukan apa yang boleh digunakan daripada apa yang tidak boleh digunakan. Senarai itu mungkin lebih pendek.
Untuk meringkaskan: satu set sekatan yang besar dalam setiap (mari ambil perhatian komersial) DBMS vs tiada (dengan pengecualian satu logik, bukan teknikal) dalam teknologi LGPL. Walau bagaimanapun, perlu diingatkan bahawa melaksanakan mekanisme ini dalam logik hubungan agak lebih sukar daripada dalam logik berfungsi yang diterangkan.
Π Π΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ
Bagaimana ia berfungsi? PostgreSQL digunakan sebagai "mesin maya". Terdapat algoritma kompleks di dalamnya yang membina pertanyaan. Di sini kod sumber. Dan bukan hanya satu set heuristik yang besar dengan sekumpulan ifs. Jadi, jika anda mempunyai beberapa bulan untuk belajar, anda boleh cuba memahami seni bina.
Adakah ia berfungsi dengan berkesan? Agak berkesan. Malangnya, ini sukar untuk dibuktikan. Saya hanya boleh mengatakan bahawa jika anda menganggap beribu-ribu pertanyaan yang wujud dalam aplikasi besar, maka secara purata ia lebih cekap daripada pemaju yang baik. Pengaturcara SQL yang cemerlang boleh menulis sebarang pertanyaan dengan lebih cekap, tetapi dengan seribu pertanyaan dia tidak akan mempunyai motivasi atau masa untuk melakukannya. Satu-satunya perkara yang boleh saya sebutkan sekarang sebagai bukti keberkesanan ialah beberapa projek sedang bekerja pada platform yang dibina pada DBMS ini sistem ERP, yang mempunyai beribu-ribu fungsi MATERIALIZED berbeza, dengan beribu-ribu pengguna dan pangkalan data terabait dengan ratusan juta rekod berjalan pada pelayan dua pemproses biasa. Walau bagaimanapun, sesiapa sahaja boleh menyemak/menafikan keberkesanan dengan memuat turun platform dan PostgreSQL, menghidupkan log pertanyaan SQL dan cuba menukar logik dan data di sana.
Dalam artikel berikut, saya juga akan bercakap tentang cara anda boleh menetapkan sekatan pada fungsi, bekerja dengan sesi perubahan dan banyak lagi.