Veritabanındaki yazma ve okuma işlemlerini dengeleme

Veritabanındaki yazma ve okuma işlemlerini dengeleme
Önceki Makale İlişkisel veri tabanlarında olduğu gibi tablolar ve alanlar yerine, işlevler temel alınarak oluşturulmuş bir veritabanının konseptini ve uygulamasını anlattım. Bu yaklaşımın klasik yaklaşıma göre avantajlarını gösteren birçok örnek verilmiştir. Birçoğu bunları yeterince ikna edici bulmadı.

Bu makalede, bu konseptin, işletim mantığında herhangi bir değişiklik olmadan veritabanına yazma ve okuma işlemlerini hızlı ve kolay bir şekilde dengelemenize nasıl olanak tanıdığını göstereceğim. Benzer işlevsellik modern ticari DBMS'lerde (özellikle Oracle ve Microsoft SQL Server) uygulanmaya çalışıldı. Yazının sonunda, en hafif deyimle yaptıklarının pek de işe yaramadığını göstereceğim.

Açıklama

Daha önce olduğu gibi, daha iyi anlaşılması için açıklamaya örneklerle başlayacağım. Diyelim ki departmanların içindeki çalışan sayısı ve toplam maaşlarının listesini döndürecek mantığı uygulamamız gerekiyor.

İşlevsel bir veritabanında şöyle görünecektir:

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

Bu sorguyu herhangi bir DBMS'de yürütmenin karmaşıklığı şuna eşdeğer olacaktır: O(çalışan sayısı)çünkü bu hesaplama, tüm çalışan tablosunun taranmasını ve ardından bunların departmanlara göre gruplandırılmasını gerektirir. Ayrıca seçilen plana bağlı olarak bazı küçük (bölümlerden daha fazla çalışan olduğuna inanıyoruz) takviyeler de olacaktır. O(çalışanların günlük sayısı) veya O(bölüm sayısı) gruplama vb. için.

Yürütme yükünün farklı DBMS'lerde farklı olabileceği açıktır, ancak karmaşıklık hiçbir şekilde değişmeyecektir.

Önerilen uygulamada, işlevsel DBMS, departman için gerekli değerleri hesaplayacak bir alt sorgu oluşturacak ve ardından adı almak için departman tablosuyla bir JOIN yapacaktır. Bununla birlikte, her fonksiyon için bildirim sırasında özel bir MATERIALIZED işaretleyici ayarlamak mümkündür. Sistem bu tür her işlev için otomatik olarak karşılık gelen bir alan oluşturacaktır. Bir fonksiyonun değeri değiştirildiğinde aynı işlemde alanın değeri de değişecektir. Bu fonksiyona erişildiğinde önceden hesaplanmış alana erişilecektir.

Özellikle, işlevler için MATERIALIZED'i ayarlarsanız Çalışanları say и maaş Toplamı, daha sonra tabloya çalışan sayısını ve toplam maaşlarını saklayacak departmanların listesini içeren iki alan eklenecektir. Çalışanlarda, maaşlarında veya departman bağlılıklarında bir değişiklik olduğunda sistem bu alanların değerlerini otomatik olarak değiştirecektir. Yukarıdaki sorgu bu alanlara doğrudan erişecek ve yürütülecektir. O(bölüm sayısı).

Kısıtlamalar nelerdir? Tek bir şey var: Böyle bir fonksiyonun, değerinin tanımlandığı sonlu sayıda giriş değeri olması gerekir. Aksi takdirde sonsuz sayıda satırı olan bir tablo olamayacağından tüm değerlerini saklayan bir tablo oluşturmak mümkün olmayacaktır.

Örnek:

employeesCount ‘Количество сотрудников с зарплатой > N’ (Department d, NUMERIC[10,2] N) = 
    GROUP SUM salary(Employee e) IF department(e) = d AND salary(e) > N;

Bu fonksiyon N'nin sonsuz sayıda değeri için tanımlanmıştır (örneğin herhangi bir negatif değer uygundur). Bu nedenle üzerine MATERIALIZED koyamazsınız. Yani bu mantıksal bir sınırlamadır, teknik değil (yani bunu uygulayamadığımız için değil). Aksi takdirde herhangi bir kısıtlama yoktur. Gruplama, sıralama, VE ve VEYA, BÖLÜM, özyineleme vb. kullanabilirsiniz.

Örneğin, önceki makalenin 2.2 numaralı probleminde, MATERIALIZED'i her iki fonksiyona da koyabilirsiniz:

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;

Sistemin kendisi tip anahtarlarını içeren bir tablo oluşturacaktır Hesap, PLATFORM и INTEGER, kendisine iki alan ekleyecek ve içlerindeki alan değerlerini herhangi bir değişiklikle güncelleyecektir. Bu işlevlere daha fazla çağrı yapıldığında bunlar hesaplanmayacak, bunun yerine ilgili alanlardan değerler okunacaktır.

Bu mekanizmayı kullanarak, örneğin sorgulardaki özyinelemelerden (CTE) kurtulabilirsiniz. Özellikle, çocuk/üst ilişkisini kullanarak bir ağaç oluşturan grupları göz önünde bulundurun (her grubun ebeveyniyle bir bağlantısı vardır):

parent = DATA Group (Group);

İşlevsel bir veritabanında özyineleme mantığı şu şekilde belirtilebilir:

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;

İşlev için olduğundan Ebeveyn MATERIALIZED olarak işaretlendiğinde, bunun için iki anahtar (grup) içeren bir tablo oluşturulacaktır; Ebeveyn yalnızca ilk anahtarın ikincinin çocuğu olması durumunda doğru olacaktır. Bu tablodaki girişlerin sayısı, grup sayısı ile ağacın ortalama derinliğinin çarpımına eşit olacaktır. Örneğin belirli bir grubun soyundan gelenlerin sayısını saymanız gerekiyorsa, bu işlevi kullanabilirsiniz:

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

SQL sorgusunda CTE olmayacak. Bunun yerine basit bir GROUP BY olacaktır.

Bu mekanizmayı kullanarak gerekirse veritabanını kolayca denormalize edebilirsiniz:

CLASS Order 'Заказ';
date 'Дата' = DATA DATE (Order);

CLASS OrderDetail 'Строка заказа';
order 'Заказ' = DATA Order (OrderDetail);
date 'Дата' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;

Bir işlevi çağırırken tarih Sipariş satırı için indeksi bulunan alan, sipariş satırlarının bulunduğu tablodan okunacaktır. Sipariş tarihi değiştiğinde sistem, satırdaki denormalize edilmiş tarihi otomatik olarak yeniden hesaplayacaktır.

Avantajları

Bütün bu mekanizma ne için? Klasik DBMS'lerde, sorguları yeniden yazmadan, bir geliştirici veya DBA yalnızca dizinleri değiştirebilir, istatistikleri belirleyebilir ve sorgu planlayıcıya bunların nasıl yürütüleceğini söyleyebilir (ve HINT'ler yalnızca ticari DBMS'lerde mevcuttur). Ne kadar uğraşırlarsa uğraşsınlar yazıdaki ilk sorguyu tamamlayamayacaklar. O (bölüm sayısı) sorguları değiştirmeden veya tetikleyiciler eklemeden. Önerilen şemada, geliştirme aşamasında veri depolama yapısını ve hangi toplamaların kullanılacağını düşünmenize gerek yok. Bütün bunlar anında, doğrudan çalışma sırasında kolayca değiştirilebilir.

Pratikte şöyle görünüyor. Bazı insanlar doğrudan eldeki göreve dayalı olarak mantık geliştirirler. Algoritmaları ve bunların karmaşıklığını, yürütme planlarını, birleştirme türlerini veya başka herhangi bir teknik bileşeni anlamıyorlar. Bu insanlar geliştiricilerden çok iş analistleridir. Daha sonra tüm bunlar teste veya işletmeye alınır. Uzun süren sorguların günlüğe kaydedilmesini sağlar. Uzun bir sorgu tespit edildiğinde, diğer kişiler (daha teknik - esasen DBA) bazı ara işlevlerde MATERIALIZED'i etkinleştirmeye karar verirler. Bu, kaydı biraz yavaşlatır (çünkü işlemde ek bir alanın güncellenmesini gerektirir). Ancak, yalnızca bu sorgu değil, aynı zamanda bu işlevi kullanan diğer sorgular da önemli ölçüde hızlandırılmıştır. Aynı zamanda hangi işlevin gerçekleştirileceğine karar vermek nispeten kolaydır. İki ana parametre: olası giriş değerlerinin sayısı (ilgili tabloda kaç kayıt olacağı budur) ve diğer işlevlerde ne sıklıkta kullanıldığı.

analogları

Modern ticari DBMS'ler benzer mekanizmalara sahiptir: HIZLI YENİLEME (Oracle) ve DİZİNLİ GÖRÜNÜM (Microsoft SQL Server) ile MALZEMESEL GÖRÜNÜM. PostgreSQL'de MATERIALIZED VIEW bir işlemde güncellenemez, ancak yalnızca istek üzerine (ve hatta çok katı kısıtlamalarla) güncellenebilir, bu nedenle bunu dikkate almıyoruz. Ancak kullanımlarını önemli ölçüde sınırlayan çeşitli sorunları var.

İlk olarak, materyalleştirmeyi yalnızca zaten normal bir GÖRÜNÜM oluşturduysanız etkinleştirebilirsiniz. Aksi takdirde, bu gerçekleştirmeyi kullanmak üzere yeni oluşturulan görünüme erişmek için kalan istekleri yeniden yazmanız gerekecektir. Veya her şeyi olduğu gibi bırakın, ancak önceden hesaplanmış belirli veriler varsa en azından etkisiz olacaktır, ancak birçok sorgu bunu her zaman kullanmaz, yeniden hesaplar.

İkincisi, çok sayıda kısıtlamaları var:

Kehanet

5.3.8.4 Hızlı Yenilemeyle İlgili Genel Kısıtlamalar

Gerçekleştirilmiş görünümün tanımlayıcı sorgusu aşağıdaki şekilde kısıtlanmıştır:

  • Gerçekleştirilmiş görünüm, aşağıdaki gibi tekrarlanmayan ifadelere referanslar içermemelidir: SYSDATE ve ROWNUM.
  • Gerçekleştirilmiş görünüm aşağıdakilere referans içermemelidir: RAW or LONG RAW veri türleri.
  • Bir içeremez SELECT alt sorguyu listeleyin.
  • Analitik fonksiyonlar içeremez (örneğin, RANKOlarak) SELECT fıkra.
  • Üzerinde bir tablonun yer aldığı bir tabloya başvuruda bulunamaz. XMLIndex indeks tanımlanır.
  • Bir içeremez MODEL fıkra.
  • Bir içeremez HAVING bir alt sorgu içeren cümle.
  • İç içe geçmiş sorgular içeremez. ANY, ALLya da NOT EXISTS.
  • Bir içeremez [START WITH …] CONNECT BY fıkra.
  • Farklı sitelerde birden fazla ayrıntı tablosu içeremez.
  • ON COMMIT gerçekleştirilmiş görünümler uzak ayrıntı tablolarına sahip olamaz.
  • İç içe gerçekleştirilmiş görünümlerin bir birleşimi veya toplaması olmalıdır.
  • Gerçekleştirilmiş birleştirme görünümleri ve gerçekleştirilmiş toplu görünümler GROUP BY yan tümcesi dizinle düzenlenmiş bir tablodan seçim yapamaz.

5.3.8.5 Yalnızca Birleştirmelerle Gerçekleştirilmiş Görünümlerde Hızlı Yenilemeye İlişkin Kısıtlamalar

Yalnızca birleştirmelerle ve toplama olmadan gerçekleştirilmiş görünümlere yönelik sorguların tanımlanması, hızlı yenilemeyle ilgili aşağıdaki kısıtlamalara sahiptir:

  • Tüm kısıtlamalar «Hızlı Yenilemeyle İlgili Genel Kısıtlamalar".
  • Sahip olamazlar GROUP BY maddeler veya toplu maddeler.
  • Tüm tabloların sıra sıraları FROM listede görünmelidir SELECT sorgunun listesi.
  • Materyalleştirilmiş görünüm günlükleri, içindeki tüm temel tablolar için satır kimlikleriyle birlikte mevcut olmalıdır. FROM sorgunun listesi.
  • Nesne türü sütunu içeren basit birleştirmelere sahip birden çok tablodan hızlı bir şekilde yenilenebilir, somutlaştırılmış bir görünüm oluşturamazsınız. SELECT ifadesi.

Ayrıca seçtiğiniz yenileme yöntemi aşağıdaki durumlarda optimum düzeyde verimli olmayacaktır:

  • Tanımlayan sorgu, iç birleşim gibi davranan bir dış birleşim kullanır. Tanımlayan sorgu böyle bir birleştirme içeriyorsa, tanımlama sorgusunu bir iç birleştirme içerecek şekilde yeniden yazmayı düşünün.
  • The SELECT Gerçekleştirilmiş görünümün listesi, birden çok tablodaki sütunlardaki ifadeleri içerir.

5.3.8.6 Toplamalarla Gerçekleştirilmiş Görünümlerde Hızlı Yenilemeye İlişkin Kısıtlamalar

Toplamalar veya birleştirmelerle gerçekleştirilmiş görünümlere yönelik sorguların tanımlanması, hızlı yenilemeyle ilgili aşağıdaki kısıtlamalara sahiptir:

Hızlı yenileme her ikisi için de desteklenir ON COMMIT ve ON DEMAND gerçekleştirilmiş görüşler ancak aşağıdaki kısıtlamalar geçerlidir:

  • Gerçekleştirilmiş görünümdeki tüm tabloların, gerçekleştirilmiş görünüm günlükleri olması gerekir ve gerçekleştirilmiş görünüm günlükleri:
    • Gerçekleştirilmiş görünümde başvurulan tablodaki tüm sütunları içerir.
    • İle belirtin ROWID ve INCLUDING NEW VALUES.
    • belirtmek SEQUENCE tablonun ekleme/doğrudan yükleme, silme ve güncellemelerin bir karışımına sahip olması bekleniyorsa yan tümce.

  • Bir tek SUM, COUNT, AVG, STDDEV, VARIANCE, MIN ve MAX hızlı yenileme için desteklenir.
  • COUNT(*) belirtilmelidir.
  • Toplama işlevleri yalnızca ifadenin en dış kısmı olarak gerçekleşmelidir. Yani, aşağıdaki gibi agregalar AVG(AVG(x)) or AVG(x)+ AVG(x) izin verilmez.
  • Her bir agrega için AVG(expr), karşılık gelen COUNT(expr) mevcut olmalıdır. Oracle bunu öneriyor SUM(expr) Belirtilmek.
  • If VARIANCE(expr) or STDDEV(expr) belirtilir, COUNT(expr) ve SUM(expr) belirtilmesi gerekir. Oracle bunu öneriyor SUM(expr *expr) Belirtilmek.
  • The SELECT Tanımlayıcı sorgudaki sütun, birden çok temel tablodan gelen sütunları içeren karmaşık bir ifade olamaz. Bunun olası bir geçici çözümü, iç içe materyalleştirilmiş bir görünüm kullanmaktır.
  • The SELECT liste hepsini içermelidir GROUP BY sütunlar.
  • Gerçekleştirilmiş görünüm bir veya daha fazla uzak tabloyu temel almaz.
  • Eğer bir CHAR materyalleştirilmiş görünüm günlüğünün filtre sütunlarındaki veri türü, ana sitenin karakter kümeleri ve materyalleştirilmiş görünümün aynı olması gerekir.
  • Gerçekleştirilmiş görünüm aşağıdakilerden birine sahipse hızlı yenileme yalnızca geleneksel DML eklemelerinde ve doğrudan yüklemelerde desteklenir.
    • Gerçekleştirilmiş görünümler MIN or MAX agrega
    • Gerçekleştirilmiş görüşler SUM(expr) ama hayır COUNT(expr)
    • Gerçekleştirilmiş görünümler COUNT(*)

    Böyle bir materyalleştirilmiş görünüme yalnızca eklemeli materyalleştirilmiş görünüm adı verilir.

  • Gerçekleştirilmiş bir görünüm MAX or MIN bir özelliği yoksa, silme veya karışık DML ifadelerinden sonra hızlı bir şekilde yenilenebilir. WHERE fıkra.
    Silme veya karma DML sonrasında maksimum/min hızlı yenileme, yalnızca ekleme durumuyla aynı davranışa sahip değildir. Etkilenen gruplar için maksimum/min değerlerini siler ve yeniden hesaplar. Performans etkisinin farkında olmanız gerekir.
  • Adlandırılmış görünümler veya alt sorgular içeren materyalleştirilmiş görünümler FROM görünümlerin tamamen birleştirilebilmesi koşuluyla, madde hızlı bir şekilde yenilenebilir. Hangi görünümlerin birleştirileceği hakkında bilgi için bkz. Oracle Veritabanı SQL Dil Referansı.
  • Dış birleştirme yoksa, isteğe bağlı seçimleriniz ve birleştirmeleriniz olabilir. WHERE fıkra.
  • Dış birleşimlere sahip materyalleştirilmiş toplu görünümler, yalnızca dış tablanın değiştirilmesi koşuluyla, geleneksel DML ve doğrudan yüklemelerden sonra hızlı bir şekilde yenilenebilir. Ayrıca iç birleştirme tablosunun birleştirme sütunlarında benzersiz kısıtlamaların bulunması gerekir. Dış birleşimler varsa, tüm birleşimler şu şekilde bağlanmalıdır: ANDs ve eşitliği kullanmalıdır (=) Şebeke.
  • Gerçekleştirilmiş görünümler için CUBE, ROLLUP, gruplandırma kümeleri veya bunların birleştirilmesi durumunda aşağıdaki kısıtlamalar geçerlidir:
    • The SELECT liste, ya bir gruplama ayırıcısı içermelidir GROUPING_ID hepsinde işlev GROUP BY ifadeler veya GROUPING her biri için bir işlev görür GROUP BY ifade. Örneğin, eğer GROUP BY somutlaştırılmış görüşün maddesi "GROUP BY CUBE(a, b)", sonra SELECT liste ikisinden birini içermelidir "GROUPING_ID(a, b)»Veya«GROUPING(a) AND GROUPING(b)» Gerçekleştirilmiş görünümün hızla yenilenebilir olması için.
    • GROUP BY yinelenen gruplamalara yol açmamalıdır. Örneğin, "GROUP BY a, ROLLUP(a, b)" yinelenen gruplamalara yol açtığı için hızlı bir şekilde yenilenemez "(a), (a, b), AND (a)".

5.3.8.7 UNION ALL ile Gerçekleştirilmiş Görünümlerde Hızlı Yenilemeye İlişkin Kısıtlamalar

Gerçekleştirilmiş görüşler UNION ALL operatör desteğini ayarla REFRESH FAST Aşağıdaki koşullar yerine getirilirse seçenek:

  • Tanımlayıcı sorgunun şu özelliklere sahip olması gerekir: UNION ALL Operatör en üst seviyede.

    The UNION ALL operatörü bir istisna dışında bir alt sorgunun içine yerleştirilemez: UNION ALL bir alt sorguda olabilir FROM Tanımlayıcı sorgunun formda olması koşuluyla yan tümce SELECT * FROM (görüntüleme veya alt sorgulama UNION ALL) aşağıdaki örnekte olduğu gibi:

    GÖRÜNÜM OLUŞTUR view_with_unionall AS (C.rowid crid, c.cust_id, müşterilerden 2 umarker CREATE c.cust_last_name = 'Smith' UNION ALL SEÇ c.rowid crid, c.cust_id, 3 umarker FROM müşterilerden c WHERE c.cust_last_name = 'Jones'); MATERYALİZE GÖRÜNÜM OLUŞTURUN unionall_inside_view_mv view_with_unionall'den İSTEK ÜZERİNE SEÇİM * OLARAK HIZLI YENİLEYİN;
    

    Görünümün view_with_unionall hızlı yenileme gereksinimlerini karşılar.

  • Her sorgu bloğunda UNION ALL sorgu, toplamalarla hızlı yenilenebilir somutlaştırılmış görünümün veya birleştirmelerle hızlı yenilenebilir somutlaştırılmış görünümün gereksinimlerini karşılamalıdır.

    İlgili hızlı yenilenebilir materyalleştirilmiş görünüm türü için uygun materyalleştirilmiş görünüm günlükleri, tablolarda gerektiği şekilde oluşturulmalıdır.
    Oracle Veritabanının aynı zamanda yalnızca aşağıdaki koşulların sağlanması koşuluyla birleştirmelerle tek bir tablonun gerçekleştirilmiş görünümünün özel durumuna da izin verdiğini unutmayın. ROWID sütunu eklendi SELECT listede ve gerçekleştirilmiş görünüm günlüğünde. Bu, görünümün tanımlayıcı sorgusunda gösterilir view_with_unionall.

  • The SELECT her sorgunun listesi bir içermelidir UNION ALL işaretleyici ve UNION ALL sütunun her birinde ayrı bir sabit sayısal veya dize değeri bulunmalıdır UNION ALL dal. Ayrıca, işaretleyici sütunun aynı sıra konumunda görünmesi gerekir. SELECT her sorgu bloğunun listesi. Görmek "UNION ALL İşaretleyici ve Sorgu Yeniden Yazma» hakkında daha fazla bilgi için UNION ALL belirteçler.
  • Dış birleşimler, yalnızca eklemeli toplu gerçekleştirilmiş görünüm sorguları ve uzak tablolar gibi bazı özellikler, gerçekleştirilmiş görünümler için desteklenmez. UNION ALL. Ancak çoğaltmada kullanılan ve birleştirme veya toplama içermeyen gerçekleştirilmiş görünümlerin, aşağıdaki durumlarda hızlı bir şekilde yenilenebileceğini unutmayın: UNION ALL veya uzak tablolar kullanılır.
  • Hızlı yenilenebilir, gerçekleştirilmiş bir görünüm oluşturmak için uyumluluk başlatma parametresi 9.2.0 veya daha yüksek bir değere ayarlanmalıdır. UNION ALL.

Oracle hayranlarını gücendirmek istemiyorum, ancak kısıtlama listelerine bakılırsa, bu mekanizmanın genel durumda değil, bir tür model kullanılarak değil, herkese fırsat verildiği binlerce Hintli tarafından yazılmış gibi görünüyor. kendi dalını yazdı ve her biri elinden geleni yaptı ve yaptı. Bu mekanizmayı gerçek mantık için kullanmak, mayın tarlasında yürümek gibidir. Belirgin olmayan kısıtlamalardan birine çarparak istediğiniz zaman mayın alabilirsiniz. Nasıl çalıştığı da ayrı bir sorudur ancak bu makalenin kapsamı dışındadır.

Microsoft SQL Server

Ek gereksinimler

SET seçeneklerine ve deterministik fonksiyon gereksinimlerine ek olarak aşağıdaki gereksinimlerin de karşılanması gerekir:

  • Çalıştıran kullanıcı CREATE INDEX görünümün sahibi olmalıdır.
  • Dizini oluşturduğunuzda, IGNORE_DUP_KEY seçeneği KAPALI (varsayılan ayar) olarak ayarlanmalıdır.
  • Tablolara iki parçalı adlarla atıfta bulunulmalıdır, plan.Tablo ismi görünüm tanımında.
  • Görünümde başvurulan kullanıcı tanımlı işlevler, WITH SCHEMABINDING seçeneği.
  • Görünümde başvurulan tüm kullanıcı tanımlı işlevlere iki parçalı adlarla başvurulmalıdır; ..
  • Kullanıcı tanımlı bir fonksiyonun veri erişim özelliği şu şekilde olmalıdır: NO SQLve harici erişim özelliği olmalıdır NO.
  • Ortak dil çalışma zamanı (CLR) işlevleri, görünümün seçim listesinde görünebilir ancak kümelenmiş dizin anahtarının tanımının parçası olamaz. CLR işlevleri, görünümün WHERE yan tümcesinde veya görünümdeki bir JOIN işleminin ON yan tümcesinde görünemez.
  • Görünüm tanımında kullanılan CLR kullanıcı tanımlı türlerin CLR işlevleri ve yöntemleri, aşağıdaki tabloda gösterildiği gibi ayarlanmış özelliklere sahip olmalıdır.

    Varlığınızı
    not

    DETERMİNİSTİK = DOĞRU
    Microsoft .NET Framework yönteminin bir özniteliği olarak açıkça bildirilmelidir.

    KESİN = DOĞRU
    .NET Framework yönteminin bir özniteliği olarak açıkça bildirilmelidir.

    VERİ ERİŞİMİ = SQL YOK
    DataAccess özniteliğinin DataAccessKind.None olarak ve SystemDataAccess özniteliğinin SystemDataAccessKind.None olarak ayarlanmasıyla belirlenir.

    HARİCİ ERİŞİM = HAYIR
    Bu özellik, CLR yordamları için varsayılan olarak HAYIR'dır.

  • Görünüm kullanılarak oluşturulmalıdır. WITH SCHEMABINDING seçeneği.
  • Görünüm yalnızca görünümle aynı veritabanında bulunan temel tablolara başvurmalıdır. Görünüm diğer görünümlere referans veremez.
  • Görünüm tanımındaki SELECT deyimi aşağıdaki Transact-SQL öğelerini içermemelidir:

    COUNT
    SATIR KÜMESİ işlevleri (OPENDATASOURCE, OPENQUERY, OPENROWSET, VE OPENXML)
    OUTER birleşir (LEFT, RIGHTya da FULL)

    Türetilmiş tablo (belirtilerek tanımlanır) SELECT ifadesinde FROM madde)
    Kendi kendine katılma
    Kullanarak sütunları belirtme SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARPya da AVG
    Ortak tablo ifadesi (CTE)

    şamandıra1, metin, metin, görüntü, XMLya da dosya akışı sütunlar
    alt sorgu
    OVER sıralama veya toplu pencere işlevlerini içeren madde

    Tam metin yüklemleri (CONTAINS, FREETEXT)
    SUM null olabilen bir ifadeye başvuran işlev
    ORDER BY

    CLR kullanıcı tanımlı toplama işlevi
    TOP
    CUBE, ROLLUPya da GROUPING SETS operatörler

    MIN, MAX
    UNION, EXCEPTya da INTERSECT operatörler
    TABLESAMPLE

    Tablo değişkenleri
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Seyrek sütun kümeleri
    Satır içi (TVF) veya çok ifadeli tablo değerli işlevler (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Dizine alınmış görünüm şunları içerebilir: şamandıra sütunlar; ancak bu tür sütunlar kümelenmiş dizin anahtarına eklenemez.

  • If GROUP BY mevcutsa, GÖRÜNÜM tanımı şunları içermelidir COUNT_BIG(*) ve içermemelidir HAVING. Bunlar GROUP BY kısıtlamalar yalnızca dizine alınmış görünüm tanımı için geçerlidir. Bir sorgu, bu koşulları karşılamasa bile yürütme planında indekslenmiş bir görünümü kullanabilir. GROUP BY kısıtlamalar.
  • Görünüm tanımı bir içeriyorsa GROUP BY yan tümcesinde, benzersiz kümelenmiş dizinin anahtarı yalnızca belirtilen sütunlara başvuruda bulunabilir. GROUP BY fıkra.

Burada Kızılderililerin bu işe karışmadığı açık, çünkü bunu "çok az yapacağız ama iyi yapacağız" şemasına göre yapmaya karar verdiler. Yani sahada daha fazla mayın var ama yerleri daha şeffaf. En hayal kırıklığı yaratan şey bu sınırlamadır:

Görünüm yalnızca görünümle aynı veritabanında bulunan temel tablolara başvurmalıdır. Görünüm diğer görünümlere referans veremez.

Bizim terminolojimizde bu, bir fonksiyonun başka bir materyalleştirilmiş fonksiyona erişemeyeceği anlamına gelir. Bu, tüm ideolojiyi başlangıç ​​aşamasından keser.
Ayrıca, bu sınırlama (ve metnin ilerleyen kısımlarında) kullanım durumlarını büyük ölçüde azaltır:

Görünüm tanımındaki SELECT deyimi aşağıdaki Transact-SQL öğelerini içermemelidir:

COUNT
SATIR KÜMESİ işlevleri (OPENDATASOURCE, OPENQUERY, OPENROWSET, VE OPENXML)
OUTER birleşir (LEFT, RIGHTya da FULL)

Türetilmiş tablo (belirtilerek tanımlanır) SELECT ifadesinde FROM madde)
Kendi kendine katılma
Kullanarak sütunları belirtme SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARPya da AVG
Ortak tablo ifadesi (CTE)

şamandıra1, metin, metin, görüntü, XMLya da dosya akışı sütunlar
alt sorgu
OVER sıralama veya toplu pencere işlevlerini içeren madde

Tam metin yüklemleri (CONTAINS, FREETEXT)
SUM null olabilen bir ifadeye başvuran işlev
ORDER BY

CLR kullanıcı tanımlı toplama işlevi
TOP
CUBE, ROLLUPya da GROUPING SETS operatörler

MIN, MAX
UNION, EXCEPTya da INTERSECT operatörler
TABLESAMPLE

Tablo değişkenleri
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Seyrek sütun kümeleri
Satır içi (TVF) veya çok ifadeli tablo değerli işlevler (MSTVF)
OFFSET

CHECKSUM_AGG

OUTER JOINS, UNION, ORDER BY ve diğerleri yasaktır. Neyin kullanılamayacağından ziyade neyin kullanılabileceğini belirtmek daha kolay olabilirdi. Liste muhtemelen çok daha küçük olurdu.

Özetlemek gerekirse: LGPL teknolojisindeki her (ticari olarak belirtelim) DBMS'de çok büyük kısıtlamalar var, ancak hiçbiri (teknik olmayan mantıksal bir istisna hariç) LGPL teknolojisinde. Ancak bu mekanizmanın ilişkisel mantıkta uygulanmasının, açıklanan işlevsel mantıktan biraz daha zor olduğu unutulmamalıdır.

uygulama

Nasıl çalışır? PostgreSQL “sanal makine” olarak kullanılır. İçinde sorgular oluşturan karmaşık bir algoritma var. Burada kaynak kodu. Ve sadece bir grup eğer içeren geniş bir buluşsal yöntem kümesi yoktur. Yani eğer birkaç ay eğitiminiz varsa mimariyi anlamaya çalışabilirsiniz.

Etkili çalışıyor mu? Oldukça etkili. Ne yazık ki bunu kanıtlamak zordur. Yalnızca şunu söyleyebilirim ki, büyük uygulamalarda bulunan binlerce sorgu göz önüne alındığında, ortalama olarak bunların iyi bir geliştiricinin sorgularından daha verimli olduğu görülür. Mükemmel bir SQL programcısı herhangi bir sorguyu daha verimli bir şekilde yazabilir, ancak binlerce sorguyla bunu yapacak motivasyona veya zamana sahip olmayacaktır. Artık etkililiğin kanıtı olarak gösterebileceğim tek şey, bu DBMS üzerine inşa edilen platform üzerinde birkaç projenin çalışıyor olmasıdır. ERP sistemleriBinlerce farklı MATERIALIZED işlevi olan, binlerce kullanıcıya ve yüz milyonlarca kayıt içeren terabayt veritabanlarına sahip, normal iki işlemcili bir sunucuda çalışıyor. Ancak herkes indirerek etkinliğini kontrol edebilir/çürütebilir. bir platform ve PostgreSQL, açık SQL sorgularını günlüğe kaydetmek ve oradaki mantığı ve verileri değiştirmeye çalışmak.

Sonraki makalelerde işlevlere nasıl kısıtlamalar koyabileceğinizi, değişiklik oturumlarıyla nasıl çalışabileceğinizi ve çok daha fazlasını nasıl yapabileceğinizi de anlatacağım.

Kaynak: habr.com

Yorum ekle