Προγραμματισμός

Μεγάλα αναλυτικά δεδομένα με Neo4j και Java, Μέρος 1

Οι σχεσιακές βάσεις δεδομένων κυριαρχούν στη διαχείριση δεδομένων εδώ και δεκαετίες, αλλά πρόσφατα έχασαν έδαφος από εναλλακτικές λύσεις 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 (δευτερόλεπτα) Καταμέτρηση αποτελέσματος

20.028~900
30.213~999
410.273~999
592.613~999

Η MySQL κάνει εξαιρετική δουλειά για τη σύνδεση δεδομένων έως και τρία επίπεδα, αλλά η απόδοση υποβαθμίζεται γρήγορα μετά από αυτό. Ο λόγος είναι ότι κάθε φορά που το USER_FRIEND Ο πίνακας συνδέεται με τον εαυτό του, η MySQL πρέπει να υπολογίσει το καρτεσιανό προϊόν του πίνακα, παρόλο που τα περισσότερα δεδομένα θα απορριφθούν. Για παράδειγμα, όταν εκτελείτε αυτήν την ένωση πέντε φορές, το καρτεσιανό προϊόν έχει ως αποτέλεσμα 50.000 ^ 5 σειρές ή 102,4 * 10 ^ 21 σειρές. Αυτό είναι χάσιμο όταν ενδιαφερόμαστε μόνο για 1.000 από αυτά!

Στη συνέχεια, οι Vukotic και Watt προσπάθησαν να εκτελέσουν τον ίδιο τύπο ερωτήσεων εναντίον του Neo4j. Αυτά τα εντελώς διαφορετικά αποτελέσματα φαίνονται στον Πίνακα 2.

Πίνακας 2. Χρόνος απόκρισης Neo4j για διάφορα βάθη σχέσεων

Χρόνος εκτέλεσης Depth (δευτερόλεπτα) Καταμέτρηση αποτελέσματος

20.04~900
30.06~999
40.07~999
50.07~999

Η απομάκρυνση από αυτές τις συγκρίσεις εκτέλεσης είναι δεν ότι το Neo4j είναι καλύτερο από το MySQL. Αντίθετα, όταν διασχίζουμε αυτούς τους τύπους σχέσεων, η απόδοση του Neo4j εξαρτάται από τον αριθμό των εγγραφών που ανακτήθηκαν, ενώ η απόδοση της MySQL εξαρτάται από τον αριθμό των εγγραφών στο USER_FRIEND τραπέζι. Έτσι, καθώς ο αριθμός των σχέσεων αυξάνεται, οι χρόνοι απόκρισης για ερωτήματα MySQL θα αυξηθούν επίσης, ενώ οι χρόνοι απόκρισης για ερωτήματα Neo4j θα παραμείνουν οι ίδιοι. Αυτό συμβαίνει επειδή ο χρόνος απόκρισης του Neo4j εξαρτάται από τον αριθμό των σχέσεων για ένα συγκεκριμένο ερώτημα και όχι από τον συνολικό αριθμό των σχέσεων.

Κλίμακα Neo4j για μεγάλα δεδομένα

Επεκτείνοντας αυτό το έργο σκέψης ένα βήμα ακόμη, οι Vukotic και Watt δημιούργησαν στη συνέχεια ένα εκατομμύριο χρήστες με 50 εκατομμύρια σχέσεις μεταξύ τους. Ο Πίνακας 3 δείχνει τα αποτελέσματα για αυτό το σύνολο δεδομένων.

Πίνακας 3. Χρόνος απόκρισης Neo4j για 50 εκατομμύρια σχέσεις

Χρόνος εκτέλεσης Depth (δευτερόλεπτα) Καταμέτρηση αποτελέσματος

20.01~2,500
30.168~110,000
41.359~600,000
52.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)
$config[zx-auto] not found$config[zx-overlay] not found