Overview
Όλοι γνωρίζουμε ότι ένα view είναι ένα stored query expression το οποίο ορίζει τι θα επιστρέφει το συγκεκριμένο view. Με απλά λόγια είναι ένα SELECT statement.
Έχουμε τους εξής τύπους view Standard, Indexed, Partitioned και System.
Advantages of Views
Tα πλεονεκτήματα των views είναι και αυτά γνωστά
- Χρησιμοποιούνται για την εστίαση, την απλοποίηση και την προσαρμογή των δεδομένων που έχει κάθε χρήστης της βάσης δεδομένων.
- Μπορούν να χρησιμοποιηθούν ως μηχανισμοί ασφαλείας, επιτρέποντας στους χρήστες να έχουν πρόσβαση σε δεδομένα μέσω της αυτών, χωρίς να εκχωρηθούν δικαιώματα στους χρήστες για άμεση πρόσβαση στους υποκείμενους βασικούς πίνακες που αυτά χρησιμοποιούν.
- Μπορούν να χρησιμοποιηθούν για την backward compatibility ή την εξομοίωση ενός πίνακα που υπήρχε, αλλά του οποίου το σχήμα έχει αλλάξει.
- Μπορούν επίσης να χρησιμοποιηθούν κατά την αντιγραφή δεδομένων από και προς τον SQL Server για τη βελτίωση των επιδόσεων και την κατάτμηση δεδομένων.
The Problem
Με όλα αυτά που προσφέρουν χρόνια τώρα τις χρησιμοποιούμε όλοι και κάνουμε την δουλειά μας, όμως τις φτιάχνουμε σωστά ώστε να δουλεύουν και σωστά;
Δυστυχώς η εμπειρία μου δείχνει ότι δεν γίνεται αυτό με αποτέλεσμα να λένε κάποιοι ότι δεν είναι καλά τα views αλλά η πραγματικότητά είναι άλλη.
Όλα ξεκινάνε από το ποιος είναι ο συγγραφέας του view και πόσο έχει ασχοληθεί με το αντικείμενο των RDBMS. Αν αυτός είναι δεν γνωρίζει τις βασικές αρχές τότε έχουμε προβλήματα.
Το ποιο κοινό λάθος που τόσα χρόνια βλέπω είναι να δημιουργείται ένα view το οποίο κάνει χρήση άλλου view το οποίο κάνει χρήση άλλου view το οποίο πατάει σε άλλο και αυτό μπορεί να συνεχιστεί σε πολλά επίπεδα nesting.
Δεν είμαι αντίθετος στην χρήση view σε view αρκεί αυτό να γίνεται με τον σωστό τρόπο. Ποιος είναι αυτός;
Η αποφυγή της λογικής του inheritance.
Σε όλες τις σύγχρονες γλώσσες προγραμματισμού μαθαίνουμε και χρησιμοποιούμε Object Oriented Programming και αρκετοί είναι ενθουσιασμένοι με αυτό. Δεν θα πω κάτι αντίθετο αλλά και σε αυτό υπάρχει ένα όριο στη χρήση που δυστυχώς δεν τηρείται με αποτέλεσμα και εδώ να υπάρχουν ζητήματα απόδοσης αλλά και άσκοπης περιπλοκότητας.
Αυτή την λογική αρκετοί την χρησιμοποιούν και στην δημιουργία των views και αυτό είναι παντελώς λάθος (IMHO) γιατί;
Η απάντηση είναι απλή. Διάβασμα των ίδιων πινάκων και δεδομένων πολλές φορές. Αυτό οδηγεί σε άσκοπα scans που φυσικά δεν είναι ότι καλύτερο για την απόδοση.
Solution
Πως γίνεται αυτό; Πολύ εύκολα.
Έχουμε τον Α που φτιάχνει ένα view που χρησιμοποιεί ένα query που μπορεί να είναι απλό ή και σύνθετο δεν έχει σημασία το οποίο επιστρέφει κάποια δεδομένα και μέσα σε αυτά υπάρχουν τέτοια που προέρχονται από expressions ή aggregations.
Θέλει ο Β στο αποτέλεσμα του Α να βάλει κάποια ακόμα δεδομένα οπότε χρησιμοποιεί το Α και βάζει και τα δικά του.
Το ίδιο μπορεί να κάνει και ο Γ στα αποτελέσματα του Β και αυτό μπορεί να συνεχιστεί αρκετές φορές.
Κάθε φορά που στα σεμινάρια που κάνω το λέω αυτό η αντίδραση είναι η ίδια και συνοψίζεται στην πρόταση «Μα αφού είναι έτοιμα γιατί να τα φτιάξω ξανά».
Δύσκολα μπορείς να πείσεις κάποιον με αυτή την αντίληψη και συνήθεια, καθώς το πρώτο και βασικό επιχείρημα που θα προβάλλει είναι ότι με αυτό τον τρόπο κάνει λιγότερες αλλαγές στο κώδικα αν χρειαστεί κάτι να προσθέσει όπως πχ ένα ακόμα πεδίο (λογική developer που για αυτό το λόγο δεν θέλει τα RDBMS και θέλει τα NoSQL γιατί πιστεύει ότι με αυτά δεν έχει πρόβλημα).
Ναι όλοι θέλουμε να έχουμε αυτή την δυνατότητα στο κώδικα μας όμως δεν πρέπει να είναι αυτό το πρώτο μέλημα μας.
Η απόδοση είναι αυτό που πρέπει να εστιάζουμε καθώς με αυτό κρίνονται οι εφαρμογές μας από τους χρήστες και όχι από το πόσο ωραίο και δομημένο κώδικα έχουμε φτιάξει (και καλά κάνουμε) καθώς δεν βλέπουν αυτόν αλλά το πως αυτός συμπεριφέρεται.
Δεν υπάρχει μαγική συνταγή για ένα καλό view. Για να φτιάξει κανείς ένα καλό view θα πρέπει να ξέρει τι θέλει να φτιάξει που θα βρει τα δεδομένα και το σημαντικό να ξέρει πως εκτελείται ένα query και ποια είναι η αρχιτεκτονική του RBDMS (στην προκειμένη περίπτωση του SQL Server).
Το να φτιάξει κανείς ένα view που πατάει σε ένα άλλο view που είναι πχ join κάποιον πινάκων και θέλει να προσθέσει δεδομένα από κάποιους πίνακες που δεν είναι στο αρχικό view δεν είναι κακή πρακτική. Αντίθετα το να φτιάξει ένα view για να προσθέσει σε αυτό κάποια πεδία από τους πίνακες που το αρχικό περιέχει είναι κακή πρακτική διότι κάνει ξανά join αυτούς ή αυτόν με αποτέλεσμα να διαβάζονται ξανά τα δεδομένα. Φανταστείτε αυτό να γίνεται σε πολλαπλά επίπεδα, είναι απίστευτα δαπανηρό και δεν σε σώζει κανένας index. Σε αυτή την περίπτωση θα πρέπει να φτιάξει ένα νέο που να εξυπηρετεί την συγκεκριμένη ανάγκη το οποίο να είναι όπως το προηγούμενο με την προσθήκη των νέων δεδομένων. Εξάλλου αυτό είναι ένα από τα πλεονεκτήματα των views όπως ανέφερα και παραπάνω.
Conclusion
Έχω πολλά παραδείγματα από views με αυτή την λογική που διαβάζουν τον ίδιο πίνακα πολλές φορές και έκαναν από πολλά λεπτά της ώρας μέχρι ώρες για να εκτελεστούν και πλέον κάνουν δευτερόλεπτα ή λίγα λεπτά της ώρας με την νέα τους λογική. (με μερικούς από εσάς που διαβάζουν το άρθρο αυτό έχουμε συνεργαστεί και έχουμε λύσει τέτοια προβλήματα).
Αυτό που θέλω από εσάς την επόμενη φορά που θα φτιάξετε ένα view είναι να σκεφτείτε απλά ότι πρέπει να αποφύγετε να διαβάζετε τον ίδιο πίνακα πολλές φορές. Αν αυτό γίνεται μέσα από χρήση άλλων views φτιάξτε ένα νέο.
//antonch