Olvasás és írás egyensúlyozása az adatbázisban

Olvasás és írás egyensúlyozása az adatbázisban
A korábbi a Spotify döntéshozatali módszertanáról. Egyre több felhasználó preferálja a zenehallgatást mobilon a streaming szolgáltatásban, de a cégnél túlnyomórészt webprogramozók dolgoznak. A Spotify elemezte ezt a helyzetet, és úgy döntött, hogy több mobilfejlesztőt vesz fel, valamint átnevezi a webes szakembereket új irányba: Leírtam egy adatbázis koncepcióját és megvalósítását, amely funkciók, nem pedig táblák és mezők alapján épül fel, ahogyan azt a relációs adatbázisokban megszokhattuk. Számos példát mutattam be, amelyek azt illusztrálják, hogy ez a megközelítés miben előnyösebb a klasszikus módszernél. Sokan nem találták őket eléggé meggyőzőnek.

Ebben a cikkben bemutatom, hogyan teszi lehetővé ez a koncepció, hogy gyorsan és kényelmesen egyensúlyozzunk az adatok írása és olvasása között, anélkül, hogy bármilyen logikát megváltoztatnánk. Hasonló funkcionalitást próbáltak megvalósítani a modern kereskedelmi DBMS-ekben (különösen az Oracle és a Microsoft SQL Server esetében). A cikk végén bemutatom, milyen eredmények születtek, hogy finoman fogalmazzak, nem éppen kielégítően.

Leírás

Ahogy korábban, a jobb érthetőség érdekében példákkal kezdem a leírást. Tegyük fel, hogy egy olyan logikát kell megvalósítanunk, amely visszaadja az osztályok listáját a bennük lévő alkalmazottak számával és azok összesített bérével.

A funkcionális adatbázisban ez a következőképpen nézne ki:

CLASS Department ‘Osztály’;
name ‘Megnevezés’ = DATA STRING[100] (Osztály);

CLASS Employee ‘Alkalmazott’;
department ‘Osztály’ = DATA Department (Employee);
salary ‘Bér’ = DATA NUMERIC[10,2] (Employee);

countEmployees ‘Alkalmazottak száma’ (Department d) = 
    GROUP SUM 1 IF department(Employee e) = d;
salarySum ‘Összes bér’ (Department d) = 
    Csoport ÖSSZEG fizetés(Munkavállaló e) HA osztály(e) = d;

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

Ennek a lekérdezésnek a végrehajtásának összetettsége bármely DBMS-ben O(alkalmazottak száma), mivel ennek a számításhoz végig kell nézni az összes alkalmazott tábláját, majd csoportosítani őket osztály szerint. Emellett lesz egy kis (tartsuk feltételezve, hogy az alkalmazottak száma sokkal nagyobb, mint az osztályoké) kiegészítés a választott tervtől függően. O(log alkalmazottak száma) vagy O(osztályok száma) a csoportosításhoz és egyebekhez.

Nyilvánvaló, hogy a végrehajtás költségei eltérőek lehetnek különböző DBMS-ekben, de az összetettség nem fog változni.

A javasolt megvalósítás egy funkcionális DBMS-ben egy al-lekérdezést fog létrehozni, amely kiszámítja a szükséges értékeket az osztályra vonatkozóan, majd összekapcsolja az osztálytáblával a név megkapásához. Ugyanakkor minden funkció kijelölésénél lehetőség van egy különleges MARKER MATERIALIZED definiálására. A rendszer automatikusan létrehozza a megfelelő mezőt minden ilyen funkcióhoz. Ha a funkció értéke megváltozik, akkor ugyanabban a tranzakcióban a mező értéke is megváltozik. A funkcióra való hivatkozáskor már a már kiszámított mezőhöz fogunk hivatkozni.

Különösen, ha a funkciókhoz MATERIALIZED-et állítunk be countEmployees és salarySum, a táblázatban a részlegek listájával két mező fog megjelenni, amelyek az alkalmazottak számát és összesített bérüket tárolják. Bármilyen alkalmazottal, bérrel vagy részleghez való tartozással kapcsolatos változás esetén a rendszer automatikusan módosítja ezeknek a mezőknek az értékeit. A fenti lekérdezés közvetlenül ezekhez a mezőkhöz fog fordulni, és végrehajtásra kerül O(osztályok száma).

Mik a korlátozások? Csak egy: ennek a funkciónak véges számú bemeneti értéke kell, hogy legyen, amelyeknél az értéke meghatározott. Különben lehetetlen lesz olyan táblázatot létrehozni, amely az összes értéket tárolja, hiszen lehetetlenség végtelen számú sorral teli táblázatot készíteni.

Példa:

alkalmazottakSzama 'A munkavállalók száma, akiknek a fizetése > N' (Osztály d, NUMERIC[10,2] N) = 
    CSOPORT ÖSSZEG bér(Employee e) HA department(e) = d ÉS salary(e) > N;

Ez a funkció végtelen számú N számértékre van definiálva (például bármilyen negatív értékre alkalmas). Ezért nem lehet MATERIALIZED-ra állítani. Így ez logikai, nem pedig technikai korlátozás (tehát nem azért, mert ezt nem tudtuk megvalósítani). Egyébként — nincsenek korlátozások. Használhatók csoportosítások, rendezések, AND és OR, PARTITION, rekurzió stb.

Például a korábbi cikk 2.2 feladatában MATERIALIZED-ot állíthatunk be mindkét funkcióra:

vásárolt 'Vásárolt' (Vevő c, Termék p, EGYES y) = 
    CSOPORT ÖSSZEG összeg(Részlet d) HA 
        vevő(rendelés(d)) = c ÉS 
        termék(d) = p ÉS 
        kivonatÉv(dátum(rendelés(d))) = y ANYAGOS;
értékelés 'Értékelés' (Vevő c, Termék p, EGYES y) = 
    PARTÍCIÓ ÖSSZEG 1 RENDEZÉS CSÖKKENŐ vásárolt(c, p, y), p CSATORNÁZVA c, y ANYAGOS;
VÁLASZTOZZ contactNév(Vevő c), név(Termék p) HA értékelés(c, p, 1997) < 3;

A rendszer automatikusan létrehoz egy táblázatot a típusok kulcsaival Ügyfél, Termék és INTEGER, hozzáadja ezt a két mezőt, és frissíti azok értékeit bármilyen változáskor. A továbbiakban, amikor ezekhez a funkciókhoz fordulunk, nem történik számítás, hanem az értékek olvasása a megfelelő mezőkből.

Ezzel a mechanizmussal például megszabadulhatunk a rekurzióktól (CTE) a lekérdezésekben. Különösen nézzük meg a csoportokat, amelyek fa struktúrát alkotnak a child/parent kapcsolattal (minden csoportnak van egy hivatkozása a szülőjére):

szülő = DATA Csoport (Csoport);

A funkcionális adatbázisban a rekurziók logikáját a következőképpen definiálhatjuk:

szint (Csoport gyermek, Csoport szülő) = REKURZIÓ 1l HA a gyermek Csoport ÉS a szülő == gyermek
                                                             LÉPÉS 2l HA a szülő == szülő($parent);
isParent (Csoport gyermek, Csoport szülő) = IGAZ HA a szint(gyermek, szülő) ANYAGI;

Mivel a funkciónak isParent MATERIALIZED-ra van állítva, egy táblázat fog létrejönni két kulccsal (csoportokkal), amelyben a mező isParent csak akkor lesz igaz, ha az első kulcs a második leszármazottja. A táblázatban lévő bejegyzések száma megegyezik a csoportok számával, megszorozva a fa átlagos mélységével. Ha például meg kell számolni egy adott csoport leszármazottainak számát, akkor ehhez a funkcióhoz fordulhatunk:

childrenCount (Csoport g) = Csoport ÖSSZEG 1 HA isParent(Csoport child, g);

A SQL lekérdezésben nem lesz CTE. Ehelyett egyszerű GROUP BY lesz.

Ezzel a mechanizmussal könnyedén végrehajtható az adatbázis denormalizálása, ha szükséges:

CLASS Order 'Rendelés';
dátum 'Dátum' = DATA DATE (Rendelés);

CLASS OrderDetail 'Rendelés sor';
order 'Rendelés' = DATA Order (OrderDetail);
date 'Dátum' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;

A függvényhez való hozzáféréskor date a rendelés sor esetén a rendelési sorok táblájából olvasás történik azon mezőről, amelyhez index kapcsolódik. A rendelési dátum megváltoztatásakor a rendszer automatikusan újraszámítja a denormalizált dátumot a sorban.

Előnyök

Miért van szükség erre a mechanizmusra? A klasszikus DBMS-ek esetében, anélkül, hogy a lekérdezéseket át kellene írni, a fejlesztő vagy DBA csak módosíthatja az indexeket, meghatározhatja a statisztikát, és útmutatást adhat a lekérdezés tervezőnek, hogy hogyan hajtsa végre őket (ráadásul a HINT-ek csak kereskedelmi DBMS-ekben elérhetők). Bármit is tesznek, nem tudják az első lekérdezést a cikkben végrehajtani O (osztályok száma) lekérdezések módosítása és trigger-ek hozzáadása nélkül. Az itt javasolt rendszerben a fejlesztés során nem kell aggódni az adatok tárolási struktúrája és az agglegóriák használata miatt. Mindez zökkenőmentesen változtatható közvetlenül a használat során.

A gyakorlatban ez így néz ki. Néhány ember a felmerült feladat alapján fejleszti a logikát. Ők nem értenek sem az algoritmusokhoz és azok bonyolultságához, sem a végrehajtási tervekhez, sem a különböző join típusokhoz, sem pedig más technikai összetevőkhöz. Ezek az emberek inkább üzleti elemzők, mint fejlesztők. Ezután mindez tesztelésre vagy üzemeltetésre kerül. Bekapcsolják a hosszú lekérdezések naplózását. Amikor egy hosszú lekérdezést észlelnek, akkor már más emberek (technikaiabbak, lényegében DBA-k) döntenek arról, hogy egy köztes függvényen MATERIALIZED-t aktiválnak. Ezzel kissé lelassul a bejegyzés (mivel egy további mező frissítése szükséges a tranzakcióban). Azonban jelentősen felgyorsul nemcsak ez a lekérdezés, hanem minden más, amely ezt a funkciót használja. Ebben az esetben a döntés, hogy pontosan melyik függvényt materializálják, viszonylag egyszerűen megoldható. Két fő paraméter: a lehetséges bemeneti értékek száma (éppen annyi bejegyzés fog szerepelni a megfelelő táblában), és hogy milyen gyakran használják más funkciókban.

Analógia

A modern kereskedelmi DBMS-ek hasonló mechanizmusokkal rendelkeznek: AZ ANYAGIASÍTVA KÉPEZÉS FÁZISÚ FRISSÍTÉSSEL (Oracle) és AZ INDEXELT KÉPEZÉS (Microsoft SQL Server). A PostgreSQL-ben az ANYAGIASÍTOTT KÉPEZÉS nem frissíthető tranzakcióban, csak kérésre (ráadásul elég szigorú korlátozásokkal), így ezt nem vizsgáljuk. De van néhány problémájuk, amelyek jelentősen korlátozzák a használatukat.

Először is, a materializálás csak akkor aktíválható, ha korábban létrehoztak egy szokásos KÉPEZÉST. Ellenkező esetben át kell írni a többi kérdést az újonnan létrehozott nézetre történő hivatkozás érdekében, hogy ezt a materializálást használhassák. Vagy mindent hagyhat úgy, ahogy van, de ez legalábbis hatástalan lesz, ha vannak már előre számított adatok, amelyeket sok kérdés nem mindig használ, hanem újra kiszámít.

Másodszor, sok korlátozással rendelkeznek:

Oracle

5.3.8.4 Általános Korlátozások a Gyors Frissítéseknél

A materializált nézet meghatározó lekérdezése a következő korlátozásokkal rendelkezik:

  • A materializált nézet nem tartalmazhat hivatkozásokat nem ismétlődő kifejezésekre, mint például SYSDATE és ROWNUM.
  • A materializált nézet nem tartalmazhat hivatkozásokat RAW vagy HOSSZÚ RAW adat típusokra.
  • Nem tartalmazhat SELECT listás a lekérdezés.
  • Nem tartalmazhat analitikai függvényeket (például, RANG) a SELECT záradékban.
  • Nem hivatkozhat egy olyan táblára, amelyen egy XMLIndex index van definiálva.
  • Nem tartalmazhat MODEL záradékban.
  • Nem tartalmazhat HAVING záradékot egy al-lekérdezéssel.
  • Nem tartalmazhatne fészkelt lekérdezéseket, amelyek vannak Ez kissé furcsán hangzik, de a sémán — minden egyszerű., ALL, vagy NEM VÉGE;.
  • Nem tartalmazhat [KIVÉTELLEL …] KAPCSOLAT ÁLTAL záradékban.
  • Nem tartalmazhat több részletes táblát különböző helyeken.
  • ON COMMIT A materializált nézetek nem tartalmazhatnak távoli részletes táblákat.
  • A fészkelt materializált nézeteknek kontár vagy összesítő kell legyen.
  • A materializált kontár nézeteknek és materializált összesítő nézeteknek CSOPORT AZ záradék nem választhat az indexszervezett táblából.

5.3.8.5 Korlátozások a Gyors Frissítésekre Csak Közös Materializált Nézetek esetén

A kötelező lekérdezések, amelyek csak közös materializált nézetek és nem aggregátumok, a következő korlátozásokkal rendelkeznek a gyors frissítések során:

  • Minden korlátozás a „Általános Korlátozások a Gyors Frissítéseknél«.
  • Nem tartalmazhatnak CSOPORT AZ záradékokat vagy aggregátumokat.
  • A táblák ROWID-jának mind a FROM listájában fel kell bukkanniuk a lekérdezés SELECT listájában.
  • A materializált nézet naplóknak létezniük kell a ROWID-kkal az összes alap táblához. FROM listájában.
  • Nem hozhatsz létre gyorsan frissíthető materializált nézetet több táblából egyszerű csatlakozásokkal, amelyek tartalmaznak egy objektum típusú oszlopot a SELECT nyilatkozatban.

A frissítési módszer, amelyet választasz, nem lesz optimálisan hatékony, ha:

  • A meghatározó lekérdezés olyan külső csatlakozást használ, amely úgy viselkedik, mint egy belső csatlakozás. Ha a meghatározó lekérdezés tartalmaz egy ilyen csatlakozást, fontold meg a lekérdezés átírását, hogy tartalmazzon egy belső csatlakozást.
  • A SELECT A materializált nézet listája kifejezéseket tartalmaz több tábla oszlopain.

5.3.8.6 Korlátozások a Gyors Frissítésekre Anyagiasított Nézeteknél Aggregátumokkal

A meghatározó lekérdezések, amelyek aggregátumokkal vagy közös lekérdezésekkel rendelkeznek, a következő korlátozásokkal rendelkeznek a gyors frissítések során:

A gyors frissítést támogatják mindkettő ON COMMIT és ON KERESLET materializált nézetek, azonban a következő korlátozások érvényesek:

  • A materializált nézetben lévő összes táblának rendelkeznie kell materializált nézet naplókkal, és a materializált nézet naplóinak:
    • Tartalmaznia kell az összes oszlopot a táblából, amelyre a materializált nézet hivatkozik.
    • A ROWID-t meg kell határozni TARTALMAZVA és ÚJ Meg kell határozni a VALUES.
    • záradékot, ha a táblának elegye van beszúrások/direkt betöltések, törlések és frissítések között. SEQUENCE Csak

  • ÖSSZEG STDDEV, COUNT, AVG, VARIÁCIÓN, MAX, a kettő közül a legkisebbet választja. és támogatott a gyors frissítéshez. COUNT(*)
  • meg kell határozni. meg kell adni.
  • Az aggregáló függvényeknek a kifejezés legkülső részén kell előfordulniuk. Azaz, olyan aggregálók, mint például AVG(AVG(x)) vagy AVG(x)+ AVG(x) nem engedélyezettek.
  • Minden aggregáló, mint például AVG(expr), a megfelelő COUNT(expr) jelen kell legyen. Az Oracle azt javasolja, hogy SUM(expr) határozva legyen.
  • Ha VARIANCE(expr) vagy STDDEV(expr) van meghatározva, COUNT(expr) és SUM(expr) meg kell határozni. Az Oracle azt javasolja, hogy SUM(expr *expr) határozva legyen.
  • A SELECT oszlop a definiáló lekérdezésben nem lehet komplex kifejezés, amely oszlopokat tartalmaz több alap táblából. Ezt megkerülheti egy beágyazott materializált nézettel.
  • A SELECT A lista minden CSOPORT AZ oszlopot tartalmaznia kell.
  • A materializált nézet nem alapul egy vagy több távoli táblán.
  • Ha egy CHAR adat típust használ a materializált nézet napló szűrő oszlopaiban, akkor a mesterhely és a materializált nézet karakterkészleteinek azonosaknak kell lenniük.
  • Ha a materializált nézet tartalmaz az alábbiak közül valamelyiket, akkor a gyors frissítés csak a hagyományos DML beszúrásokra és közvetlen betöltésre támogatott.
    • Materializált nézetek aggregálókkal a kettő közül a legkisebbet választja. vagy támogatott a gyors frissítéshez. Materializált nézetek, amelyek rendelkeznek
    • de nincs SUM(expr) Materializált nézetek anélkül, hogy COUNT(expr)
    • Egy ilyen materializált nézetet beszúrásra alkalmas materializált nézetnek neveznek. meg kell határozni.

    Egy materializált nézet, amely

  • gyorsan frissíthető törlés vagy vegyes DML utasítások után, ha nincs támogatott a gyors frissítéshez. vagy a kettő közül a legkisebbet választja. A max/min gyors frissítés törlés vagy vegyes DML után nem ugyanúgy működik, mint a beszúrásra alkalmas eset. Törli és újraszámolja a max/min értékeket az érintett csoportok számára. Tudnia kell a teljesítményhatását. AHOL záradékban.
    Materializált nézetek nézettel vagy részlekérdezésekkel a
  • záradékban gyorsan frissíthetők, amennyiben a nézeteket teljesen össze lehet vonni. Az összevonásra vonatkozó információkért lásd FROM Oracle Database SQL Language Reference Ha nincsenek külső összekapcsolások, önálló választások és összekapcsolások lehetnek a.
  • A materializált aggregáló nézetek külső összekapcsolásokkal gyorsan frissíthetők hagyományos DML és közvetlen betöltések után, amennyiben csak a külső táblát módosították. Az is egyedi kényszereknek kell lenniük a belső összekapcsolás táblájának összekapcsolási oszlopaiban. Ha külső összekapcsolások vannak, az összes összekapcsolásnak kapcsolódnia kell AHOL záradékban.
  • és használniuk kell az egyenlőséget ( ÉS) operátort.=A materializált nézetekkel, amelyek rendelkeznek
  • CUBE ROLLUP, , csoportosító halmazokkal, vagy azok összefűzésével, a következő korlátozások vonatkoznak:a lista csoportosító megkülönböztetőt kell tartalmazzon, amely lehet vagy egy
    • A SELECT GROUPING_ID függvény minden kifejezésre, vagy CSOPORT AZ GROUPING függvények, egy minden kifejezéshez. Például, ha a materializált nézet záradéka « CSOPORT AZ CUBE(a, b) CSOPORT AZ «, akkor a lista tartalmaznia kell vagy «CSOPORT AZ GROUPING_ID(a, b)» vagy « SELECT GROUPING(a)GROUPING(b)» a materializált nézet gyors frissítéséhez.nem szabad semmilyen duplikált csoportosítást eredményeznie. Például, « ÉS GROUP BY a, ROLLUP(a, b)» nem gyorsan frissíthető, mert duplikált csoportosítást eredményez «
    • CSOPORT AZ (a), (a, b), ÉS (a)5.3.8.7 Korlátozások a gyors frissítésre az UNION ALL-lel rendelkező materializált nézeteknélAz UNION ALL-t tartalmazó materializált nézetek aset operátor támogatják«.

REFRESH

FAST UNION ALL opciót, ha a következő feltételek teljesülnek: A definiáló lekérdezésnek a operátornak a legfelső szinten kell lennie. Az operátor nem ágyazható be egy részlekérdezésbe, egy kivétel van: A

  • egy részlekérdezésben lehet a UNION ALL záradékban, amennyiben a definiáló lekérdezés a következő formában van:

    A UNION ALL SELECT * FROM UNION ALL (nézet vagy részlekérdezés, amely tartalmazza FROM ) mint a következő példában: CREATE VIEW view_with_unionall AS (SELECT c.rowid crid, c.cust_id, 2 umarker FROM customers c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker FROM customers c WHERE c.cust_last_name = 'Jones');CREATE MATERIALIZED VIEW unionall_inside_view_mv REFRESH FAST ON DEMAND AS SELECT * FROM view_with_unionall; Vegye figyelembe, hogy a nézet UNION ALLview_with_unionall

    teljesíti a gyors frissítés követelményeit.
    

    Minden lekérdezési blokk a lekérdezésnek meg kell felelnie a gyorsan frissíthető materializált nézet aggregátorokkal vagy gyorsan frissíthető materializált nézetekkel kapcsolatos követelményeknek. A megfelelő materializált nézet naplókat a táblákon kell létrehozni a megfelelő gyorsan frissíthető materializált nézet típusához szükségesek.

  • Minden lekérdezési blokk a UNION ALL lekérdezésnek meg kell felelnie a gyorsan frissíthető anyagolt nézet aggregátumokkal vagy a gyorsan frissíthető anyagolt nézet összekapcsolásokkal szemben támasztott követelményeknek.

    A megfelelő anyagolt nézet naplók létrehozása szükséges a táblákon, ahogy azt a megfelelő típusú gyorsan frissíthető anyagolt nézet megköveteli.
    Vegye figyelembe, hogy az Oracle Database különleges esetként lehetővé teszi egyetlen táblás materializált nézet létrehozását, amely csak lekérdezéseket tartalmaz, ha a TARTALMAZVA oszlop szerepel a SELECT listában és a materializált nézet naplóban. Ezt a nézet definíciós lekérdezésében mutatják be. lekérdezésnek meg kell felelnie a gyorsan frissíthető materializált nézet aggregátorokkal vagy gyorsan frissíthető materializált nézetekkel kapcsolatos követelményeknek..

  • A SELECT Minden lekérdezés listájának tartalmaznia kell egy UNION ALL jelölőt, és a UNION ALL oszlopnak egyedi állandó numerikus vagy karakterértékkel kell rendelkeznie minden UNION ALL ágban. Ezen túlmenően a jelölő oszlopnak ugyanabban a sorszámban kell szerepelnie a SELECT lekérdezési blokk listájában. További információk találhatók a «UNION ALL jelölő és lekérdezés átírása» című részben. UNION ALL jelölőkről.
  • Egyes funkciók, mint például a külső csatlakozások, csak beszúró halmozott materializált nézet lekérdezések és távoli táblák nem támogatottak a materializált nézetekhez. UNION ALL. Vegye figyelembe, hogy a replikációval használt materializált nézetek, amelyek nem tartalmaznak csatlakozásokat vagy halmozásokat, gyorsan újra frissíthetők, ha UNION ALL vagy távoli táblák használatosak.
  • A kompatibilitási inicializáló paraméternek 9.2.0 vagy magasabb értékre kell lennie beállítva, hogy gyors frissíthető materializált nézetet hozhassunk létre. UNION ALL.

Nem szeretném megbántani az Oracle rajongóit, de az ő korlátozási listájuk alapján az a benyomásom támadt, hogy ezt a mechanizmust nem általános esetben írták, hanem valamilyen modell felhasználásával, hanem több ezer indiai fejlesztő, akik mindegyike a saját ágát írta, és mindegyikük azt csinált, amire képes volt. Ennek a mechanizmusnak a használata a valódi logikában olyan, mint egy aknamezőn járni. Bármikor felrobbanhat egy akna, ha rátalálunk egy nem nyilvánvaló korlátozásra. A működése is egy külön kérdés, de ez a cikk keretein kívül esik.

Microsoft SQL Server

További követelmények

A SET opciók és a determinisztikus függvény követelmények mellett a következő követelményeknek is meg kell felelni:

  • A felhasználónak, aki végrehajtja CREATE INDEX a nézet tulajdonosának kell lennie.
  • Amikor létrehozza az indexet, a IGNORE_DUP_KEY opciónak OFF-ra (az alapértelmezett beállítás) kell lennie állítva.
  • A táblákat két részes névvel kell hivatkozni, schema.tablename a nézet definíciójában.
  • A nézetben hivatkozott felhasználó által létrehozott függvényeknek a WITH SCHEMABINDING opcióval kell létrehozva lenniük.
  • A nézetben hivatkozott minden felhasználó által létrehozott függvénynek két részes néven kell szerepelnie, <schema>.<function>.
  • A felhasználó által meghatározott függvény adat-hozzáférési tulajdonságának NO SQL, és a külső hozzáférési tulajdonságának NO.
  • A közös nyelv futtatási (CLR) függvények megjelenhetnek a nézet választási listájában, de nem lehetnek a klaszterezett index kulcs definíciójának részét képezniük. A CLR függvények nem jelenhetnek meg a nézet WHERE záradékában vagy a JOIN művelet ON záradékában a nézetben.
  • A nézet definíciójában használt CLR függvénynek és CLR felhasználó által meghatározott típusának a következő táblázatban bemutatott tulajdonságokkal kell rendelkeznie.

    Tulajdonság
    Megjegyzés

    DETERMINISTIC = TRUE
    Kifejezetten a Microsoft .NET Framework metódus attribútumaként kell deklarálni.

    PRECISE = TRUE
    Kifejezetten a .NET Framework metódus attribútumaként kell deklarálni.

    ADATA HOZZÁFÉRÉS = NO SQL
    Ez a DataAccess attribútum DataAccessKind.None-ra és a SystemDataAccess attribútum SystemDataAccessKind.None-ra állításával van meghatározva.

    KÜLSŐ HOZZÁFÉRÉS = NO
    Ez a tulajdonság alapértelmezés szerint NO a CLR rutinok esetében.

  • A nézetet a következő módon kell létrehozni: WITH SCHEMABINDING opcióval kell létrehozva lenniük.
  • A nézetnek csak az ugyanabban az adatbázisban lévő alap táblákra kell hivatkoznia. A nézet nem hivatkozhat más nézetekre.
  • A nézet definíciós SELECT nyilatkozatának nem szabad tartalmaznia a következő Transact-SQL elemeket:

    COUNT
    ROWSET függvények (OPENDATASOURCE, OPENQUERY, OPENROWSET, ÉS OPENXML)
    KÜLSŐ csatlakozások (BAL, JOBB, vagy TELJES)

    Származtatott tábla (amelyet úgy definiálunk, hogy megadunk egy SELECT állítást a FROM záradékban)
    Öncsatlakozások
    Oszlopok megadása SELECT * vagy SELECT

    .*

    DISTINCT
    STDEV, STDEVP, VAR, VARP, vagy AVG
    Közös táblázati kifejezés (CTE)

    lebegőpontos1, szöveg, ntext, kép, XML, vagy fájlstream oszlopok
    Alkérdés
    OVER záradék, amely rangsorolási vagy aggregáló ablakfüggvényeket tartalmaz

    Teljes szöveges predikátumok (TARTALMAZ, SZABAD SZÖVEG)
    STDDEV függvény, amely hivatkozik egy nullable kifejezésre
    Rendezés után,

    CLR felhasználó által definiált aggregáló függvény
    FELSŐ
    ROLLUP, , csoportosító halmazokkal, vagy azok összefűzésével, a következő korlátozások vonatkoznak:, vagy Csoportosító készletek operátorok

    a kettő közül a legkisebbet választja., támogatott a gyors frissítéshez.
    UNION, KIVÉVE, vagy INTERSECT operátorok
    TÁBLAMINTA

    Tábla változók
    KÜLSŐ ALKALMAZÁS vagy CROSS APPLY
    FORGATÁS, FORGATÁS VISSZA

    Ritka oszlopkészletek
    Inline (TVF) vagy többs statements táblázatos értékű függvények (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Az indexelt nézet tartalmazhat lebegőpontos oszlopokat; azonban az ilyen oszlopok nem szerepelhetnek a klaszterezett index kulcsában.

  • Ha A rekurzív „táblázás” nem található egy beágyazott lekérdezésben. ha jelen van, a NÉZET definíciójának tartalmaznia kell COUNT_BIG(*) és nem tartalmazhat HAVING. Ezek A rekurzív „táblázás” nem található egy beágyazott lekérdezésben. korlátozások csak az indexelt nézet definíciójára vonatkoznak. Egy lekérdezés használhat egy indexelt nézetet a végrehajtási tervében, még akkor is, ha nem teljesíti ezeket a A rekurzív „táblázás” nem található egy beágyazott lekérdezésben. korlátozásokat.
  • Ha a nézet definíció tartalmaz egy A rekurzív „táblázás” nem található egy beágyazott lekérdezésben. záradékot, akkor az egyedi klaszterezett index kulcsa csak azokat az oszlopokat hivatkozhatja, amelyeket a A rekurzív „táblázás” nem található egy beágyazott lekérdezésben. záradékban.
  • Itt látható, hogy az indiaiakat nem vonzották, mivel úgy döntöttek, hogy "keveset, de jót" készítenek. Vagyis nekik több aknájuk van a mezőn, de elhelyezésük átláthatóbb. Legjobban ez a korlátozás bántja:

    A nézetnek csak az ugyanabban az adatbázisban lévő alap táblákra kell hivatkoznia. A nézet nem hivatkozhat más nézetekre.

    A mi terminológiánkban ez azt jelenti, hogy a függvény nem hivatkozhat egy másik materializált függvényre. Ez aláássa az egész ideológiát.
    Ezen korlátozás (és a továbbiakban) nagyon erősen csökkenti a használati lehetőségeket:

    A nézet definíciós SELECT nyilatkozatának nem szabad tartalmaznia a következő Transact-SQL elemeket:

    COUNT
    ROWSET függvények (OPENDATASOURCE, OPENQUERY, OPENROWSET, ÉS OPENXML)
    KÜLSŐ csatlakozások (BAL, JOBB, vagy TELJES)

    Származtatott tábla (amelyet úgy definiálunk, hogy megadunk egy SELECT állítást a FROM záradékban)
    Öncsatlakozások
    Oszlopok megadása SELECT * vagy SELECT

    .*

    DISTINCT
    STDEV, STDEVP, VAR, VARP, vagy AVG
    Közös táblázati kifejezés (CTE)

    lebegőpontos1, szöveg, ntext, kép, XML, vagy fájlstream oszlopok
    Alkérdés
    OVER záradék, amely rangsorolási vagy aggregáló ablakfüggvényeket tartalmaz

    Teljes szöveges predikátumok (TARTALMAZ, SZABAD SZÖVEG)
    STDDEV függvény, amely hivatkozik egy nullable kifejezésre
    Rendezés után,

    CLR felhasználó által definiált aggregáló függvény
    FELSŐ
    ROLLUP, , csoportosító halmazokkal, vagy azok összefűzésével, a következő korlátozások vonatkoznak:, vagy Csoportosító készletek operátorok

    a kettő közül a legkisebbet választja., támogatott a gyors frissítéshez.
    UNION, KIVÉVE, vagy INTERSECT operátorok
    TÁBLAMINTA

    Tábla változók
    KÜLSŐ ALKALMAZÁS vagy CROSS APPLY
    FORGATÁS, FORGATÁS VISSZA

    Ritka oszlopkészletek
    Inline (TVF) vagy többs statements táblázatos értékű függvények (MSTVF)
    OFFSET

    CHECKSUM_AGG

    Külső JOINS, UNION, REND SZERINT és hasonlók tilosak. Lehet, hogy egyszerűbb lett volna megjelölni, hogy mit lehet használni, mint amit nem. A lista valószínűleg sokkal rövidebb lett volna.

    Összefoglalva: hatalmas mennyiségű korlátozás minden (megjegyzem kereskedelmi) DBMS esetében, szemben az LGPL technológia által nem jelentett semmivel (kivéve egy logikai, nem technikai) esetet. Meg kell azonban jegyezni, hogy ezt a mechanizmust relációs logikában néhány dologban nehezebb megvalósítani, mint a leírt funkcionális.

    Megvalósítás

    Hogyan működik? A "virtuális gépként" a PostgreSQL-t használják. Belül egy bonyolult algoritmus van, amely a lekérdezések felépítésével foglalkozik. Itt forráskód. És nem csak egy nagy halom heurisztika sok if-vel. Tehát, ha van pár hónapod a tanulmányozásra, akkor megpróbálhatsz belemerülni az architektúrába.

    Mennyire működik ez hatékonyan? Meglehetősen hatékonyan. Sajnos nehéz ezt bizonyítani. Csak annyit mondhatok, hogy ha megnézzük a nagy alkalmazásokban található ezer lekérdezést, akkor átlagosan hatékonyabbak, mint egy jó fejlesztőé. Egy kiváló SQL-programozó bármely lekérdezést hatékonyabban tudna írni, de ezer lekérdezés esetén egyszerűen nem lenne sem motivációja, sem ideje erre. Az egyetlen dolog, amit most bizonyítékként felhozhatok a hatékonyságról, az az, hogy az ezen az adatbázison alapuló platformon néhány projekt működik ERP-rendszerek, amelyekben ezer különböző MATERIALIZED funkció található, ezer felhasználóval és terabájt méretű adatbázisokkal, amelyek több száz millió rekordot kezelnek egy átlagos, kétprocesszoros szerveren. Mindazonáltal bárki ellenőrizheti vagy megcáfolhatja a hatékonyságot azzal, hogy letölti platformját és a PostgreSQL-t, engedeznie kell beállítja az SQL-lekérdezések naplózását, és megpróbálja módosítani a logikát és az adatokat.

    A következő cikkekben arról is beszélni fogok, hogyan lehet korlátozásokat beállítani a funkciókra, a változáskezelési munkamenetekre és sok egyébre.

    Forrás: habr.com

    Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster