Στο κόσμο των relational databases έχουμε εξοικειωθεί χρόνια τώρα με έννοιες όπως database, table , field, relation, constraint και άλλες.
Γνωρίζουμε ότι κάθε database έχει tables, κάθε table έχει rows (records) , κάθε row έχει fields και όλα αυτά είναι σταθερά σε όλα τα rows.
Είναι εύλογο όταν μαθαίνουμε κάτι καινούργιο να προσπαθούμε να αντιστοιχίσουμε την υπάρχουσα γνώση μας με αυτό ώστε να το κατανοήσουμε ευκολότερα και για αυτό ας το κάνουμε.
Cosmos DB Account
Στη Cosmos DB έχουμε Account και σε αυτό μπορώ να έχω πολλές databases. Θα μπορούσαμε να πούμε ότι αυτό είναι το SQL Server Instance
Collections
Σε κάθε Cosmos DB database έχουμε τα Collections και μπορούμε να αντιστοιχίσουμε αυτά με τα tables σε μια relational database.
Documents
Κάθε Cosmos DB Collections έχει documents (JSON format) και μπορούμε να αντιστοιχίσουμε αυτά σαν τα rows που έχει κάθε table σε μία relational database.
Properties
Κάθε document καθώς είναι σε JSON έχει properties και κάθε ένα από αυτά μπορούμε να το αντιστοιχίσουμε στα fields που έχει το κάθε row. Απλά να επισημανθεί ότι εδώ δεν έχουμε σταθερό σχήμα.
Denormalized data
Έχουμε συνηθίσει στις relational databases να έχουμε normalized schemas και μάλιστα αυτό να είναι από τα κυρίαρχα και σημαντικότερα χαρακτηριστικά σε αυτές.
Το αντίθετο όμως ισχύει στις document databases που επειδή είναι serialized objects για να έχουν καλύτερη απόδοση και να είναι απλά στο querying απαιτούν denormalization.
Ακόμα να επισημανθεί ότι οι περισσότερες document databases δεν επιτρέπουν JOINs πχ MongoDB, μάλιστα κατά το σχεδιασμό τους αυτό θα πρέπει να ληφθεί σοβαρά υπόψη καθώς πρέπει να βρεθεί η χρυσή τομή μεταξύ της συντήρησης του denormalization και του query performance.
Referential Integrity
Η έννοια του referential integrity όπως την έχουμε συνηθίσει/μάθει στις relational databases δεν υπάρχει καθόλου στις document databases.
Document structure
Όπως ήδη έχω γράψει το κάθε document είναι σε JSON format που είναι πλέον industry standard για την ανταλλαγή δεδομένων και πολλές γλώσσες πλέον περιέχουν classes που κάνουν parsing σε αυτό.
Αυτό σημαίνει ότι κάθε document δεν πρέπει να είναι πάνω από 2ΜΒ και αν θέλω να έχω binary blobs αυτά θα πρέπει να μπαίνουν σαν attachments (URL pointer εκτός του document) και επειδή μιλάμε για την Cosmos DB SQL API database μπορούμε να χρησιμοποιήσουμε το Cosmos DB blob store που φτάνει τα 2GB / database account.
Να επισημανθεί ότι εξαιτίας του JSON υποστηρίζεται και GeoJSON.
Primary / Unique Keys
Αυτόματα σε όλα τα documents μπαίνουν extra κάποια properties ( _rid, _etag, _ts, _self) και ένα από αυτά είναι και το Id (που είναι GUID αν δεν έχουμε ορίσει εμεις το δικό μας) και μοναδικά χαρακτηρίζει το κάθε document.
Παρόλα αυτά όμως μπορούμε να έχουμε το δικό μας primary/unique key με συνδυασμό από τα υπάρχοντα document properties αρκεί να μην είναι πάνω από 16 properties και μπορώ να έχω μέχρι 10 διαφορετικά unique keys σε κάθε collection.
Όλα αυτά όμως θα πρέπει να τα ορίσω όταν δημιουργώ το collection. ΔΕΝ ΜΠΟΡΩ σε υπάρχον collection να δημιουργήσω ή να διαγράψω unique keys.
Query First Design approach
Η συνήθεια που έχουμε όταν σχεδιάζουμε relational databases όπου αναλύουμε τις απαιτήσεις και εντοπίζουμε τις λογικές οντότητες και τις σχέσεις μεταξύ τους και μετά προχωρούμε στο φυσικό σχεδιασμό είναι παντελώς λάθος προσέγγιση στο σχεδιασμό των documents databases και αυτό διότι αυτές είναι φτωχές σε joins.
Η συνηθέστερη προσέγγιση για το σχεδιασμό των document database collections είναι να δημιουργούμε λίστα με τα ερωτήματα που η εφαρμογή χρειάζεται και με βάση αυτά να σχεδιάζουμε τα document collections.
Αυτό έχει τα θετικά του αλλά και τα αρνητικά του καθώς δεν είναι πάντα εφικτό πολλές εφαρμογές να μοιραστούν τα ίδια collections και σε αρκετές περιπτώσεις θα χρειαστεί data duplication με τις παραλλαγές που χρειάζονται.
Η προσέγγιση αυτή είναι αρκετά χρήσιμη σε heavily read databases και πιθανώς να μην εξυπηρετεί heavily write databases καθώς το document structure θα πρέπει να είναι έτσι ορισμένο ώστε να μην επηρεάζει το write performance εξαιτίας του denormalization.
Joins
Στο Cosmos DB SQL API υποστηρίζονται joins αλλά μόνο cross joins. Η σύνταξη είναι όμοια με αυτή που έχουμε συνηθίσει σε T-SQL. Επίσης υποστηρίζονται μόνο στο συγκεκριμένο document και όχι μεταξύ documents ακόμα και στο ίδιο collection.
Με απλά λόγια αν έχω ένα collection που έχει πελάτες και κάθε document (row) έχει τις παραγγελίες μπορώ να έχω join στο συγκεκριμένο document για κάθε document ξεχωριστά στο collection. Δεν μπορώ να έχω ένα collection πελάτες και ένα άλλο collection παραγγελίες και να κάνω join μεταξύ τους.
Παρότι αυτό σε όλους όσους έχουν relational database background ακούγεται σαν μεγάλος περιορισμός θα πρέπει να επισημάνω ότι δουλεύει εξαιρετικά και είναι αρκετά χρήσιμο σε περιπτώσεις που έχω documents που περιέχουν arrays από sub-documents.
Aggregations
Υποστηρίζονται οι COUNT, SUM, AVG, MAX, MIN aggregate functions με το ίδιο συντακτικό που έχουμε συνηθίσει σε T-SQL αλλά δεν υποστηρίζεται η GROUP BY.
Αυτό σημαίνει ότι δεν μπορώ να έχω πχ SUM ανά πελάτη / προϊόν αλλά μόνο γενικό σε επίπεδο πεδίου.
Επίσης κάποιες χρήσεις που έχουμε συνηθίσει πχ με την COUNT για να μετρήσουμε τον αριθμό των εγγραφών καλό θα είναι να μην γίνονται (χρησιμοποιούμε την ARRAY_COUNT για αυτό το σκοπό).
Ordering
Υποστηρίζεται η Order By είτε ASC είτε DESC αλλά υπάρχουν περιορισμοί και αυτοί είναι:
- Μπορώ να έχω μόνο ένα property για να κάνω sorting δηλαδή δεν μπορώ να έχω order by customer,date
- Στο order by μπορώ να έχω μόνο property δηλαδή δεν μπορώ να έχω calculation ή alias
- To property που θα χρησιμοποιηθεί θα πρέπει να έχει covered index
Επίσης υποστηρίζεται η TOP αλλά αν δεν έχω order by αυτή δεν είναι deterministic.
//antonch