Οι σχεσιακές βάσεις δεδομένων κυριαρχούν στη διαχείριση δεδομένων εδώ και δεκαετίες, αλλά πρόσφατα έχασαν έδαφος από εναλλακτικές λύσεις NoSQL. Ενώ τα καταστήματα δεδομένων NoSQL δεν είναι κατάλληλα για κάθε περίπτωση χρήσης, είναι γενικά καλύτερα για μεγάλα δεδομένα, η οποία είναι συντομογραφία για συστήματα που επεξεργάζονται τεράστιους όγκους δεδομένων. Τέσσερις τύποι αποθήκευσης δεδομένων χρησιμοποιούνται για μεγάλα δεδομένα:
- Καταστήματα κλειδιών / τιμών όπως Memcached και Redis
- Βάσεις δεδομένων προσανατολισμένες σε έγγραφα, όπως MongoDB, CouchDB και DynamoDB
- Αποθήκες δεδομένων προσανατολισμένες στη στήλη, όπως η Cassandra και η HBase
- Βάσεις δεδομένων γραφημάτων όπως Neo4j και OrientDB
Αυτό το σεμινάριο παρουσιάζει το Neo4j, το οποίο είναι μια βάση δεδομένων γραφημάτων που χρησιμοποιείται για αλληλεπίδραση πολύ σχετικά δεδομένα. Ενώ οι σχεσιακές βάσεις δεδομένων είναι καλοί στη διαχείριση των σχέσεων μεταξύ τα δεδομένα, οι βάσεις δεδομένων γραφημάτων είναι καλύτερα στη διαχείριση απείρως μικρός σχέσεις πτυχίου. Για παράδειγμα, πάρτε ένα κοινωνικό δίκτυο, όπου θέλετε να αναλύσετε μοτίβα που περιλαμβάνουν φίλους, φίλους φίλων και ούτω καθεξής. Μια βάση δεδομένων γραφημάτων θα διευκόλυνε την απάντηση σε μια ερώτηση όπως, "Δεδομένου των πέντε βαθμών διαχωρισμού, ποιες είναι οι πέντε ταινίες δημοφιλείς στο κοινωνικό μου δίκτυο που δεν έχω δει ακόμα;" Τέτοιες ερωτήσεις είναι κοινές για λογισμικό προτάσεων και οι βάσεις δεδομένων γραφημάτων είναι ιδανικές για την επίλυσή τους. Επιπλέον, οι βάσεις δεδομένων γραφημάτων είναι ικανές να αντιπροσωπεύουν ιεραρχικά δεδομένα, όπως στοιχεία ελέγχου πρόσβασης, καταλόγους προϊόντων, βάσεις δεδομένων ταινιών ή ακόμη και τοπολογίες δικτύου και οργανόγραμμα. Όταν έχετε αντικείμενα με πολλαπλές σχέσεις, θα διαπιστώσετε γρήγορα ότι οι βάσεις δεδομένων γραφημάτων προσφέρουν ένα κομψό, αντικειμενοστρεφή παράδειγμα για τη διαχείριση αυτών των αντικειμένων.
Η περίπτωση για βάσεις δεδομένων γραφημάτων
Όπως υποδηλώνει το όνομα, οι βάσεις δεδομένων γραφημάτων είναι καλοί στην αναπαράσταση γραφημάτων δεδομένων. Αυτό είναι ιδιαίτερα χρήσιμο για κοινωνικό λογισμικό, όπου κάθε φορά που συνδέεστε με κάποιον, καθορίζεται μια σχέση μεταξύ σας. Πιθανότατα στην τελευταία αναζήτηση εργασίας σας, επιλέξατε μερικές εταιρείες που σας ενδιέφεραν και έπειτα πραγματοποιήσατε αναζήτηση στα κοινωνικά σας δίκτυα για συνδέσεις με αυτές. Παρόλο που ίσως να μην γνωρίζετε κάποιον που εργάζεται για μία από αυτές τις εταιρείες, κάποιος στο κοινωνικό σας δίκτυο πιθανότατα το κάνει. Η επίλυση ενός τέτοιου προβλήματος είναι εύκολη σε έναν ή δύο βαθμούς διαχωρισμού (ο φίλος σας ή ένας φίλος ενός φίλου), αλλά τι συμβαίνει όταν αρχίσετε να επεκτείνετε την αναζήτηση στο δίκτυό σας;
Στο βιβλίο τους, οι Neo4j In Action, οι Aleksa Vukotic και Nicki Watt διερευνούν τις διαφορές μεταξύ σχεσιακών βάσεων δεδομένων και γραφημάτων βάσης δεδομένων για την επίλυση προβλημάτων κοινωνικού δικτύου. Θα ακολουθήσω τη δουλειά τους για τα επόμενα λίγα παραδείγματα, προκειμένου να σας δείξω γιατί οι βάσεις δεδομένων γραφημάτων γίνονται μια ολοένα και πιο δημοφιλής εναλλακτική λύση στις σχεσιακές βάσεις δεδομένων.
Μοντελοποίηση σύνθετων σχέσεων: Neo4j έναντι MySQL
Από την άποψη της επιστήμης των υπολογιστών, όταν σκεφτόμαστε τη μοντελοποίηση των σχέσεων μεταξύ των χρηστών σε ένα κοινωνικό δίκτυο, θα μπορούσαμε να σχεδιάσουμε ένα γράφημα όπως αυτό στο Σχήμα 1.
Στίβεν ΧάινςΈνας χρήστης έχει IS_FRIEND_OF
σχέσεις με άλλους χρήστες, και αυτοί οι χρήστες έχουν IS_FRIEND_OF
σχέσεις με άλλους χρήστες και ούτω καθεξής. Το σχήμα 2 δείχνει πώς θα το εκπροσωπούσαμε σε σχεσιακή βάση δεδομένων.
ο ΧΡΗΣΤΗΣ
ο πίνακας έχει μια σχέση με το ένα με το USER_FRIEND
πίνακα, ο οποίος διαμορφώνει τη σχέση "φίλου" μεταξύ δύο χρηστών. Τώρα που έχουμε μοντελοποιήσει τις σχέσεις, πώς θα ρωτήσουμε τα δεδομένα μας; Ο Vukotic και ο Watt μέτρησαν την απόδοση του ερωτήματος για να μετρήσουν τον αριθμό των διακριτών φίλων που βγαίνουν σε βάθος πέντε επιπέδων (φίλοι φίλων φίλων φίλων φίλων φίλων). Σε μια σχεσιακή βάση δεδομένων τα ερωτήματα θα φαίνονται ως εξής:
# Depth 1 select count (ξεχωριστό uf. *) Από το user_friend uf όπου uf.user_1 =? # Depth 2 select count (ξεχωριστό uf2. *) Από user_friend uf1 internal join user_friend uf2 στο uf1.user_1 = uf2.user_2 όπου uf1.user_1 =? # Depth 3 select count (ξεχωριστό uf3. *) Από t_user_friend uf1 internal join t_user_friend uf2 on uf1.user_1 = uf2.user_2 internal join t_user_friend uf3 on uf2.user_1 = uf3.user_2 όπου uf1.user_1 =? # Και ούτω καθεξής...
Αυτό που είναι ενδιαφέρον για αυτά τα ερωτήματα είναι ότι κάθε φορά που βγαίνουμε σε ένα ακόμη επίπεδο, πρέπει να συμμετέχουμε στο USER_FRIEND
τραπέζι με τον εαυτό του. Ο Πίνακας 1 δείχνει τι βρήκαν οι ερευνητές Vukotic και Watt όταν εισήγαγαν 1.000 χρήστες με περίπου 50 σχέσεις ο καθένας (50.000 σχέσεις) και έτρεξαν τα ερωτήματα.
Πίνακας 1. Χρόνος απόκρισης ερωτημάτων MySQL για διάφορα βάθη σχέσεων
Χρόνος εκτέλεσης Depth (δευτερόλεπτα) Καταμέτρηση αποτελέσματος
2 | 0.028 | ~900 |
3 | 0.213 | ~999 |
4 | 10.273 | ~999 |
5 | 92.613 | ~999 |
Η MySQL κάνει εξαιρετική δουλειά για τη σύνδεση δεδομένων έως και τρία επίπεδα, αλλά η απόδοση υποβαθμίζεται γρήγορα μετά από αυτό. Ο λόγος είναι ότι κάθε φορά που το USER_FRIEND
Ο πίνακας συνδέεται με τον εαυτό του, η MySQL πρέπει να υπολογίσει το καρτεσιανό προϊόν του πίνακα, παρόλο που τα περισσότερα δεδομένα θα απορριφθούν. Για παράδειγμα, όταν εκτελείτε αυτήν την ένωση πέντε φορές, το καρτεσιανό προϊόν έχει ως αποτέλεσμα 50.000 ^ 5 σειρές ή 102,4 * 10 ^ 21 σειρές. Αυτό είναι χάσιμο όταν ενδιαφερόμαστε μόνο για 1.000 από αυτά!
Στη συνέχεια, οι Vukotic και Watt προσπάθησαν να εκτελέσουν τον ίδιο τύπο ερωτήσεων εναντίον του Neo4j. Αυτά τα εντελώς διαφορετικά αποτελέσματα φαίνονται στον Πίνακα 2.
Πίνακας 2. Χρόνος απόκρισης Neo4j για διάφορα βάθη σχέσεων
Χρόνος εκτέλεσης Depth (δευτερόλεπτα) Καταμέτρηση αποτελέσματος
2 | 0.04 | ~900 |
3 | 0.06 | ~999 |
4 | 0.07 | ~999 |
5 | 0.07 | ~999 |
Η απομάκρυνση από αυτές τις συγκρίσεις εκτέλεσης είναι δεν ότι το Neo4j είναι καλύτερο από το MySQL. Αντίθετα, όταν διασχίζουμε αυτούς τους τύπους σχέσεων, η απόδοση του Neo4j εξαρτάται από τον αριθμό των εγγραφών που ανακτήθηκαν, ενώ η απόδοση της MySQL εξαρτάται από τον αριθμό των εγγραφών στο USER_FRIEND
τραπέζι. Έτσι, καθώς ο αριθμός των σχέσεων αυξάνεται, οι χρόνοι απόκρισης για ερωτήματα MySQL θα αυξηθούν επίσης, ενώ οι χρόνοι απόκρισης για ερωτήματα Neo4j θα παραμείνουν οι ίδιοι. Αυτό συμβαίνει επειδή ο χρόνος απόκρισης του Neo4j εξαρτάται από τον αριθμό των σχέσεων για ένα συγκεκριμένο ερώτημα και όχι από τον συνολικό αριθμό των σχέσεων.
Κλίμακα Neo4j για μεγάλα δεδομένα
Επεκτείνοντας αυτό το έργο σκέψης ένα βήμα ακόμη, οι Vukotic και Watt δημιούργησαν στη συνέχεια ένα εκατομμύριο χρήστες με 50 εκατομμύρια σχέσεις μεταξύ τους. Ο Πίνακας 3 δείχνει τα αποτελέσματα για αυτό το σύνολο δεδομένων.
Πίνακας 3. Χρόνος απόκρισης Neo4j για 50 εκατομμύρια σχέσεις
Χρόνος εκτέλεσης Depth (δευτερόλεπτα) Καταμέτρηση αποτελέσματος
2 | 0.01 | ~2,500 |
3 | 0.168 | ~110,000 |
4 | 1.359 | ~600,000 |
5 | 2.132 | ~800,000 |
Περιττό να πω, είμαι ευγνώμων στους Aleksa Vukotic και Nicki Watt και συνιστώ ανεπιφύλακτα να ελέγξετε τη δουλειά τους. Έβγαλα όλες τις δοκιμές σε αυτήν την ενότητα από το πρώτο κεφάλαιο του βιβλίου τους, Neo4j σε δράση.
Ξεκινώντας με το Neo4j
Έχετε δει ότι το Neo4j είναι ικανό να εκτελεί πολύ γρήγορα τεράστιες ποσότητες δεδομένων που σχετίζονται πολύ, και δεν υπάρχει αμφιβολία ότι ταιριάζει καλύτερα από το MySQL (ή οποιαδήποτε σχετική βάση δεδομένων) για ορισμένα είδη προβλημάτων. Εάν θέλετε να καταλάβετε περισσότερα σχετικά με τον τρόπο λειτουργίας του Neo4j, ο ευκολότερος τρόπος είναι να αλληλεπιδράσετε μαζί του μέσω της κονσόλας ιστού.
Ξεκινήστε κατεβάζοντας το Neo4j. Για αυτό το άρθρο, θα θέλατε την Έκδοση κοινότητας, η οποία από αυτήν τη γραφή είναι στην έκδοση 3.2.3.
- Σε Mac, κατεβάστε ένα αρχείο DMG και εγκαταστήστε το όπως θα κάνατε σε οποιαδήποτε άλλη εφαρμογή.
- Στα Windows, κατεβάστε ένα EXE και ακολουθήστε τον οδηγό εγκατάστασης ή κατεβάστε ένα αρχείο ZIP και αποσυμπιέστε το στον σκληρό σας δίσκο.
- Στο Linux, κατεβάστε ένα αρχείο TAR και αποσυμπιέστε το στον σκληρό σας δίσκο.
- Εναλλακτικά, χρησιμοποιήστε μια εικόνα Docker σε οποιοδήποτε λειτουργικό σύστημα.
Αφού εγκαταστήσετε το Neo4j, ξεκινήστε το και ανοίξτε ένα παράθυρο προγράμματος περιήγησης στην ακόλουθη διεύθυνση URL:
//127.0.0.1:7474/browser/
Συνδεθείτε με το προεπιλεγμένο όνομα χρήστη του neo4j
και τον προεπιλεγμένο κωδικό πρόσβασης του neo4j
. Θα πρέπει να δείτε μια οθόνη παρόμοια με το Σχήμα 3.
Κόμβοι και σχέσεις στο Neo4j
Το Neo4j έχει σχεδιαστεί γύρω από την έννοια των κόμβων και των σχέσεων:
- ΕΝΑ κόμβος αντιπροσωπεύει ένα πράγμα, όπως ένας χρήστης, μια ταινία ή ένα βιβλίο.
- Ένας κόμβος περιέχει ένα σύνολο ζεύγη κλειδιών / τιμών, όπως όνομα, τίτλος ή εκδότη.
- Ένας κόμβος επιγραφή καθορίζει τι είδους πράγμα είναι - πάλι, ένας χρήστης, μια ταινία ή ένα βιβλίο.
- Σχέσεις καθορίζει συσχετίσεις μεταξύ κόμβων και είναι συγκεκριμένων τύπων.
Για παράδειγμα, ενδέχεται να ορίσουμε κόμβους χαρακτήρων όπως το Iron Man και το Captain America. ορίστε έναν κόμβο ταινίας με το όνομα "Avengers". και μετά ορίστε ένα APPEARS_IN
σχέση μεταξύ Iron Man και Avengers και Captain America και Avengers. Όλα αυτά φαίνονται στο Σχήμα 4.
Το σχήμα 4 δείχνει τρεις κόμβους (δύο κόμβους χαρακτήρων και έναν κόμβο ταινίας) και δύο σχέσεις (και οι δύο τύπου APPEARS_IN
).
Μοντελοποίηση και ερώτηση κόμβων και σχέσεων
Παρόμοια με τον τρόπο με τον οποίο μια σχεσιακή βάση δεδομένων χρησιμοποιεί τη Δομημένη Γλώσσα Ερωτήσεων (SQL) για να αλληλεπιδράσει με δεδομένα, το Neo4j χρησιμοποιεί το Cypher Query Language για να αλληλεπιδρά με κόμβους και σχέσεις.
Ας χρησιμοποιήσουμε το Cypher για να δημιουργήσουμε μια απλή αναπαράσταση μιας οικογένειας. Στην κορυφή της διεπαφής ιστού, αναζητήστε το σύμβολο του δολαρίου. Αυτό υποδηλώνει ένα πεδίο που σας επιτρέπει να εκτελείτε ερωτήματα Cypher απευθείας έναντι του Neo4j. Εισαγάγετε το ακόλουθο ερώτημα Cypher σε αυτό το πεδίο (χρησιμοποιώ την οικογένειά μου ως παράδειγμα, αλλά μη διστάσετε να αλλάξετε τις λεπτομέρειες για να διαμορφώσετε τη δική σας οικογένεια εάν θέλετε):
ΔΗΜΙΟΥΡΓΙΑ (άτομο: Πρόσωπο {όνομα: "Steven", ηλικία: 45}) ΕΠΙΣΤΡΟΦΗ άτομο
Το αποτέλεσμα φαίνεται στο σχήμα 5.
Στίβεν ΧάινςΣτο σχήμα 5 μπορείτε να δείτε έναν νέο κόμβο με την ετικέτα Person και το όνομα Steven. Εάν τοποθετήσετε το ποντίκι σας πάνω από τον κόμβο στην κονσόλα ιστού σας, θα δείτε τις ιδιότητές του στο κάτω μέρος. Σε αυτήν την περίπτωση, οι ιδιότητες είναι ID: 19, όνομα: Steven και ηλικία: 45. Τώρα ας αναλύσουμε το ερώτημα Cypher:
- ΔΗΜΙΟΥΡΓΩ: Ο
ΔΗΜΙΟΥΡΓΩ
Η λέξη-κλειδί χρησιμοποιείται για τη δημιουργία κόμβων και σχέσεων. Σε αυτήν την περίπτωση, το περνάμε ένα μόνο επιχείρημα, το οποίο είναιΠρόσωπο
περικλείεται σε παρένθεση, οπότε προορίζεται να δημιουργήσει έναν μόνο κόμβο. - (άτομο: Άτομο {...}): Η πεζά "
πρόσωπο
"είναι ένα μεταβλητό όνομα μέσω του οποίου μπορούμε να έχουμε πρόσβαση στο άτομο που δημιουργείται, ενώ το κεφάλαιο"Πρόσωπο
είναι η ετικέτα. Σημειώστε ότι μια άνω και κάτω τελεία διαχωρίζει το όνομα της μεταβλητής από την ετικέτα. - {όνομα: "Στίβεν, ηλικία: 45}: Αυτές είναι οι ιδιότητες κλειδιού / τιμής που ορίζουμε για τον κόμβο που δημιουργούμε. Το Neo4j δεν απαιτεί να ορίσετε ένα σχήμα πριν από τη δημιουργία κόμβων και κάθε κόμβος μπορεί να έχει ένα μοναδικό σύνολο στοιχείων. (Τις περισσότερες φορές ορίζετε κόμβους με την ίδια ετικέτα για να έχετε τις ίδιες ιδιότητες, αλλά δεν απαιτείται.)
- ΕΠΙΣΤΡΟΦΗ άτομο: Μετά τη δημιουργία του κόμβου, ζητάμε από το Neo4j να το επιστρέψει σε εμάς. Αυτός είναι ο λόγος για τον οποίο είδαμε τον κόμβο να εμφανίζεται στη διεπαφή χρήστη.
ο ΔΗΜΙΟΥΡΓΩ
Η εντολή (που δεν είναι κεφαλαία) χρησιμοποιείται για τη δημιουργία κόμβων και μπορεί να διαβαστεί ως εξής: δημιουργήστε έναν νέο κόμβο με την ετικέτα Person που περιέχει ιδιότητες ονόματος και ηλικίας. εκχωρήστε τη στη μεταβλητή προσώπου και επιστρέψτε την στον καλούντα.
Ερώτηση με Cypher Query Language
Στη συνέχεια θέλουμε να δοκιμάσουμε κάποια ερώτηση με το Cypher. Πρώτον, θα πρέπει να δημιουργήσουμε μερικά ακόμη άτομα, ώστε να μπορούμε να καθορίσουμε τις σχέσεις μεταξύ τους.
ΔΗΜΙΟΥΡΓΙΑ (άτομο: Πρόσωπο {όνομα: "Michael", ηλικία: 16}) ΕΠΙΣΤΡΟΦΗ άτομο ΔΗΜΙΟΥΡΓΙΑ (άτομο: Άτομο {όνομα: "Rebecca", ηλικία: 7}) ΕΠΙΣΤΡΟΦΗ προσώπου ΔΗΜΙΟΥΡΓΙΑ (άτομο: Άτομο {όνομα: "Linda"} ΕΠΙΣΤΡΟΦΗ ατόμου
Μόλις δημιουργήσετε τα τέσσερα άτομα, μπορείτε είτε να κάνετε κλικ στο Πρόσωπο κουμπί κάτω από το Ετικέτες κόμβου (ορατό εάν κάνετε κλικ στο εικονίδιο της βάσης δεδομένων στην επάνω αριστερή γωνία της ιστοσελίδας) ή εκτελέσετε το ακόλουθο ερώτημα Cypher:
ΑΓΩΝΑ (άτομο: άτομο) ΕΠΙΣΤΡΟΦΗ ατόμου
Το Cypher χρησιμοποιεί το ΑΓΩΝΑΣ
λέξη-κλειδί για να βρείτε πράγματα στο Neo4j. Σε αυτό το παράδειγμα, ζητάμε από τον Cypher να αντιστοιχίσει όλους τους κόμβους που έχουν ετικέτα Person, αντιστοιχίστε αυτούς τους κόμβους στο πρόσωπο μεταβλητή και επιστρέψτε την τιμή που σχετίζεται με αυτήν τη μεταβλητή. Ως αποτέλεσμα θα πρέπει να δείτε τους τέσσερις κόμβους που έχετε δημιουργήσει. Εάν τοποθετείτε το δείκτη του ποντικιού πάνω από κάθε κόμβο στην κονσόλα ιστού σας, θα δείτε τις ιδιότητες κάθε ατόμου. (Ίσως σημειώσετε ότι απέκλεισα την ηλικία της συζύγου μου από τον κόμβο της, υποδεικνύοντας ότι οι ιδιότητες δεν χρειάζεται να είναι συνεπείς μεταξύ των κόμβων, ακόμη και της ίδιας ετικέτας. Επίσης, δεν είμαι αρκετά ανόητος για να δημοσιεύσω την ηλικία της γυναίκας μου.)
Μπορούμε να το επεκτείνουμε ΑΓΩΝΑΣ
παράδειγμα λίγο πιο πέρα προσθέτοντας συνθήκες στους κόμβους που θέλουμε να επιστρέψουμε. Για παράδειγμα, εάν θέλαμε μόνο τον κόμβο "Steven", θα μπορούσαμε να τον ανακτήσουμε αντιστοιχίζοντας στην ιδιότητα name:
MATCH (άτομο: Πρόσωπο {όνομα: "Steven"}) ΕΠΙΣΤΡΟΦΗ άτομο
Ή, εάν θέλαμε να επιστρέψουμε όλα τα παιδιά, θα μπορούσαμε να ζητήσουμε από όλους τους ανθρώπους ηλικίας κάτω των 18 ετών:
ΑΓΩΝΑ (άτομο: Πρόσωπο) ΠΟΥ άτομο. Ηλικία <18 ΕΠΙΣΤΡΟΦΗ άτομο
Σε αυτό το παράδειγμα προσθέσαμε το ΟΠΟΥ
ρήτρα στο ερώτημα για να περιορίσουμε τα αποτελέσματά μας. ΟΠΟΥ
λειτουργεί πολύ παρόμοια με το αντίστοιχο SQL: MATCH (άτομο: άτομο)
βρίσκει όλους τους κόμβους με την ετικέτα Person και μετά το ΟΠΟΥ
Το clause φιλτράρει τιμές εκτός του συνόλου αποτελεσμάτων.
Κατεύθυνση μοντελοποίησης στις σχέσεις
Έχουμε τέσσερις κόμβους, οπότε ας δημιουργήσουμε μερικές σχέσεις. Πρώτα απ 'όλα, ας δημιουργήσουμε το IS_MARRIED_TO
σχέση μεταξύ Steven και Linda:
MATCH (steven: Person {name: "Steven"}), (linda: Person {name: "Linda"}) CREATE (steven) - [: IS_MARRIED_TO] -> (linda) επιστροφή steven, linda
Σε αυτό το παράδειγμα ταιριάζουμε με δύο κόμβους με την ονομασία Steven και Linda και δημιουργούμε μια σχέση τύπου IS_MARRIED_TO
από τον Στίβεν στη Λίντα. Η μορφή για τη δημιουργία της σχέσης έχει ως εξής:
(κόμβος1) - [σχέση Μεταβλητή: RELATIONSHIP_TYPE -> (κόμβος2)