Το Balance γράφει και διαβάζει στη βάση δεδομένων

Το Balance γράφει και διαβάζει στη βάση δεδομένων
Στο προηγούμενο άρθρο Περιέγραψα την ιδέα και την υλοποίηση μιας βάσης δεδομένων που βασίζεται σε συναρτήσεις και όχι σε πίνακες και πεδία όπως στις σχεσιακές βάσεις δεδομένων. Παρείχε πολλά παραδείγματα που δείχνουν τα πλεονεκτήματα αυτής της προσέγγισης έναντι της κλασικής. Πολλοί τους βρήκαν όχι αρκετά πειστικούς.

Σε αυτό το άρθρο, θα δείξω πώς αυτή η ιδέα σάς επιτρέπει να εξισορροπείτε γρήγορα και άνετα τις εγγραφές και τις αναγνώσεις στη βάση δεδομένων χωρίς καμία αλλαγή στη λογική λειτουργίας. Παρόμοια λειτουργικότητα έχει επιχειρηθεί να εφαρμοστεί σε σύγχρονα εμπορικά DBMS (ιδιαίτερα, Oracle και Microsoft SQL Server). Στο τέλος του άρθρου θα δείξω ότι αυτό που έκαναν, για να το θέσω ήπια, δεν λειτούργησε πολύ καλά.

Περιγραφή

Όπως και πριν, για καλύτερη κατανόηση θα ξεκινήσω την περιγραφή με παραδείγματα. Ας πούμε ότι πρέπει να εφαρμόσουμε μια λογική που θα επιστρέψει μια λίστα τμημάτων με τον αριθμό των εργαζομένων σε αυτά και τον συνολικό μισθό τους.

Σε μια λειτουργική βάση δεδομένων θα μοιάζει με αυτό:

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

Η πολυπλοκότητα της εκτέλεσης αυτού του ερωτήματος σε οποιοδήποτε DBMS θα είναι ισοδύναμη με O (αριθμός εργαζομένων)γιατί αυτός ο υπολογισμός απαιτεί σάρωση ολόκληρου του πίνακα των υπαλλήλων και στη συνέχεια ομαδοποίησή τους ανά τμήμα. Θα υπάρχει επίσης κάποιο μικρό συμπλήρωμα (πιστεύουμε ότι είναι πολύ περισσότεροι οι υπάλληλοι από τα τμήματα) ανάλογα με το επιλεγμένο πρόγραμμα O (αριθμός καταγραφής εργαζομένων) ή O (αριθμός τμημάτων) για ομαδοποίηση και ούτω καθεξής.

Είναι σαφές ότι τα γενικά έξοδα εκτέλεσης μπορεί να είναι διαφορετικά σε διαφορετικά DBMS, αλλά η πολυπλοκότητα δεν θα αλλάξει με κανέναν τρόπο.

Στην προτεινόμενη υλοποίηση, το λειτουργικό DBMS θα δημιουργήσει ένα υποερώτημα που θα υπολογίζει τις απαιτούμενες τιμές για το τμήμα και στη συνέχεια θα κάνει ένα JOIN με τον πίνακα του τμήματος για να αποκτήσει το όνομα. Ωστόσο, για κάθε λειτουργία, κατά τη δήλωση, είναι δυνατό να οριστεί ένας ειδικός δείκτης ΥΛΙΚΟΣ. Το σύστημα θα δημιουργήσει αυτόματα ένα αντίστοιχο πεδίο για κάθε τέτοια λειτουργία. Όταν αλλάζετε την τιμή μιας συνάρτησης, η τιμή του πεδίου θα αλλάξει επίσης στην ίδια συναλλαγή. Κατά την πρόσβαση σε αυτήν τη λειτουργία, θα γίνει πρόσβαση στο προυπολογισμένο πεδίο.

Ειδικότερα, εάν ορίσετε το MATERIALIZED για λειτουργίες καταμέτρηση υπαλλήλων и μισθός Άθροισμα, στη συνέχεια θα προστεθούν δύο πεδία στον πίνακα με τη λίστα των τμημάτων, όπου θα αποθηκεύεται ο αριθμός των εργαζομένων και ο συνολικός μισθός τους. Κάθε φορά που υπάρχει αλλαγή στους υπαλλήλους, στους μισθούς τους ή στις υπηρεσίες τους, το σύστημα θα αλλάζει αυτόματα τις τιμές αυτών των πεδίων. Το παραπάνω ερώτημα θα έχει άμεση πρόσβαση σε αυτά τα πεδία και θα εκτελεστεί σε O (αριθμός τμημάτων).

Ποιοι είναι οι περιορισμοί; Μόνο ένα πράγμα: μια τέτοια συνάρτηση πρέπει να έχει έναν πεπερασμένο αριθμό τιμών εισόδου για τις οποίες ορίζεται η τιμή της. Διαφορετικά, θα είναι αδύνατο να δημιουργηθεί ένας πίνακας που να αποθηκεύει όλες τις τιμές του, αφού δεν μπορεί να υπάρχει πίνακας με άπειρο αριθμό σειρών.

Παράδειγμα:

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

Αυτή η συνάρτηση ορίζεται για έναν άπειρο αριθμό τιμών N (για παράδειγμα, οποιαδήποτε αρνητική τιμή είναι κατάλληλη). Επομένως, δεν μπορείτε να βάλετε ΥΛΙΚΟ σε αυτό. Αυτός λοιπόν είναι ένας λογικός περιορισμός, όχι τεχνικός (δηλαδή, όχι επειδή δεν μπορέσαμε να τον εφαρμόσουμε). Διαφορετικά, δεν υπάρχουν περιορισμοί. Μπορείτε να χρησιμοποιήσετε ομαδοποιήσεις, ταξινόμηση, AND και OR, PARTITION, recursion κ.λπ.

Για παράδειγμα, στο πρόβλημα 2.2 του προηγούμενου άρθρου, μπορείτε να βάλετε MATERIALIZED και στις δύο συναρτήσεις:

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;

Το ίδιο το σύστημα θα δημιουργήσει έναν πίνακα με πλήκτρα τύπου Πελάτης, Προϊόν и ΑΚΕΡΑΙΟΣ ΑΡΙΘΜΟΣ, θα προσθέσει δύο πεδία σε αυτό και θα ενημερώσει τις τιμές των πεδίων σε αυτά με τυχόν αλλαγές. Όταν γίνονται περαιτέρω κλήσεις σε αυτές τις συναρτήσεις, δεν θα υπολογίζονται, αλλά οι τιμές θα διαβάζονται από τα αντίστοιχα πεδία.

Χρησιμοποιώντας αυτόν τον μηχανισμό, μπορείτε, για παράδειγμα, να απαλλαγείτε από τις αναδρομές (CTE) σε ερωτήματα. Ειδικότερα, εξετάστε τις ομάδες που σχηματίζουν ένα δέντρο χρησιμοποιώντας τη σχέση παιδιού/γονέα (κάθε ομάδα έχει έναν σύνδεσμο με τον γονέα της):

parent = DATA Group (Group);

Σε μια λειτουργική βάση δεδομένων, η λογική αναδρομής μπορεί να καθοριστεί ως εξής:

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;

Αφού για τη λειτουργία είναι Γονέας επισημαίνεται ΥΛΙΚΟ, τότε θα δημιουργηθεί ένας πίνακας με δύο κλειδιά (ομάδες) για αυτόν, στον οποίο το πεδίο είναι Γονέας θα ισχύει μόνο αν το πρώτο κλειδί είναι παιδί του δεύτερου. Ο αριθμός των καταχωρήσεων σε αυτόν τον πίνακα θα είναι ίσος με τον αριθμό των ομάδων πολλαπλασιασμένος με το μέσο βάθος του δέντρου. Εάν χρειάζεστε, για παράδειγμα, να μετρήσετε τον αριθμό των απογόνων μιας συγκεκριμένης ομάδας, μπορείτε να χρησιμοποιήσετε αυτήν τη συνάρτηση:

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

Δεν θα υπάρχει CTE στο ερώτημα SQL. Αντίθετα θα υπάρχει ένα απλό GROUP BY.

Χρησιμοποιώντας αυτόν τον μηχανισμό, μπορείτε επίσης να αποκανονικοποιήσετε εύκολα τη βάση δεδομένων εάν είναι απαραίτητο:

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

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

Όταν καλείτε μια λειτουργία Ραντεβού για τη γραμμή παραγγελίας, το πεδίο για το οποίο υπάρχει ευρετήριο θα διαβαστεί από τον πίνακα με τις γραμμές παραγγελίας. Όταν αλλάξει η ημερομηνία παραγγελίας, το ίδιο το σύστημα θα υπολογίσει ξανά αυτόματα την ημερομηνία αποκανονικής λειτουργίας στη γραμμή.

Πλεονεκτήματα

Σε τι χρησιμεύει όλος αυτός ο μηχανισμός; Στα κλασικά DBMS, χωρίς επανεγγραφή ερωτημάτων, ένας προγραμματιστής ή DBA μπορεί να αλλάξει μόνο ευρετήρια, να καθορίσει στατιστικά στοιχεία και να πει στον προγραμματιστή ερωτημάτων πώς να τα εκτελέσει (και τα HINT είναι διαθέσιμα μόνο σε εμπορικά DBMS). Όσο και να προσπαθήσουν, δεν θα μπορέσουν να ολοκληρώσουν το πρώτο ερώτημα στο άρθρο στο O (αριθμός τμημάτων) χωρίς αλλαγή ερωτημάτων ή προσθήκη κανόνων. Στο προτεινόμενο σχήμα, στο στάδιο ανάπτυξης δεν χρειάζεται να σκεφτείτε τη δομή αποθήκευσης δεδομένων και ποιες συναθροίσεις θα χρησιμοποιήσετε. Όλα αυτά μπορούν εύκολα να αλλάξουν εν κινήσει, απευθείας σε λειτουργία.

Στην πράξη μοιάζει με αυτό. Μερικοί άνθρωποι αναπτύσσουν τη λογική απευθείας με βάση την εργασία που εκτελούν. Δεν κατανοούν τους αλγόριθμους και την πολυπλοκότητά τους, ούτε σχέδια εκτέλεσης, ούτε τύπους συνδέσεων, ούτε οποιοδήποτε άλλο τεχνικό στοιχείο. Αυτοί οι άνθρωποι είναι περισσότερο επιχειρησιακοί αναλυτές παρά προγραμματιστές. Στη συνέχεια, όλα αυτά περνούν σε δοκιμή ή λειτουργία. Επιτρέπει την καταγραφή μακροχρόνιων ερωτημάτων. Όταν εντοπίζεται ένα μεγάλο ερώτημα, τότε άλλα άτομα (πιο τεχνικά - ουσιαστικά DBA) αποφασίζουν να ενεργοποιήσουν το MATERIALIZED σε κάποια ενδιάμεση συνάρτηση. Αυτό επιβραδύνει λίγο την εγγραφή (καθώς απαιτεί ενημέρωση ενός επιπλέον πεδίου στη συναλλαγή). Ωστόσο, όχι μόνο αυτό το ερώτημα επιταχύνεται σημαντικά, αλλά και όλα τα άλλα που χρησιμοποιούν αυτήν τη λειτουργία. Ταυτόχρονα, είναι σχετικά εύκολο να αποφασίσετε ποια συνάρτηση θα υλοποιηθεί. Δύο κύριες παράμετροι: ο αριθμός των πιθανών τιμών εισαγωγής (αυτό είναι πόσες εγγραφές θα υπάρχουν στον αντίστοιχο πίνακα) και πόσο συχνά χρησιμοποιείται σε άλλες συναρτήσεις.

Αναλόγους

Τα σύγχρονα εμπορικά DBMS έχουν παρόμοιους μηχανισμούς: ΥΛΙΚΗ ΠΡΟΒΟΛΗ με ΓΡΗΓΟΡΗ ΑΝΑΝΕΩΣΗ (Oracle) και ΠΡΟΒΟΛΗ ΕΥΡΕΤΗΡΙΟΥ (Microsoft SQL Server). Στην PostgreSQL, το MATERIALIZED VIEW δεν μπορεί να ενημερωθεί σε μια συναλλαγή, αλλά μόνο κατόπιν αιτήματος (και μάλιστα με πολύ αυστηρούς περιορισμούς), επομένως δεν το εξετάζουμε. Έχουν όμως αρκετά προβλήματα που περιορίζουν σημαντικά τη χρήση τους.

Πρώτον, μπορείτε να ενεργοποιήσετε την υλοποίηση μόνο εάν έχετε ήδη δημιουργήσει μια κανονική ΠΡΟΒΟΛΗ. Διαφορετικά, θα πρέπει να ξαναγράψετε τα υπόλοιπα αιτήματα για πρόσβαση στην προβολή που δημιουργήθηκε πρόσφατα για να χρησιμοποιήσετε αυτήν την υλοποίηση. Ή αφήστε τα πάντα ως έχουν, αλλά θα είναι τουλάχιστον αναποτελεσματικό εάν υπάρχουν ορισμένα ήδη προυπολογισμένα δεδομένα, αλλά πολλά ερωτήματα δεν τα χρησιμοποιούν πάντα, αλλά τα υπολογίζουν εκ νέου.

Δεύτερον, έχουν τεράστιο αριθμό περιορισμών:

μαντείο

5.3.8.4 Γενικοί περιορισμοί στη γρήγορη ανανέωση

Το καθοριστικό ερώτημα της υλοποιημένης προβολής περιορίζεται ως εξής:

  • Η υλοποιημένη προβολή δεν πρέπει να περιέχει αναφορές σε μη επαναλαμβανόμενες εκφράσεις όπως SYSDATE και ROWNUM.
  • Η υλοποιημένη άποψη δεν πρέπει να περιέχει αναφορές σε RAW or LONG RAW τύπους δεδομένων.
  • Δεν μπορεί να περιέχει α SELECT υποερώτημα λίστας.
  • Δεν μπορεί να περιέχει αναλυτικές συναρτήσεις (για παράδειγμα, RANK) στο SELECT ρήτρα.
  • Δεν μπορεί να αναφέρεται σε έναν πίνακα στον οποίο ένα XMLIndex ορίζεται ευρετήριο.
  • Δεν μπορεί να περιέχει α MODEL ρήτρα.
  • Δεν μπορεί να περιέχει α HAVING ρήτρα με υποερώτημα.
  • Δεν μπορεί να περιέχει ένθετα ερωτήματα που έχουν ANY, ALL, ή NOT EXISTS.
  • Δεν μπορεί να περιέχει α [START WITH …] CONNECT BY ρήτρα.
  • Δεν μπορεί να περιέχει πολλούς πίνακες λεπτομερειών σε διαφορετικούς ιστότοπους.
  • ON COMMIT Οι υλοποιημένες προβολές δεν μπορούν να έχουν πίνακες απομακρυσμένων λεπτομερειών.
  • Οι ένθετες υλοποιημένες προβολές πρέπει να έχουν σύνδεσμο ή άθροισμα.
  • Υλοποιημένες ενώσεις προβολών και υλοποιημένες συγκεντρωτικές απόψεις με α GROUP BY Ο όρος δεν μπορεί να επιλέξει από έναν πίνακα οργανωμένο με ευρετήριο.

5.3.8.5 Περιορισμοί στη γρήγορη ανανέωση σε υλοποιημένες προβολές μόνο με συνδέσεις

Ο καθορισμός ερωτημάτων για υλοποιημένες προβολές μόνο με ενώσεις και χωρίς συγκεντρωτικά στοιχεία έχει τους ακόλουθους περιορισμούς στη γρήγορη ανανέωση:

  • Όλοι οι περιορισμοί από «Γενικοί περιορισμοί στη γρήγορη ανανέωση".
  • Δεν μπορούν να έχουν GROUP BY ρήτρες ή συγκεντρωτικά μεγέθη.
  • Σειρές όλων των τραπεζιών στο FROM η λίστα πρέπει να εμφανίζεται στο SELECT λίστα του ερωτήματος.
  • Τα αρχεία καταγραφής υλοποιημένης προβολής πρέπει να υπάρχουν με σειρές για όλους τους βασικούς πίνακες στο FROM λίστα του ερωτήματος.
  • Δεν μπορείτε να δημιουργήσετε μια υλοποιημένη προβολή με δυνατότητα γρήγορης ανανέωσης από πολλούς πίνακες με απλές ενώσεις που περιλαμβάνουν μια στήλη τύπου αντικειμένου στο SELECT δήλωση.

Επίσης, η μέθοδος ανανέωσης που θα επιλέξετε δεν θα είναι βέλτιστα αποτελεσματική εάν:

  • Το καθοριστικό ερώτημα χρησιμοποιεί μια εξωτερική ένωση που συμπεριφέρεται σαν μια εσωτερική ένωση. Εάν το καθοριστικό ερώτημα περιέχει μια τέτοια ένωση, εξετάστε το ενδεχόμενο να ξαναγράψετε το καθοριστικό ερώτημα ώστε να περιέχει μια εσωτερική ένωση.
  • Η SELECT η λίστα της υλοποιημένης προβολής περιέχει εκφράσεις σε στήλες από πολλούς πίνακες.

5.3.8.6 Περιορισμοί στη γρήγορη ανανέωση σε υλοποιημένες προβολές με συγκεντρωτικά στοιχεία

Ο καθορισμός ερωτημάτων για υλοποιημένες προβολές με συγκεντρωτικά στοιχεία ή ενώσεις έχουν τους ακόλουθους περιορισμούς στη γρήγορη ανανέωση:

Η γρήγορη ανανέωση υποστηρίζεται και για τα δύο ON COMMIT και ON DEMAND υλοποιήθηκαν απόψεις, ωστόσο ισχύουν οι ακόλουθοι περιορισμοί:

  • Όλοι οι πίνακες στην υλοποιημένη προβολή πρέπει να έχουν αρχεία καταγραφής υλοποιημένης προβολής και τα αρχεία καταγραφής υλοποιημένης προβολής πρέπει:
    • Περιέχει όλες τις στήλες από τον πίνακα που αναφέρεται στην υλοποιημένη προβολή.
    • Καθορίστε με ROWID και INCLUDING NEW VALUES.
    • Καθορίστε το SEQUENCE ρήτρα εάν ο πίνακας αναμένεται να έχει έναν συνδυασμό από ένθετα/άμεσες φορτώσεις, διαγραφές και ενημερώσεις.

  • Μόνο SUM, COUNT, AVG, STDDEV, VARIANCE, MIN και MAX υποστηρίζονται για γρήγορη ανανέωση.
  • COUNT(*) πρέπει να διευκρινιστεί.
  • Οι αθροιστικές συναρτήσεις πρέπει να εμφανίζονται μόνο ως το πιο εξωτερικό μέρος της έκφρασης. Δηλαδή αδρανή όπως π.χ AVG(AVG(x)) or AVG(x)+ AVG(x) δεν επιτρέπονται.
  • Για κάθε άθροισμα όπως π.χ AVG(expr), το αντίστοιχο COUNT(expr) πρέπει να είναι παρών. Η Oracle το συνιστά SUM(expr) να καθοριστεί.
  • If VARIANCE(expr) or STDDEV(expr) καθορίζεται, COUNT(expr) και SUM(expr) πρέπει να διευκρινιστεί. Η Oracle το συνιστά SUM(expr *expr) να καθοριστεί.
  • Η SELECT Η στήλη στο καθοριστικό ερώτημα δεν μπορεί να είναι μια σύνθετη έκφραση με στήλες από πολλούς πίνακες βάσης. Μια πιθανή λύση σε αυτό είναι η χρήση μιας ένθετης υλοποιημένης προβολής.
  • Η SELECT η λίστα πρέπει να περιέχει όλα GROUP BY στήλες.
  • Η υλοποιημένη προβολή δεν βασίζεται σε έναν ή περισσότερους απομακρυσμένους πίνακες.
  • Εάν χρησιμοποιείτε a CHAR τύπος δεδομένων στις στήλες φίλτρου ενός αρχείου καταγραφής υλοποιημένης προβολής, τα σύνολα χαρακτήρων της κύριας τοποθεσίας και της υλοποιημένης προβολής πρέπει να είναι τα ίδια.
  • Εάν η υλοποιημένη προβολή έχει ένα από τα ακόλουθα, τότε η γρήγορη ανανέωση υποστηρίζεται μόνο σε συμβατικά ένθετα DML και απευθείας φορτώσεις.
    • Υλοποιημένες απόψεις με MIN or MAX αδρανών υλικών
    • Υλοποιημένες απόψεις οι οποίες έχουν SUM(expr) αλλά όχι COUNT(expr)
    • Υλοποιημένες απόψεις χωρίς COUNT(*)

    Μια τέτοια υλοποιημένη άποψη ονομάζεται υλοποιημένη προβολή μόνο με ένθετο.

  • Μια υλοποιημένη άποψη με MAX or MIN ανανεώνεται γρήγορα μετά από διαγραφή ή ανάμειξη δηλώσεων DML, εάν δεν έχει α WHERE ρήτρα.
    Η μέγιστη/λεπτή γρήγορη ανανέωση μετά τη διαγραφή ή την ανάμειξη DML δεν έχει την ίδια συμπεριφορά με την περίπτωση μόνο για εισαγωγή. Διαγράφει και υπολογίζει εκ νέου τις μέγιστες/ελάχιστες τιμές για τις ομάδες που επηρεάζονται. Πρέπει να γνωρίζετε τον αντίκτυπό του στην απόδοση.
  • Υλοποιημένες απόψεις με επώνυμες προβολές ή υποερωτήματα στο FROM Η ρήτρα μπορεί να ανανεωθεί γρήγορα με την προϋπόθεση ότι οι προβολές μπορούν να συγχωνευθούν πλήρως. Για πληροφορίες σχετικά με το ποιες προβολές θα συγχωνευθούν, βλ Αναφορά γλώσσας βάσης δεδομένων Oracle SQL.
  • Εάν δεν υπάρχουν εξωτερικές συνδέσεις, μπορεί να έχετε αυθαίρετες επιλογές και ενώσεις στο WHERE ρήτρα.
  • Οι υλικές προβολές συγκεντρωτικών στοιχείων με εξωτερικές συνδέσεις μπορούν να ανανεωθούν γρήγορα μετά από συμβατικά DML και άμεσες φορτώσεις, υπό την προϋπόθεση ότι έχει τροποποιηθεί μόνο ο εξωτερικός πίνακας. Επίσης, πρέπει να υπάρχουν μοναδικοί περιορισμοί στις στήλες ένωσης του πίνακα εσωτερικής ένωσης. Εάν υπάρχουν εξωτερικές συνδέσεις, όλες οι συνδέσεις πρέπει να συνδέονται με ANDs και πρέπει να χρησιμοποιήσει την ισότητα (=) χειριστής.
  • Για υλοποιημένες απόψεις με CUBE, ROLLUP, ομαδοποίηση συνόλων ή συνένωση τους, ισχύουν οι ακόλουθοι περιορισμοί:
    • Η SELECT Η λίστα πρέπει να περιέχει διαχωριστικό ομαδοποίησης που μπορεί να είναι είτε α GROUPING_ID λειτουργία σε όλα GROUP BY εκφράσεις ή GROUPING λειτουργίες μία για την καθεμία GROUP BY έκφραση. Για παράδειγμα, εάν το GROUP BY ρήτρα της υλοποιημένης άποψης είναι "GROUP BY CUBE(a, b)", μετά το SELECT η λίστα πρέπει να περιέχει είτε "GROUPING_ID(a, b)" ή "GROUPING(a) AND GROUPING(b)» για να ανανεώνεται γρήγορα η υλοποιημένη όψη.
    • GROUP BY δεν πρέπει να οδηγεί σε διπλότυπες ομαδοποιήσεις. Για παράδειγμα, "GROUP BY a, ROLLUP(a, b)"Δεν ανανεώνεται γρήγορα γιατί οδηγεί σε διπλότυπες ομαδοποιήσεις"(a), (a, b), AND (a)".

5.3.8.7 Περιορισμοί στη γρήγορη ανανέωση σε υλοποιημένες προβολές με UNION ALL

Υλοποιημένες απόψεις με το UNION ALL σετ υποστήριξη χειριστή το REFRESH FAST επιλογή εάν πληρούνται οι ακόλουθες προϋποθέσεις:

  • Το καθοριστικό ερώτημα πρέπει να έχει το UNION ALL χειριστή στο ανώτατο επίπεδο.

    Η UNION ALL Ο τελεστής δεν μπορεί να ενσωματωθεί σε ένα υποερώτημα, με μία εξαίρεση: Το UNION ALL μπορεί να είναι σε ένα υποερώτημα στο FROM ρήτρα με την προϋπόθεση ότι το καθοριστικό ερώτημα είναι της μορφής SELECT * FROM (προβολή ή υποερώτημα με UNION ALL) όπως στο παρακάτω παράδειγμα:

    ΔΗΜΙΟΥΡΓΙΑ ΠΡΟΒΟΛΗΣ view_with_unionall AS (ΕΠΙΛΟΓΗ c.rowid crid, c.cust_id, 2 umarker ΑΠΟ πελάτες c WHERE c.cust_last_name = 'Smith' UNION ALL SELECT c.rowid crid, c.cust_id, 3 umarker ΑΠΟ πελάτες c WHERE_last. «Τζόουνς»); ΔΗΜΙΟΥΡΓΙΑ ΥΛΙΚΟΠΟΙΗΜΕΝΗ ΠΡΟΒΟΛΗ unionall_inside_view_mv ΓΡΗΓΟΡΑ ΑΝΑΝΕΩΣΗ ΚΑΤΑ ΑΠΑΙΤΗΣΗ ΩΣ ΕΠΙΛΟΓΗ * ΑΠΟ view_with_unionall;
    

    Σημειώστε ότι η θέα view_with_unionall ικανοποιεί τις απαιτήσεις για γρήγορη ανανέωση.

  • Κάθε μπλοκ ερωτήματος στο UNION ALL Το ερώτημα πρέπει να ικανοποιεί τις απαιτήσεις μιας γρήγορης ανανέωσης υλοποιημένης προβολής με συγκεντρωτικά στοιχεία ή μιας γρήγορης ανανέωσης υλοποιημένης προβολής με συνδέσεις.

    Τα κατάλληλα αρχεία καταγραφής υλοποιημένης προβολής πρέπει να δημιουργηθούν στους πίνακες, όπως απαιτείται για τον αντίστοιχο τύπο υλοποιημένης προβολής με δυνατότητα γρήγορης ανανέωσης.
    Λάβετε υπόψη ότι η βάση δεδομένων Oracle επιτρέπει επίσης την ειδική περίπτωση μιας ενιαίας υλοποίησης προβολής πίνακα με ενώσεις μόνο εφόσον το ROWID στήλη έχει συμπεριληφθεί στο SELECT λίστα και στο αρχείο καταγραφής υλοποιημένης προβολής. Αυτό φαίνεται στο καθοριστικό ερώτημα της προβολής view_with_unionall.

  • Η SELECT η λίστα κάθε ερωτήματος πρέπει να περιλαμβάνει α UNION ALL μαρκαδόρος, και το UNION ALL Η στήλη πρέπει να έχει μια ξεχωριστή σταθερή αριθμητική ή συμβολοσειρά τιμή σε καθεμία UNION ALL κλαδί. Επιπλέον, η στήλη δείκτη πρέπει να εμφανίζεται στην ίδια τακτική θέση στο SELECT λίστα κάθε μπλοκ ερωτημάτων. Βλέπω "UNION ALL Marker and Query Rewrite» για περισσότερες πληροφορίες σχετικά με UNION ALL δείκτες.
  • Ορισμένες δυνατότητες, όπως εξωτερικές ενώσεις, ερωτήματα αθροιστικών υλοποιημένων προβολών μόνο για εισαγωγή και απομακρυσμένοι πίνακες δεν υποστηρίζονται για υλοποιημένες προβολές με UNION ALL. Σημειώστε, ωστόσο, ότι οι υλοποιημένες προβολές που χρησιμοποιούνται στην αναπαραγωγή, οι οποίες δεν περιέχουν ενώσεις ή συγκεντρωτικά στοιχεία, μπορούν να ανανεωθούν γρήγορα όταν UNION ALL ή χρησιμοποιούνται απομακρυσμένα τραπέζια.
  • Η παράμετρος αρχικοποίησης συμβατότητας πρέπει να οριστεί σε 9.2.0 ή υψηλότερη για να δημιουργηθεί μια υλοποιημένη προβολή με δυνατότητα γρήγορης ανανέωσης με UNION ALL.

Δεν θέλω να προσβάλω τους οπαδούς της Oracle, αλλά κρίνοντας από τη λίστα των περιορισμών τους, φαίνεται ότι αυτός ο μηχανισμός δεν γράφτηκε στη γενική περίπτωση, χρησιμοποιώντας κάποιο είδος μοντέλου, αλλά από χιλιάδες Ινδούς, όπου δόθηκε σε όλους η ευκαιρία να γράψει το δικό του κλάδο και ο καθένας τους έκανε ό,τι μπορούσε και έκανε. Η χρήση αυτού του μηχανισμού για πραγματική λογική είναι σαν να περπατάς μέσα από ένα ναρκοπέδιο. Μπορείτε να αποκτήσετε ορυχείο ανά πάσα στιγμή πατώντας έναν από τους μη προφανείς περιορισμούς. Το πώς λειτουργεί είναι επίσης μια ξεχωριστή ερώτηση, αλλά δεν εμπίπτει στο πεδίο εφαρμογής αυτού του άρθρου.

Microsoft SQL Server

Πρόσθετες απαιτήσεις

Εκτός από τις επιλογές SET και τις ντετερμινιστικές απαιτήσεις λειτουργίας, πρέπει να πληρούνται οι ακόλουθες απαιτήσεις:

  • Ο χρήστης που εκτελεί CREATE INDEX πρέπει να είναι ο κάτοχος της προβολής.
  • Όταν δημιουργείτε το ευρετήριο, το IGNORE_DUP_KEY Η επιλογή πρέπει να οριστεί σε OFF (η προεπιλεγμένη ρύθμιση).
  • Οι πίνακες πρέπει να αναφέρονται με ονόματα δύο μερών, σχέδιο.όνομα πίνακα στον ορισμό της προβολής.
  • Οι συναρτήσεις που καθορίζονται από το χρήστη που αναφέρονται στην προβολή πρέπει να δημιουργηθούν χρησιμοποιώντας το WITH SCHEMABINDING επιλογή.
  • Τυχόν συναρτήσεις που ορίζονται από το χρήστη και αναφέρονται στην προβολή πρέπει να αναφέρονται με ονόματα δύο μερών, ..
  • Η ιδιότητα πρόσβασης δεδομένων μιας συνάρτησης που ορίζεται από το χρήστη πρέπει να είναι NO SQL, και η ιδιότητα εξωτερικής πρόσβασης πρέπει να είναι NO.
  • Οι συναρτήσεις χρόνου εκτέλεσης κοινής γλώσσας (CLR) μπορούν να εμφανίζονται στη λίστα επιλογής της προβολής, αλλά δεν μπορούν να αποτελούν μέρος του ορισμού του κλειδιού ευρετηρίου συμπλέγματος. Οι συναρτήσεις CLR δεν μπορούν να εμφανιστούν στον όρο WHERE της προβολής ή στον όρο ON μιας λειτουργίας JOIN στην προβολή.
  • Οι συναρτήσεις και οι μέθοδοι CLR των τύπων που καθορίζονται από το χρήστη CLR που χρησιμοποιούνται στον ορισμό της προβολής πρέπει να έχουν τις ιδιότητες που έχουν οριστεί όπως φαίνεται στον παρακάτω πίνακα.

    Περιουσία
    Note

    ΝΤΕΤΕΡΜΙΝΙΣΤΙΚΟΣ = ΑΛΗΘΙΝΟΣ
    Πρέπει να δηλωθεί ρητά ως χαρακτηριστικό της μεθόδου Microsoft .NET Framework.

    ΑΚΡΙΒΗ = ΑΛΗΘΕΙΑ
    Πρέπει να δηλωθεί ρητά ως χαρακτηριστικό της μεθόδου .NET Framework.

    ΠΡΟΣΒΑΣΗ ΔΕΔΟΜΕΝΩΝ = ΟΧΙ SQL
    Καθορίζεται ορίζοντας το χαρακτηριστικό DataAccess σε DataAccessKind.None και το χαρακτηριστικό SystemDataAccess σε SystemDataAccessKind.None.

    ΕΞΩΤΕΡΙΚΗ ΠΡΟΣΒΑΣΗ = ΟΧΙ
    Αυτή η ιδιότητα ορίζεται από προεπιλογή σε ΟΧΙ για τις ρουτίνες CLR.

  • Η προβολή πρέπει να δημιουργηθεί χρησιμοποιώντας το WITH SCHEMABINDING επιλογή.
  • Η προβολή πρέπει να αναφέρεται μόνο σε πίνακες βάσης που βρίσκονται στην ίδια βάση δεδομένων με την προβολή. Η προβολή δεν μπορεί να παραπέμπει σε άλλες προβολές.
  • Η πρόταση SELECT στον ορισμό της προβολής δεν πρέπει να περιέχει τα ακόλουθα στοιχεία Transact-SQL:

    COUNT
    Λειτουργίες ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, ΚΑΙ OPENXML)
    OUTER ενώνει (LEFT, RIGHT, ή FULL)

    Πίνακας που προκύπτει (που ορίζεται προσδιορίζοντας α SELECT δήλωση στο FROM ρήτρα)
    Αυτοενώσεις
    Καθορισμός στηλών χρησιμοποιώντας SELECT * or SELECT <table_name>.*

    DISTINCT
    STDEV, STDEVP, VAR, VARP, ή AVG
    Κοινή έκφραση πίνακα (CTE)

    φλοτέρ1, κείμενο, ntext, εικόνα, XML, ή ροή αρχείων στήλες
    Υποερώτημα
    OVER ρήτρα, η οποία περιλαμβάνει κατάταξη ή συγκεντρωτικές συναρτήσεις παραθύρου

    Κατηγορήματα πλήρους κειμένου (CONTAINS, FREETEXT)
    SUM συνάρτηση που αναφέρεται σε μηδενική έκφραση
    ORDER BY

    CLR αθροιστική συνάρτηση που ορίζεται από το χρήστη
    TOP
    CUBE, ROLLUP, ή GROUPING SETS φορείς

    MIN, MAX
    UNION, EXCEPT, ή INTERSECT φορείς
    TABLESAMPLE

    Μεταβλητές πίνακα
    OUTER APPLY or CROSS APPLY
    PIVOT, UNPIVOT

    Αραιά σύνολα στηλών
    Ενσωματωμένες (TVF) ή συναρτήσεις με τιμές πίνακα πολλαπλών δηλώσεων (MSTVF)
    OFFSET

    CHECKSUM_AGG

    1 Η ευρετηριασμένη προβολή μπορεί να περιέχει φλοτέρ στήλες; Ωστόσο, τέτοιες στήλες δεν μπορούν να συμπεριληφθούν στο κλειδί ευρετηρίου συμπλέγματος.

  • If GROUP BY υπάρχει, ο ορισμός VIEW πρέπει να περιέχει COUNT_BIG(*) και δεν πρέπει να περιέχει HAVING. Αυτοί GROUP BY Οι περιορισμοί ισχύουν μόνο για τον ορισμό της ευρετηριασμένης προβολής. Ένα ερώτημα μπορεί να χρησιμοποιήσει μια ευρετηριασμένη προβολή στο σχέδιο εκτέλεσής του, ακόμα κι αν δεν τα ικανοποιεί GROUP BY περιορισμούς.
  • Εάν ο ορισμός της προβολής περιέχει α GROUP BY ρήτρα, το κλειδί του μοναδικού ευρετηρίου συμπλέγματος μπορεί να αναφέρεται μόνο στις στήλες που καθορίζονται στο GROUP BY ρήτρα.

Είναι σαφές εδώ ότι οι Ινδοί δεν συμμετείχαν, αφού αποφάσισαν να το κάνουν σύμφωνα με το σχέδιο "θα κάνουμε λίγα, αλλά καλά". Δηλαδή έχουν περισσότερες νάρκες στο γήπεδο, αλλά η τοποθεσία τους είναι πιο διαφανής. Το πιο απογοητευτικό είναι αυτός ο περιορισμός:

Η προβολή πρέπει να αναφέρεται μόνο σε πίνακες βάσης που βρίσκονται στην ίδια βάση δεδομένων με την προβολή. Η προβολή δεν μπορεί να παραπέμπει σε άλλες προβολές.

Στην ορολογία μας, αυτό σημαίνει ότι μια συνάρτηση δεν μπορεί να έχει πρόσβαση σε μια άλλη υλοποιημένη συνάρτηση. Αυτό περικόπτει κάθε ιδεολογία στο μπουμπούκι.
Επίσης, αυτός ο περιορισμός (και περαιτέρω στο κείμενο) μειώνει σημαντικά τις περιπτώσεις χρήσης:

Η πρόταση SELECT στον ορισμό της προβολής δεν πρέπει να περιέχει τα ακόλουθα στοιχεία Transact-SQL:

COUNT
Λειτουργίες ROWSET (OPENDATASOURCE, OPENQUERY, OPENROWSET, ΚΑΙ OPENXML)
OUTER ενώνει (LEFT, RIGHT, ή FULL)

Πίνακας που προκύπτει (που ορίζεται προσδιορίζοντας α SELECT δήλωση στο FROM ρήτρα)
Αυτοενώσεις
Καθορισμός στηλών χρησιμοποιώντας SELECT * or SELECT <table_name>.*

DISTINCT
STDEV, STDEVP, VAR, VARP, ή AVG
Κοινή έκφραση πίνακα (CTE)

φλοτέρ1, κείμενο, ntext, εικόνα, XML, ή ροή αρχείων στήλες
Υποερώτημα
OVER ρήτρα, η οποία περιλαμβάνει κατάταξη ή συγκεντρωτικές συναρτήσεις παραθύρου

Κατηγορήματα πλήρους κειμένου (CONTAINS, FREETEXT)
SUM συνάρτηση που αναφέρεται σε μηδενική έκφραση
ORDER BY

CLR αθροιστική συνάρτηση που ορίζεται από το χρήστη
TOP
CUBE, ROLLUP, ή GROUPING SETS φορείς

MIN, MAX
UNION, EXCEPT, ή INTERSECT φορείς
TABLESAMPLE

Μεταβλητές πίνακα
OUTER APPLY or CROSS APPLY
PIVOT, UNPIVOT

Αραιά σύνολα στηλών
Ενσωματωμένες (TVF) ή συναρτήσεις με τιμές πίνακα πολλαπλών δηλώσεων (MSTVF)
OFFSET

CHECKSUM_AGG

ΕΞΩΤΕΡΙΚΕΣ ΣΥΝΔΕΣΕΙΣ, ΕΝΩΣΗ, ORDER BY και άλλα απαγορεύονται. Ίσως ήταν πιο εύκολο να προσδιορίσετε τι θα μπορούσε να χρησιμοποιηθεί παρά τι δεν θα μπορούσε να χρησιμοποιηθεί. Η λίστα θα ήταν μάλλον πολύ μικρότερη.

Συνοψίζοντας: ένα τεράστιο σύνολο περιορισμών σε κάθε (ας σημειώσουμε εμπορικό) DBMS έναντι κανενός (με εξαίρεση έναν λογικό, όχι τεχνικό) στην τεχνολογία LGPL. Ωστόσο, πρέπει να σημειωθεί ότι η εφαρμογή αυτού του μηχανισμού στη σχεσιακή λογική είναι κάπως πιο δύσκολη από ό,τι στην περιγραφόμενη λειτουργική λογική.

Реализация

Πως δουλεύει? Η PostgreSQL χρησιμοποιείται ως «εικονική μηχανή». Υπάρχει ένας πολύπλοκος αλγόριθμος μέσα που δημιουργεί ερωτήματα. Εδώ πηγή. Και δεν υπάρχει απλώς ένα μεγάλο σύνολο ευρετικών με ένα σωρό αν. Έτσι, αν έχετε μερικούς μήνες για σπουδές, μπορείτε να προσπαθήσετε να κατανοήσετε την αρχιτεκτονική.

Λειτουργεί αποτελεσματικά; Αρκετά αποτελεσματικό. Δυστυχώς, αυτό είναι δύσκολο να αποδειχθεί. Μπορώ μόνο να πω ότι αν λάβετε υπόψη τα χιλιάδες ερωτήματα που υπάρχουν σε μεγάλες εφαρμογές, τότε κατά μέσο όρο είναι πιο αποτελεσματικά από αυτά ενός καλού προγραμματιστή. Ένας εξαιρετικός προγραμματιστής SQL μπορεί να γράψει οποιοδήποτε ερώτημα πιο αποτελεσματικά, αλλά με χίλιες ερωτήσεις απλά δεν θα έχει το κίνητρο ή το χρόνο να το κάνει. Το μόνο πράγμα που μπορώ τώρα να αναφέρω ως απόδειξη αποτελεσματικότητας είναι ότι πολλά έργα εργάζονται στην πλατφόρμα που είναι χτισμένη σε αυτό το DBMS Συστήματα ERP, που έχουν χιλιάδες διαφορετικές ΥΛΙΚΟΙ συναρτήσεις, με χιλιάδες χρήστες και βάσεις δεδομένων terabyte με εκατοντάδες εκατομμύρια εγγραφές που εκτελούνται σε έναν κανονικό διακομιστή δύο επεξεργαστών. Ωστόσο, ο καθένας μπορεί να ελέγξει/διαψεύσει την αποτελεσματικότητα με λήψη η πλατφόρμα και PostgreSQL, άναψε καταγραφή ερωτημάτων SQL και προσπάθεια αλλαγής της λογικής και των δεδομένων εκεί.

Στα επόμενα άρθρα, θα μιλήσω επίσης για το πώς μπορείτε να ορίσετε περιορισμούς στις λειτουργίες, να εργαστείτε με συνεδρίες αλλαγής και πολλά άλλα.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο