Αφού έχουμε σχεδιάσει λογικά και σύμφωνα με τις επιχειρησιακές απαιτήσεις το DW μας, φτάνει η στιγμή που πρέπει να το κάνουμε πραγματικότητα υλοποιώντας το φυσικά.
Όπως έχω αναφέρει σε όλα τα προηγούμενα post αυτής της σειράς θα πρέπει φυσικά να υλοποιήσω το DW λαμβάνοντας σοβαρά υπόψη μου τους εξής παράγοντες που δεν είναι άλλοι από τους
performance,
scalability,
manageability.
Με αυτούς σαν πυξίδα θα πρέπει να
Tips for Database Files
- Η database που θα δημιουργήσω για το DW θα πρέπει να έχει κάνει preallocate το χώρο που χρειάζομαι και όχι να είναι auto growth το μέγεθος της. Αυτό πρέπει να γίνει ώστε να μειώσω το table και index fragmentation το οποίο όπως είναι γνωστό έχει σαν αποτέλεσμα να επηρεάζει αρνητικά το performance. Με την τεχνική αυτή επιτυγχάνω το παραπάνω.
- Σε συνέχεια του προηγούμενου θα πρέπει να επισημανθεί ότι επειδή σε ένα DW κατά τις φάσεις όπου γίνονται ενημερώσεις (διαδικασίες ETL) σε αυτό από τις πηγές των δεδομένων σίγουρα θα χρειαστεί να μεγαλώσει ο χώρος, αυτό θα πρέπει να υπολογίζεται κάθε φορά και να μεγαλώσει άπαξ καθώς αν το μεγαλώνουμε τμηματικά αυτό θα οδηγήσει σε performance penalty κατά την φάση του ETL process καθώς θα υπάρχει ένα επαναλαμβανόμενο I/O request.
- Αν και σε ένα DW write operations έχω μόνο κατά την στιγμή που φορτώνω σε αυτό δεδομένα εντούτοις καλό είναι να εφαρμόσω το best practice που έχουμε σε OLTP databases και δεν είναι άλλο από το να έχω σε ξεχωριστούς φυσικούς δίσκους τα data files από τα transaction log files.
- Μια αρκετά σημαντική επιλογή είναι αυτή του RAID των δίσκων μου. Θα πρέπει σοφά να διαλέξω αυτή που χρειάζομαι καθώς όλες δεν έχουν την ίδια απόδοση αλλά και ασφάλεια. Ενδεικνυόμενη επιλογή ιδιαίτερα σε μεγάλα DW είναι του RAID 10.
- Είναι γνωστό ότι το SQL Server Query Engine έχει την δυνατότητα να εκμεταλλευτεί ιδανικά το πλεονέκτημα του parallel thread processing όταν διαβάζει από ξεχωριστά physical devices. Έτσι σοφό είναι να διασκορπίσω τα δεδομένα μου σε πολλαπλά ξεχωριστά physical devices κάνοντας partitioningκυρίως στα fact tables. Τα πλεονεκτήματα που θα αποκομίσω από μια τέτοια ενέργεια θα είναι:
- Βελτίωση του query performance. Ιδιαίτερα αν είμαι σε SQL Server 2012 ο οποίος υποστηρίζει partitioned table parallelism τότε θα μπορώ να διαβάζω δεδομένα από πολλά διαφορετικά partitions ταυτόχρονα.
- Θα έχω ταχύτητα στο φόρτωμα ή στην διαγραφή των δεδομένων.
- Θα μπορώ να συντηρώ τους indexes σε επίπεδο partitions. Ιδιαίτερα αν κάνω χρήση των columnstore indexes όπου δεν μπορώ να κάνω αλλαγές σε ένα πίνακα που έχει τέτοιο index η χρήση του partitioning είναι απαραίτητη καθώς έτσι λύνω το πρόβλημα που μόλις αναφέρθηκε.
- Ακόμα θα έχω περισσότερες δυνατότητες για backup και restore καθώς θα έχω την δυνατότητα να υλοποιήσω σενάρια filegroup backup/restore με τα οποία μπορώ να μειώσω σημαντικά τους χρόνους που απαιτούνται για τις διαδικασίες backup και restore.
- Αρκετές φορές μέσα σε ένα DW έχουμε αντικείμενα πχ tables που κάθε φορά που εκτελείται ένα ETL process αυτά σβήνονται και ξαναδημιουργούνται. Συνήθως είναι αυτά που βρίσκονται στην stage area. Σκόπιμο είναι τέτοιου σκοπού και συμπεριφοράς αντικείμενα να είναι σε ξεχωριστό filegroup από τα filegroups που βρίσκονται τα fact και dimension tables καθώς έτσι θα έχω καταφέρει να μειώσω το ρίσκο να έχω fragmentation σε αυτά (fact & dimension tables).
- Ένα ακόμα στοιχείο το όποιο δεν θα πρέπει να ξεχνάμε είναι το γεγονός ότι μπορώ να κάνω data compresion. Ενεργοποιώντας το, μπορώ να πετύχω εκτός από το να μειώσω τους φυσικούς χώρους που χρειάζομαι για τον όγκο των δεδομένων μου, μπορώ να βελτιστοποιήσω και το γενικότερο performance σε I/O καθώς θα διαβάζω λιγότερες σελίδες από το δίσκο αλλά παράλληλα θα έχω και εξοικονόμηση μνήμης (buffer cache) καθώς θα ανεβαίνουν και λιγότερες σελίδες σε αυτή. Φυσικά υπάρχει ένα tradeoff το οποίο θα πρέπει να ελέγξω και αυτό δεν είναι άλλο από την χρήση της CPU. Αν και σε πολλές περιπτώσεις τα οφέλη είναι περισσότερα από τα μειονεκτήματα.
Tips for Indexes
- Στα dimension tables φτιάχνουμε indexes ως εξής:
- Το primary key θα πρέπει να είναι nonclustered και θα πρέπει να είναι το surrogate key column.
- Δημιουργούμε clustered index στο business key column. Με αυτό θα έχουμε το ιδανικό performance κατά τις φάσεις που κάνουμε φόρτωμα δεδομένων ιδιαίτερα σε περιπτώσεις Slowly changing dimension όπου το business key θα πρέπει να το κάνω lookup.
- Δημιουργούμε nonclustered indexes σε όποια άλλη κολώνα/πεδίο που χρησιμοποιείτε συχνά σαν φίλτρο σε query (where clauses).
- Στα fact tables φτιάχνουμε indexes ως εξής:
- Στην περίπτωση που το fact είναι συσχετιζόμενο με λίγους dimensional tables φτιάχνω το primary key unique clustered index. Στην περίπτωση που είναι με πολλούς τότε επιλέγω nonclustered.
- Δημιουργώ ξεχωριστούς nonclustred indexes για κάθε ξεχωριστώ foreign key (με τους dimension tables) που χρησιμοποιείται σε queries.
- Σε την περίπτωση που είμαι σε SQL Server 2012 θα ήταν παντελώς χαζό να μην κάνω χρήση των Columnstore Indexes τόσο σε facts όσο και σε μεγάλα dimension tables. Η διαφορά στο performance που θα έχω είναι εντυπωσιακή. Απλά να επισημανθεί ότι σε κάθε πίνακα μπορώ να έχω ένα τέτοιο index που όμως μπορεί να έχει πολλά πεδία μέσα του. Περισσότερα για αυτό μπορείτε να διαβάσετε κατεβάζοντας το white paper με τίτλο «Columnstore Indexes for Fast DW QP SQL Server 11.0»
Δεν συνηθίζω να το λέω αλλά τα παραπάνω πρέπει ευλαβικά σαν ευαγγέλιο να ακολουθούνται όταν υλοποιώ ένα DW.
/*antonch*/