
Dans l'article prĂ©cĂ©dent J'ai dĂ©crit le concept et la mise en Ćuvre d'une base de donnĂ©es basĂ©e sur des fonctions plutĂŽt que sur des tables et des champs comme dans les bases de donnĂ©es relationnelles. De nombreux exemples ont Ă©tĂ© fournis pour montrer les avantages de cette approche par rapport Ă la classique. Beaucoup les ont jugĂ©s peu convaincants.
Dans cet article, je vais montrer comment ce concept permet d'équilibrer rapidement et facilement les écritures et les lectures dans la base de données sans modifier la logique de fonctionnement. Une fonctionnalité similaire a été tentée dans des SGBD commerciaux modernes (en particulier, Oracle et Microsoft SQL Server). à la fin de l'article, je montrerai les résultats obtenus, qui, pour le dire poliment, ne sont pas trÚs concluants.
Description
Comme auparavant, pour une meilleure comprĂ©hension, je commencerai la description par des exemples. Supposons que nous devions mettre en Ćuvre une logique qui retourne une liste de dĂ©partements avec le nombre d'employĂ©s et leur salaire total.
Dans une base de données fonctionnelle, cela ressemblerait à ceci :
CLASS DĂ©partement âDĂ©partementâ;
name âDĂ©nominationâ = CHAĂNE DE DONNĂES[100] (DĂ©partement);
CLASS Employee âEmployĂ©â;
department âDĂ©partementâ = DATA Department (Employee);
salary âSalaireâ = DATA NUMERIC[10,2] (Employee);
countEmployees âNombre dâemployĂ©sâ (Department d) =Â
    GROUPE SOMME 1 SI department(Employee e) = d;
salarySum âSalaire totalâ (Department d) =Â
    GROUPE SOMME salary(Employee e) SI department(e) = d;
SELECT name(Department d), countEmployees(d), salarySum(d);
La complexitĂ© de l'exĂ©cution de cette requĂȘte dans n'importe quel SGBD sera Ă©quivalente Ă O(nombre d'employĂ©s), car pour ce calcul, il faut parcourir l'ensemble de la table des employĂ©s, puis les regrouper par dĂ©partement. Il y aura Ă©galement un lĂ©ger ajout (en supposant que le nombre dâemployĂ©s est bien plus Ă©levĂ© que le nombre de dĂ©partements) en fonction du plan choisi. O(log nombre d'employĂ©s) ou O(nombre de dĂ©partements) pour le regroupement et autres.
Il est clair que les frais généraux peuvent varier d'un SGBD à l'autre, mais la complexité ne changera pas.
Dans l'implĂ©mentation proposĂ©e, le SGBD fonctionnel gĂ©nĂ©rera une sous-requĂȘte qui calculera les valeurs nĂ©cessaires par dĂ©partement, puis effectuera un JOIN avec la table des dĂ©partements pour obtenir le nom. Cependant, pour chaque fonction lors de la dĂ©claration, il est possible de dĂ©finir un marqueur spĂ©cial MATERIALIZED. Le systĂšme crĂ©era automatiquement un champ correspondant pour chaque telle fonction. Lorsque la valeur de la fonction change, la valeur du champ changera Ă©galement dans la mĂȘme transaction. Lors de l'appel Ă cette fonction, l'accĂšs se fera dĂ©jĂ au champ prĂ©-calculĂ©.
En particulier, si l'on dĂ©finit MATERIALIZED pour les fonctions countEmployees et salarySum, deux champs seront ajoutĂ©s Ă la table des dĂ©partements, dans lesquels seront stockĂ©s le nombre d'employĂ©s et leur salaire total. Chaque fois qu'il y a un changement concernant les employĂ©s, leurs salaires ou leur appartenance aux dĂ©partements, le systĂšme mettra automatiquement Ă jour les valeurs de ces champs. La requĂȘte ci-dessus accĂ©dera directement Ă ces champs et s'exĂ©cutera en O(nombre de dĂ©partements).
Quelles sont les limitations ? Une seule : une telle fonction doit avoir un nombre fini de valeurs d'entrée pour lesquelles sa valeur est définie. Sinon, il ne sera pas possible de construire une table contenant toutes ses valeurs, car il ne peut y avoir de table avec un nombre infini de lignes.
Exemple :
employeesCount âNombre d'employĂ©s avec un salaire > Nâ (DĂ©partement d, NUMERIC[10,2] N) =Â
    GROUPE SOMME salaire(Employé e) SI département(e) = d ET salaire(e) > N;
Cette fonction est définie pour une infinité de valeurs du nombre N (par exemple, toute valeur négative convient). Par conséquent, il est impossible d'appliquer MATERIALIZED. Ainsi, c'est une contrainte logique et non technique (c'est-à -dire que ce n'est pas parce que nous n'avons pas pu le réaliser). En dehors de cela, aucune restriction. Il est possible d'utiliser des regroupements, des tris, AND et OR, PARTITION, des récursions, etc.
Par exemple, dans la tùche 2.2 de l'article précédent, il est possible d'appliquer MATERIALIZED sur les deux fonctions :
achetĂ© 'Achat' (Client c, Produit p, ENTIER y) =Â
    SOMME DU GROUPE sum(DĂ©tail d) SIÂ
        client(commande(d)) = c ETÂ
        produit(d) = p ETÂ
        extraireAnnĂ©e(date(commande(d))) = y MATĂRIALISĂ;
Ă©valuation 'Ăvaluation' (Client c, Produit p, ENTIER y) =Â
    SOMME DE PARTITION 1 ORDRE DESC achetĂ©(c, p, y), p PAR c, y MATĂRIALISĂ;
SĂLECTIONNER contactNom(Client c), nom(Produit p) OĂ Ă©valuation(c, p, 1997) < 3;
Le systĂšme crĂ©era lui-mĂȘme une table avec des clĂ©s de type Client, Produit et INTEGER, ajoutera deux champs et mettra Ă jour leurs valeurs lors de tout changement. Lors des appels futurs Ă ces fonctions, aucun calcul ne sera effectuĂ©, mais les valeurs seront lues Ă partir des champs correspondants.
Ă l'aide de ce mĂ©canisme, il est possible, par exemple, de se dĂ©barrasser des rĂ©cursions (CTE) dans les requĂȘtes. En particulier, considĂ©rons les groupes qui forment un arbre Ă l'aide de la relation enfant/parent (chaque groupe a un lien vers son parent) :
parent = DATA Group (Groupe);
Dans une base de donnĂ©es fonctionnelle, la logique des rĂ©cursions peut ĂȘtre dĂ©finie comme suit :
niveau (Groupe enfant, Groupe parent) = RĂCURSION 1l SI enfant EST Groupe ET parent == enfant
                                                             ĂTAPE 2l SI parent == parent($parent);
estParent (Groupe enfant, Groupe parent) = VRAI SI niveau(enfant, parent) MATĂRIALISĂ;
Puisque la fonction isParent est marquĂ©e MATERIALIZED, une table avec deux clĂ©s (groupes) sera créée, dans laquelle le champ isParent sera vrai uniquement si la premiĂšre clĂ© est un descendant de la seconde. Le nombre d'enregistrements dans cette table sera Ă©gal au nombre de groupes multipliĂ© par la profondeur moyenne de l'arbre. Si, par exemple, il est nĂ©cessaire de calculer le nombre de descendants d'un groupe spĂ©cifique, cette fonction peut ĂȘtre utilisĂ©e :
childrenCount (Groupe g) = SOMME GROUPE 1 SI isParent(Groupe enfant, g);
Il n'y aura pas de CTE dans la requĂȘte SQL. Ă la place, il y aura simplement un GROUP BY.
Grùce à ce mécanisme, il est également possible de procéder facilement à la dénormalisation de la base de données si nécessaire :
CLASS Commande 'Commande';
date 'Date' = DONNĂES DATE (Commande);
CLASS OrderDetail 'Détail de la commande';
order 'Commande' = DATA Order (OrderDetail);
date 'Date' (OrderDetail d) = date(order(d)) MATERIALIZED INDEXED;
Lorsqu'il est question de la fonction date pour une ligne de commande, il y aura une lecture depuis la table des lignes de commandes pour le champ qui a un index. Lorsque la date de la commande change, le systÚme recalculera automatiquement la date dénormalisée dans la ligne.
Avantages
Ă quoi sert tout ce mĂ©canisme ? Dans les SGBD classiques, sans réécriture des requĂȘtes, le dĂ©veloppeur ou le DBA peuvent simplement modifier les index, dĂ©finir des statistiques et suggĂ©rer au planificateur de requĂȘtes comment les exĂ©cuter (et les HINTs ne sont disponibles que dans les SGBD commerciaux). Peu importe leurs efforts, ils ne pourront pas exĂ©cuter la premiĂšre requĂȘte de l'article en O (nombre de dĂ©partements) sans modifier les requĂȘtes et ajouter des triggers. Dans le schĂ©ma proposĂ©, au stade de dĂ©veloppement, on peut ne pas penser Ă la structure de stockage des donnĂ©es et aux agrĂ©gations Ă utiliser. Tout cela peut ĂȘtre modifiĂ© Ă la volĂ©e directement en exploitation.
Dans la pratique, cela se prĂ©sente comme suit. Certaines personnes dĂ©veloppent directement la logique en fonction de la tĂąche fixĂ©e. Elles ne maĂźtrisent ni les algorithmes et leur complexitĂ©, ni les plans d'exĂ©cution, ni les types de jointures, ni aucun autre aspect technique. Ces personnes sont plutĂŽt des analystes commerciaux que des dĂ©veloppeurs. Ensuite, tout cela passe en test ou en production. La journalisation des requĂȘtes longues est activĂ©e. Lorsqu'une requĂȘte longue est dĂ©tectĂ©e, la dĂ©cision d'activer MATERIALIZED sur une certaine fonction intermĂ©diaire est prise par d'autres personnes (plus techniques â en fait des DBA). Cela ralentit lĂ©gĂšrement l'Ă©criture (car une mise Ă jour d'un champ supplĂ©mentaire dans la transaction est nĂ©cessaire). Cependant, non seulement cette requĂȘte est considĂ©rablement accĂ©lĂ©rĂ©e, mais toutes les autres qui utilisent cette fonction le sont Ă©galement. La dĂ©cision sur la fonction Ă matĂ©rialiser est relativement simple. Deux paramĂštres principaux : le nombre de valeurs d'entrĂ©e possibles (c'est exactement le nombre d'enregistrements qui se trouvera dans la table correspondante) et la frĂ©quence de son utilisation dans d'autres fonctions.
Analogues
Dans les SGBD commerciaux modernes, il existe des mĂ©canismes similaires : MATERIALIZED VIEW avec FAST REFRESH (Oracle) et INDEXED VIEW (Microsoft SQL Server). Dans PostgreSQL, MATERIALIZED VIEW ne peut pas ĂȘtre mise Ă jour dans une transaction, mais seulement sur demande (avec des restrictions trĂšs strictes), donc nous ne le prenons pas en considĂ©ration. Cependant, ils prĂ©sentent plusieurs problĂšmes qui limitent considĂ©rablement leur utilisation.
PremiĂšrement, vous ne pouvez activer la matĂ©rialisation que si vous avez dĂ©jĂ créé une vue ordinaire. Sinon, il vous faudra réécrire toutes les autres requĂȘtes qui accĂšdent Ă la nouvelle vue créée afin d'utiliser cette matĂ©rialisation. Ou laisser les choses telles qu'elles sont, mais cela sera au minimum inefficace si certaines donnĂ©es dĂ©jĂ prĂ©-calculĂ©es existent, et que beaucoup de requĂȘtes ne les utilisent pas toujours, mais les recalculent.
DeuxiĂšmement, il existe un grand nombre de restrictions :
Oracle
5.3.8.4 Restrictions générales sur le rafraßchissement rapide
La requĂȘte dĂ©finissant la vue matĂ©rialisĂ©e est limitĂ©e comme suit :
- La vue matérialisée ne doit pas contenir de références à des expressions non répétitives telles que
SYSDATEandROWNUM.- La vue matĂ©rialisĂ©e ne doit pas contenir de rĂ©fĂ©rences Ă
RAWorLONGRAWtypes de données.- Elle ne peut pas contenir un
SELECTsous-requĂȘte de liste.- Elle ne peut pas contenir de fonctions analytiques (par exemple,
RANK) dans laSELECTclause.- Elle ne peut pas référencer une table sur laquelle un
index XMLIndexest défini.- Elle ne peut pas contenir un
MODELclause.- Elle ne peut pas contenir un
clause avec une sous-requĂȘte.Elle ne peut pas contenir de requĂȘtes imbriquĂ©es qui aient- ANY
ALL,, ou[START WITH âŠ] CONNECT BYNOTsoient « vrais », mais.- Elle ne peut pas contenir un
[START WITH âŠ] CONNECT BYclause.- Il ne peut pas contenir plusieurs tables de dĂ©tail Ă diffĂ©rents sites.
ACTIVERCOMMITles vues matérialisées ne peuvent pas avoir de tables de détail distantes.- Les vues matérialisées imbriquées doivent avoir une jointure ou un agrégat.
- Les vues de jointure matérialisées et les vues agrégées matérialisées avec un
GROUPEPARla clause ne peut pas sélectionner à partir d'une table organisée par index.5.3.8.5 Restrictions sur le Rafraßchissement Rapide sur les Vues Matérialisées avec Uniquement des Jointures
Les requĂȘtes dĂ©finissant des vues matĂ©rialisĂ©es avec uniquement des jointures et sans agrĂ©gats ont les restrictions suivantes sur le rafraĂźchissement rapide :
- Toutes les restrictions de ««.
- Elles ne peuvent pas avoir
GROUPEPARclauses ou agrégats.- Les Rowids de toutes les tables dans la
DEliste doivent apparaĂźtre dans laSELECTliste de la requĂȘte.- Les journaux de vues matĂ©rialisĂ©es doivent exister avec les rowids pour toutes les tables de base dans le
DEliste de la requĂȘte.- Vous ne pouvez pas crĂ©er une vue matĂ©rialisĂ©e rafraĂźchissable rapidement Ă partir de plusieurs tables avec des jointures simples qui incluent une colonne de type objet dans la
SELECTdéclaration.De plus, la méthode de rafraßchissement que vous choisissez ne sera pas optimalement efficace si :
- La requĂȘte dĂ©finissant utilise une jointure externe qui se comporte comme une jointure interne. Si la requĂȘte dĂ©finissant contient une telle jointure, envisagez de réécrire la requĂȘte dĂ©finissant pour qu'elle contienne une jointure interne.
- Le
SELECTla liste de la vue matérialisée contient des expressions sur des colonnes provenant de plusieurs tables.5.3.8.6 Restrictions sur le Rafraßchissement Rapide sur les Vues Matérialisées avec Agrégats
Les requĂȘtes dĂ©finissant des vues matĂ©rialisĂ©es avec des agrĂ©gats ou des jointures ont les restrictions suivantes sur le rafraĂźchissement rapide :
- Toutes les restrictions de ««.
Le rafraßchissement rapide est supporté pour les deux
ACTIVERCOMMITandACTIVERSUR DEMANDEvues matérialisées, cependant les restrictions suivantes s'appliquent :
- Toutes les tables dans la vue matérialisée doivent avoir des journaux de vues matérialisées, et les journaux de vues matérialisées doivent :
- Contenir toutes les colonnes de la table référencée dans la vue matérialisée.
- Spécifiez avec
ROWIDandY COMPRISNOUVEAUXVALEURS.- Spécifiez la
SĂQUENCEclause si la table est censĂ©e avoir un mĂ©lange d'inserts/chargements directs, de suppressions et de mises Ă jour.- Seuls
SOMME,COUNT,AVG,ĂCART TYPE,VARIANCE,MINandMAXsont supportĂ©s pour le rafraĂźchissement rapide.COUNT(*)doit ĂȘtre spĂ©cifiĂ©.- Les fonctions agrĂ©gĂ©es doivent apparaĂźtre uniquement comme la partie la plus extĂ©rieure de l'expression. C'est-Ă -dire, des agrĂ©gats tels que
AVG(AVG(x))orAVG(x)+AVG(x)ne sont pas autorisés.- Pour chaque agrégat tel que
AVG(expr), le correspondantCOUNT(expr)doit ĂȘtre prĂ©sent. Oracle recommande queSOMME(expr)soit spĂ©cifiĂ©.- Si
VARIANCE(expr)orĂCART TYPE(expr) est spĂ©cifiĂ©,COUNT(expr)andSOMME(expr)doit ĂȘtre spĂ©cifiĂ©. Oracle recommande queSOMME(expr *expr)soit spĂ©cifiĂ©.- Le
SELECTla colonne dans la requĂȘte dĂ©finissant ne peut pas ĂȘtre une expression complexe avec des colonnes provenant de plusieurs tables de base. Un possible contournement Ă cela est d'utiliser une vue matĂ©rialisĂ©e imbriquĂ©e.- Le
SELECTla liste doit contenir toutesGROUPEPARles colonnes.- La vue matérialisée n'est pas basée sur une ou plusieurs tables distantes.
- Si vous utilisez un
CHARtype de donnĂ©es dans les colonnes filtrĂ©es d'un journal de vues matĂ©rialisĂ©es, les ensembles de caractĂšres du site maĂźtre et de la vue matĂ©rialisĂ©e doivent ĂȘtre les mĂȘmes.- Si la vue matĂ©rialisĂ©e a l'une des Ă©lĂ©ments suivants, alors le rafraĂźchissement rapide est supportĂ© uniquement sur des inserts DML conventionnels et des chargements directs.
- Vues matérialisées avec
MINorMAXagrégats- Vues matérialisées qui ont
SOMME(expr)mais pas deCOUNT(expr)- Vues matérialisées sans
COUNT(*)Une telle vue matérialisée est appelée une vue matérialisée insérable uniquement.
- Une vue matérialisée avec
MAXorMINest rafraĂźchissable rapidement aprĂšs des suppressions ou des dĂ©clarations DML mixtes si elle n'a pas unOĂclause.
Le rafraĂźchissement rapide max/min aprĂšs des suppressions ou des DML mixtes n'a pas le mĂȘme comportement que le cas insĂ©rable uniquement. Il supprime et recompute les valeurs max/min pour les groupes affectĂ©s. Vous devez ĂȘtre conscient de son impact sur les performances.- Les vues matĂ©rialisĂ©es avec des vues nommĂ©es ou des sous-requĂȘtes dans la
DEclause peuvent ĂȘtre rafraĂźchies rapidement Ă condition que les vues puissent ĂȘtre entiĂšrement fusionnĂ©es. Pour des informations sur les vues qui seront fusionnĂ©es, voir .- S'il n'y a pas de jointures externes, vous pouvez avoir des sĂ©lections et des jointures arbitraires dans le
OĂclause.- Les vues agrĂ©gĂ©es matĂ©rialisĂ©es avec des jointures externes sont rafraĂźchissables rapidement aprĂšs un DML conventionnel et des chargements directs, Ă condition que seule la table externe ait Ă©tĂ© modifiĂ©e. De plus, des contraintes uniques doivent exister sur les colonnes de jointure de la table de jointure interne. S'il y a des jointures externes, toutes les jointures doivent ĂȘtre connectĂ©es par
ANDet doivent utiliser l'égalité (=) l'opérateur.- Pour les vues matérialisées avec
CUBE,ROLLUP, des ensembles de regroupement, ou leur concaténation, les restrictions suivantes s'appliquent :
- Le
SELECTla liste doit contenir un identifiant de regroupement qui peut ĂȘtre soit unGROUPING_IDfonction sur toutes lesGROUPEPARexpressions ouGROUPINGfonctions, une pour chaqueGROUPEPARexpression. Par exemple, si laGROUPEPARclause de la vue matĂ©rialisĂ©e est «GROUPEPARCUBE(a, b)«, alors laSELECTliste doit contenir soit «GROUPING_ID(a, b)» ou «GROUPING(a)ANDGROUPING(b)» pour que la vue matĂ©rialisĂ©e soit rafraĂźchissable rapidement.GROUPEPARne doit pas aboutir Ă des regroupements par duplicata. Par exemple, «GROUP BY a, ROLLUP(a, b)» n'est pas rapidement rafraĂźchissable car elle aboutit Ă des regroupements par duplicata «(a), (a, b), ET (a)«.5.3.8.7 Restrictions sur le RafraĂźchissement Rapide des Vues MatĂ©rialisĂ©es avec UNION ALL
Les vues matérialisées avec l'opérateur
UNION, ousupportent l'optionREFRESHFASTsi les conditions suivantes sont respectées :
- La requĂȘte dĂ©finissant doit avoir l'opĂ©rateur au niveau supĂ©rieur.
UNION, oul'opĂ©rateur ne peut pas ĂȘtre intĂ©grĂ© dans une sous-requĂȘte, exceptĂ© dans une exception : leLe
UNION, oupeut ĂȘtre dans une sous-requĂȘte dans laUNION, ouclause Ă condition que la requĂȘte dĂ©finissant soit de la formeDESELECT * FROM(vue ou sous-requĂȘte avec) comme dans l'exemple suivant :UNION, ouCREATE 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;Notez que la vueview_with_unionall
satisfait les exigences pour un rafraĂźchissement rapide.Chaque bloc de requĂȘte dans la- requĂȘte doit satisfaire aux exigences d'une vue matĂ©rialisĂ©e rapidement rafraĂźchissable avec des agrĂ©gats ou d'une vue matĂ©rialisĂ©e rapidement rafraĂźchissable avec des jointures.
UNION, ouLes journaux de vue matĂ©rialisĂ©e appropriĂ©s doivent ĂȘtre créés sur les tables comme requis pour le type correspondant de vue matĂ©rialisĂ©e rapidement rafraĂźchissable.Notez que la base de donnĂ©es Oracle permet Ă©galement le cas particulier d'une vue matĂ©rialisĂ©e avec jointures uniquement, Ă condition que la
colonne ait Ă©tĂ© incluse dans laROWIDliste et dans le journal de la vue matĂ©rialisĂ©e. Cela est montrĂ© dans la requĂȘte dĂ©finissant la vue.SELECTla liste de chaque requĂȘte doit inclure unsatisfait les exigences pour un rafraĂźchissement rapide..- Le
SELECTmarqueur, et laUNION, oucolonne doit avoir une valeur numĂ©rique ou de chaĂźne constante distincte dans chaqueUNION, oubranche. De plus, la colonne de marqueur doit apparaĂźtre dans la mĂȘme position ordinale dans laUNION, ouliste de chaque bloc de requĂȘte. Voir «SELECTUNION ALL Marker and Query Rewriteles marqueurs.UNION, ouCertaines fonctionnalitĂ©s, telles que les jointures externes, les requĂȘtes de vues matĂ©rialisĂ©es agrĂ©gĂ©es en mode insertion uniquement et les tables distantes ne sont pas prises en charge pour les vues matĂ©rialisĂ©es avec- . Notez cependant que les vues matĂ©rialisĂ©es utilisĂ©es dans la rĂ©plication, qui ne contiennent ni jointures ni agrĂ©gats, peuvent ĂȘtre rafraĂźchies rapidement lorsque
UNION, ouou des tables distantes sont utilisĂ©es.UNION, ouLe paramĂštre d'initialisation de compatibilitĂ© doit ĂȘtre rĂ©glĂ© sur 9.2.0 ou plus pour crĂ©er une vue matĂ©rialisĂ©e rafraĂźchissable rapidement avec- Le paramĂštre d'initialisation de compatibilitĂ© doit ĂȘtre dĂ©fini sur 9.2.0 ou une version supĂ©rieure pour crĂ©er une vue matĂ©rialisĂ©e avec mise Ă jour rapide de
UNION, ou.
Je ne veux pas blesser les fans d'Oracle, mais à en juger par leur liste de limitations, on a l'impression que ce mécanisme n'a pas été conçu de maniÚre générale, en utilisant un modÚle, mais par des milliers d'Indiens à qui on a donné la liberté d'écrire leur propre branche, avec chacun qui a fait ce qu'il a pu. Utiliser ce mécanisme pour de la logique réelle, c'est comme marcher sur un champ de mines. à tout moment, on peut déclencher une mine en tombant sur l'une des limitations non évidentes. Comment cela fonctionne, c'est une autre question, mais cela dépasse le cadre de cet article.
Microsoft SQL Server
Exigences supplémentaires
En plus des options SET et des exigences de fonction dĂ©terministe, les exigences suivantes doivent ĂȘtre satisfaites :
- L'utilisateur qui exécute
CREATE INDEXdoit ĂȘtre le propriĂ©taire de la vue.- Lorsque vous crĂ©ez l'index, lâ
IGNORE_DUP_KEYl'option doit ĂȘtre dĂ©finie sur OFF (paramĂštre par dĂ©faut).- Les tables doivent ĂȘtre rĂ©fĂ©rencĂ©es par des noms en deux parties, schĂ©ma.nom_de_table dans la dĂ©finition de la vue.
- Les fonctions dĂ©finies par l'utilisateur rĂ©fĂ©rencĂ©es dans la vue doivent ĂȘtre créées en utilisant l'option
WITH SCHEMABINDINGTout fonction dĂ©finie par l'utilisateur rĂ©fĂ©rencĂ©e dans la vue doit ĂȘtre rĂ©fĂ©rencĂ©e par des noms en deux parties,- <schĂ©ma> <fonction>.La propriĂ©tĂ© d'accĂšs aux donnĂ©es d'une fonction dĂ©finie par l'utilisateur doit ĂȘtre.
- NO SQL
, et la propriĂ©tĂ© d'accĂšs externe doit ĂȘtreNONLes fonctions de runtime commun (CLR) peuvent apparaĂźtre dans la liste de sĂ©lection de la vue, mais ne peuvent pas faire partie de la dĂ©finition de la clĂ© d'index cluster. Les fonctions CLR ne peuvent pas apparaĂźtre dans la clause WHERE de la vue ou dans la clause ON d'une opĂ©ration JOIN dans la vue..- Les fonctions CLR et les mĂ©thodes des types dĂ©finis par l'utilisateur CLR utilisĂ©s dans la dĂ©finition de la vue doivent avoir les propriĂ©tĂ©s dĂ©finies comme indiquĂ© dans le tableau suivant.
- Remarque
Propriété
DĂTERMINISTIQUE = VRAIDoit ĂȘtre dĂ©clarĂ© explicitement comme un attribut de la mĂ©thode Microsoft .NET Framework.
PRĂCIS = VRAIDoit ĂȘtre dĂ©clarĂ© explicitement comme un attribut de la mĂ©thode .NET Framework.
ACCĂS AUX DONNĂES = AUCUN SQLDĂ©terminĂ© en dĂ©finissant l'attribut DataAccess sur DataAccessKind.None et l'attribut SystemDataAccess sur SystemDataAccessKind.None.
ACCĂS EXTERNE = AUCUNCette propriĂ©tĂ© par dĂ©faut est NON pour les routines CLR.
La vue doit ĂȘtre créée en utilisant le- La vue doit faire uniquement rĂ©fĂ©rence aux tables de base qui se trouvent dans la mĂȘme base de donnĂ©es que la vue. La vue ne peut pas rĂ©fĂ©rencer d'autres vues.
WITH SCHEMABINDINGTout fonction dĂ©finie par l'utilisateur rĂ©fĂ©rencĂ©e dans la vue doit ĂȘtre rĂ©fĂ©rencĂ©e par des noms en deux parties,- La dĂ©claration SELECT dans la dĂ©finition de la vue ne doit pas contenir les Ă©lĂ©ments suivants de Transact-SQL :
- Fonctions ROWSET (
COUNT
OPENDATASOURCEOPENQUERY,OPENROWSET,, ETOPENXMLJOINTS EXTĂRIEURS ()
GAUCHEDROITTable dĂ©rivĂ©e (dĂ©finie en spĂ©cifiant une,dĂ©claration dans la[START WITH âŠ] CONNECT BYFULL)clause)
SELECTAuto-jointsDESpécifiant des colonnes en utilisant
SELECT *
SELECT <nom_de_table>.*STDEVorSTDEVP
DISTINCT
VAR,VARP,Expression de table commune (CTE),ntext[START WITH âŠ] CONNECT BYAVG
XMLfloat1, text, filestream, image, colonnes[START WITH âŠ] CONNECT BY Sous-requĂȘte CLAUSE OVER, qui inclut des fonctions de fenĂȘtre de classement ou d'agrĂ©gation
Prédicats de recherche en texte intégral (
CONTIENTFREETEXTfonction qui référence une expression nullable
Fonction d'agrégation définie par l'utilisateur CLR,TOP)
SOMMEENSEMBLES DE GROUPAGE
ORDER BYopérateurs
EXCEPT
CUBE,ROLLUP[START WITH âŠ] CONNECT BYĂCHANTILLONNERVariables de table
MIN,MAX
UNION,OUTER APPLY[START WITH âŠ] CONNECT BYINTERSECTVariables de table
PIVOTUNPIVOT
Ensembles de colonnes éparsesorCROSS APPLY
Fonctions de table valorisées en ligne (TVF) ou multi-énoncé (MSTVF),CHECKSUM_AGG1 La vue indexée peut contenir
colonnes ; cependant, de telles colonnes ne peuvent pas ĂȘtre incluses dans la clĂ© d'index cluster.
OFFSET
GROUPE PARest présent, la définition de la VUE doit contenir float COUNT_BIG(*)
- Si
et ne doit pas contenir. Cesrestrictions ne s'appliquent qu'Ă la dĂ©finition de la vue indexĂ©e. Une requĂȘte peut utiliser une vue indexĂ©e dans son plan d'exĂ©cution mĂȘme si elle ne respecte pas cesrestrictions.clause avec une sous-requĂȘte.Si la dĂ©finition de la vue contient uneet ne doit pas contenirclause, la clĂ© de l'index cluster unique ne peut faire rĂ©fĂ©rence qu'aux colonnes spĂ©cifiĂ©es dans leet ne doit pas contenirrestrictions.- Si la dĂ©finition de la vue contient un
et ne doit pas contenirclause, la clé de l'index clusterisé unique ne peut référencer que les colonnes spécifiées dans leet ne doit pas contenirclause.
Il est clair que les Indiens n'ont pas été attirés, car ils ont décidé de suivre le schéma "nous ferons peu, mais bien". Cela signifie qu'ils ont plus de mines sur le terrain, mais leur emplacement est plus transparent. Ce qui est le plus décevant, c'est cette restriction :
La déclaration SELECT dans la définition de la vue ne doit pas contenir les éléments suivants de Transact-SQL :
Dans notre terminologie, cela signifie qu'une fonction ne peut pas faire appel à une autre fonction matérialisée. Cela met à mal toute l'idéologie.
Cette restriction (et plus loin dans le texte) réduit considérablement les possibilités d'utilisation :
Fonctions ROWSET (
COUNT
OPENDATASOURCEOPENQUERY,OPENROWSET,, ETOPENXMLJOINTS EXTĂRIEURS ()
GAUCHEDROITTable dĂ©rivĂ©e (dĂ©finie en spĂ©cifiant une,dĂ©claration dans la[START WITH âŠ] CONNECT BYFULL)clause)
SELECTAuto-jointsDESpécifiant des colonnes en utilisant
SELECT *
SELECT <nom_de_table>.*STDEVorSTDEVP
DISTINCT
VAR,VARP,Expression de table commune (CTE),ntext[START WITH âŠ] CONNECT BYAVG
XMLfloat1, text, filestream, image, colonnes[START WITH âŠ] CONNECT BY Sous-requĂȘte CLAUSE OVER, qui inclut des fonctions de fenĂȘtre de classement ou d'agrĂ©gation
Prédicats de recherche en texte intégral (
CONTIENTFREETEXTfonction qui référence une expression nullable
Fonction d'agrégation définie par l'utilisateur CLR,TOP)
SOMMEENSEMBLES DE GROUPAGE
ORDER BYopérateurs
EXCEPT
CUBE,ROLLUP[START WITH âŠ] CONNECT BYĂCHANTILLONNERVariables de table
MIN,MAX
UNION,OUTER APPLY[START WITH âŠ] CONNECT BYINTERSECTVariables de table
PIVOTUNPIVOT
Ensembles de colonnes éparsesorCROSS APPLY
Fonctions de table valorisées en ligne (TVF) ou multi-énoncé (MSTVF),CHECKSUM_AGG1 La vue indexée peut contenir
colonnes ; cependant, de telles colonnes ne peuvent pas ĂȘtre incluses dans la clĂ© d'index cluster.
OFFSET
GROUPE PAR
Les OUTER JOINS, UNION, ORDER BY, et autres sont interdits. Il aurait peut-ĂȘtre Ă©tĂ© plus simple d'indiquer ce qui peut ĂȘtre utilisĂ©, plutĂŽt que ce qui ne peut pas. La liste aurait probablement Ă©tĂ© beaucoup plus courte.
En rĂ©sumĂ© : un vaste ensemble de restrictions dans chaque SGBD (je souligne commercial) vs aucune (Ă l'exception d'une logique, pas technique) dans la technologie LGPL. Cependant, il convient de noter que la mise en Ćuvre de ce mĂ©canisme dans une logique relationnelle est un peu plus complexe que dans la logique fonctionnelle dĂ©crite.
Mise en Ćuvre
Comment cela fonctionne-t-il ? Comme "machine virtuelle", PostgreSQL est utilisĂ©. Ă l'intĂ©rieur, il y a un algorithme complexe qui s'occupe de la construction des requĂȘtes. Voici . Et il n'y a pas simplement un grand nombre d'heuristiques avec une multitude de if. Donc, si vous avez quelques mois pour Ă©tudier, vous pouvez essayer de comprendre l'architecture.
Est-ce que cela fonctionne efficacement ? Assez efficacement. Malheureusement, il est difficile de le prouver. Je ne peux que dire que si l'on considĂšre des milliers de requĂȘtes dans de grandes applications, en moyenne elles sont plus efficaces que celles d'un bon dĂ©veloppeur. Un excellent programmeur SQL peut Ă©crire n'importe quelle requĂȘte de maniĂšre plus efficace, mais sur mille requĂȘtes, il n'a tout simplement ni la motivation ni le temps de le faire. La seule chose que je peux apporter comme preuve d'efficacitĂ© est que plusieurs projets fonctionnent sur une plateforme basĂ©e sur ce SGBD , dans lesquels il y a des milliers de fonctions MATERIALIZED diffĂ©rentes, avec des milliers d'utilisateurs et des bases de donnĂ©es de tĂ©raoctets contenant des centaines de millions d'enregistrements, fonctionnant sur un serveur Ă deux processeurs ordinaire. Cependant, quiconque le souhaite peut vĂ©rifier/rĂ©futer l'efficacitĂ© en tĂ©lĂ©chargeant et PostgreSQL, la journalisation des requĂȘtes SQL et en essayant de modifier la logique et les donnĂ©es.
Dans les articles suivants, je parlerai également de la maniÚre d'imposer des restrictions sur les fonctions, de la gestion des sessions de modifications et bien plus encore.
Source : habr.com
