Γιατί χρειάζεστε οργανική υποστήριξη για σελιδοποίηση σε κλειδιά;

Γεια σε όλους! Είμαι προγραμματιστής backend που γράφω microservices σε Java + Spring. Εργάζομαι σε μία από τις εσωτερικές ομάδες ανάπτυξης προϊόντων στο Tinkoff.

Γιατί χρειάζεστε οργανική υποστήριξη για σελιδοποίηση σε κλειδιά;

Στην ομάδα μας, τίθεται συχνά το ζήτημα της βελτιστοποίησης των ερωτημάτων σε ένα DBMS. Θέλετε πάντα να είστε λίγο πιο γρήγοροι, αλλά δεν μπορείτε πάντα να τα βγάλετε πέρα ​​με προσεκτικά κατασκευασμένους δείκτες - πρέπει να αναζητήσετε κάποιες λύσεις. Κατά τη διάρκεια μιας από αυτές τις περιπλανήσεις στον Ιστό για αναζήτηση λογικών βελτιστοποιήσεων κατά την εργασία με βάσεις δεδομένων, βρήκα Το ατελείωτα χρήσιμο blog του Marcus Wynand, συγγραφέας του SQL Performance Explained. Αυτός είναι ο σπάνιος τύπος ιστολογίου στο οποίο μπορείτε να διαβάσετε όλα τα άρθρα στη σειρά.

Θα ήθελα να σας μεταφράσω ένα σύντομο άρθρο του Μάρκους. Μπορεί να ονομαστεί σε κάποιο βαθμό ένα μανιφέστο που επιδιώκει να επιστήσει την προσοχή στο παλιό, αλλά ακόμα σχετικό πρόβλημα της απόδοσης της λειτουργίας μετατόπισης σύμφωνα με το πρότυπο SQL.

Σε κάποια σημεία θα συμπληρώσω τον συγγραφέα με επεξηγήσεις και σχόλια. Θα αναφέρω όλα αυτά τα μέρη ως "περίπου". για περισσότερη σαφήνεια

Μικρή εισαγωγή

Νομίζω ότι πολλοί άνθρωποι γνωρίζουν πόσο προβληματική και αργή είναι η εργασία με επιλογές σελίδων μέσω offset. Γνωρίζατε ότι μπορεί εύκολα να αντικατασταθεί με πιο αποδοτικό σχεδιασμό;

Έτσι, η λέξη-κλειδί offset λέει στη βάση δεδομένων να παραλείψει τις πρώτες n εγγραφές στο αίτημα. Ωστόσο, η βάση δεδομένων εξακολουθεί να χρειάζεται να διαβάζει αυτές τις πρώτες n εγγραφές από το δίσκο, με τη δεδομένη σειρά (σημείωση: εφαρμόστε ταξινόμηση εάν έχει καθοριστεί), και μόνο τότε θα είναι δυνατή η επιστροφή εγγραφών από το n+1 και μετά. Το πιο ενδιαφέρον είναι ότι το πρόβλημα δεν βρίσκεται στη συγκεκριμένη υλοποίηση στο DBMS, αλλά στον αρχικό ορισμό σύμφωνα με το πρότυπο:

…οι σειρές ταξινομούνται πρώτα σύμφωνα με το και στη συνέχεια περιορίζεται με την απόρριψη του αριθμού των σειρών που καθορίζονται στο από την αρχή…
-SQL:2016, Μέρος 2, 4.15.3 Παράγωγοι πίνακες (σημείωση: επί του παρόντος το πιο χρησιμοποιούμενο πρότυπο)

Το βασικό σημείο εδώ είναι ότι η μετατόπιση απαιτεί μία μόνο παράμετρο - τον αριθμό των εγγραφών που πρέπει να παραβλεφθούν, και αυτό είναι. Ακολουθώντας αυτόν τον ορισμό, το DBMS μπορεί μόνο να ανακτήσει όλες τις εγγραφές και στη συνέχεια να απορρίψει τις περιττές. Προφανώς, αυτός ο ορισμός του offset μας αναγκάζει να κάνουμε επιπλέον δουλειά. Και δεν έχει καν σημασία αν είναι SQL ή NoSQL.

Λίγο περισσότερο πόνο

Τα προβλήματα με το offset δεν σταματούν εκεί, και να γιατί. Εάν, μεταξύ της ανάγνωσης δύο σελίδων δεδομένων από το δίσκο, μια άλλη λειτουργία εισάγει μια νέα εγγραφή, τι θα συμβεί σε αυτήν την περίπτωση;

Γιατί χρειάζεστε οργανική υποστήριξη για σελιδοποίηση σε κλειδιά;

Όταν χρησιμοποιείται η μετατόπιση για παράβλεψη εγγραφών από προηγούμενες σελίδες, στην περίπτωση προσθήκης μιας νέας εγγραφής μεταξύ αναγνώσεων διαφορετικών σελίδων, πιθανότατα θα λάβετε διπλότυπα (σημείωση: αυτό είναι δυνατό όταν διαβάζουμε σελίδα προς σελίδα χρησιμοποιώντας τη σειρά κατά κατασκευή, στη συνέχεια στη μέση της εξόδου μας μπορεί να λάβει μια νέα καταχώρηση).

Το σχήμα απεικονίζει ξεκάθαρα αυτή την κατάσταση. Η βάση διαβάζει τις πρώτες 10 εγγραφές και στη συνέχεια εισάγεται μια νέα εγγραφή, η οποία αντισταθμίζει όλες τις εγγραφές ανάγνωσης κατά 1. Στη συνέχεια, η βάση παίρνει μια νέα σελίδα από τις επόμενες 10 εγγραφές και ξεκινά όχι από την 11η, όπως θα έπρεπε, αλλά από την 10ο, αντιγραφή αυτού του δίσκου. Υπάρχουν και άλλες ανωμαλίες που σχετίζονται με τη χρήση αυτής της έκφρασης, αλλά αυτή είναι η πιο κοινή.

Όπως έχουμε ήδη ανακαλύψει, δεν πρόκειται για προβλήματα συγκεκριμένου ΣΔΒΔ ή για τις υλοποιήσεις τους. Το πρόβλημα έγκειται στον ορισμό της σελιδοποίησης σύμφωνα με το πρότυπο SQL. Λέμε στο DBMS ποια σελίδα να ανακτήσει ή πόσες εγγραφές να παραλείψει. Η βάση δεδομένων απλά δεν είναι σε θέση να βελτιστοποιήσει ένα τέτοιο αίτημα, καθώς υπάρχουν πολύ λίγες πληροφορίες για αυτό.

Αξίζει επίσης να διευκρινιστεί ότι αυτό δεν είναι πρόβλημα με μια συγκεκριμένη λέξη-κλειδί, αλλά μάλλον με τη σημασιολογία του ερωτήματος. Υπάρχουν πολλές ακόμη συντακτικές που είναι πανομοιότυπες ως προς την προβληματική τους φύση:

  • Η λέξη-κλειδί offset είναι όπως αναφέρθηκε προηγουμένως.
  • Μια κατασκευή δύο λέξεων-κλειδιών όριο [offset] (αν και το ίδιο το όριο δεν είναι τόσο κακό).
  • Φιλτράρισμα με κατώτερα όρια, με βάση την αρίθμηση σειρών (για παράδειγμα, row_number(), rownum, κ.λπ.).

Όλες αυτές οι εκφράσεις απλώς σας λένε πόσες γραμμές πρέπει να παραλείψετε, χωρίς πρόσθετες πληροφορίες ή περιεχόμενο.

Αργότερα σε αυτό το άρθρο, η λέξη-κλειδί μετατόπισης χρησιμοποιείται ως σύνοψη όλων αυτών των επιλογών.

Ζωή χωρίς OFFSET

Τώρα ας φανταστούμε πώς θα ήταν ο κόσμος μας χωρίς όλα αυτά τα προβλήματα. Αποδεικνύεται ότι η ζωή χωρίς μετατόπιση δεν είναι τόσο δύσκολη: με μια επιλογή, μπορείτε να επιλέξετε μόνο εκείνες τις σειρές που δεν έχουμε δει ακόμη (σημείωση: αυτές που δεν ήταν στην προηγούμενη σελίδα), χρησιμοποιώντας μια συνθήκη όπου.

Σε αυτήν την περίπτωση, ξεκινάμε από το γεγονός ότι οι επιλογές εκτελούνται σε ένα διατεταγμένο σύνολο (παλιά καλή παραγγελία κατά). Εφόσον έχουμε ένα ταξινομημένο σύνολο, μπορούμε να χρησιμοποιήσουμε ένα αρκετά απλό φίλτρο για να λάβουμε μόνο τα δεδομένα που βρίσκονται πίσω από την τελευταία εγγραφή της προηγούμενης σελίδας:

    SELECT ...
    FROM ...
    WHERE ...
    AND id < ?last_seen_id
    ORDER BY id DESC
    FETCH FIRST 10 ROWS ONLY

Αυτή είναι η όλη αρχή αυτής της προσέγγισης. Φυσικά, τα πράγματα γίνονται πιο διασκεδαστικά όταν ταξινομούνται κατά πολλές στήλες, αλλά η ιδέα παραμένει η ίδια. Είναι σημαντικό να σημειωθεί ότι αυτός ο σχεδιασμός μπορεί να εφαρμοστεί σε πολλούς NoSQL- αποφάσεις.

Αυτή η προσέγγιση ονομάζεται μέθοδος αναζήτησης ή σελιδοποίηση συνόλου κλειδιών. Λύνει το πρόβλημα του κυμαινόμενου αποτελέσματος (σημείωση: η κατάσταση με τη γραφή μεταξύ αναγνωσμένων σελίδων που περιγράφηκε νωρίτερα) και, φυσικά, αυτό που όλοι αγαπάμε, λειτουργεί πιο γρήγορα και πιο σταθερά από το κλασικό offset. Η σταθερότητα έγκειται στο γεγονός ότι ο χρόνος επεξεργασίας αιτήματος δεν αυξάνεται ανάλογα με τον αριθμό του ζητούμενου πίνακα (σημείωση: εάν θέλετε να μάθετε περισσότερα σχετικά με τη δουλειά των διαφορετικών προσεγγίσεων στη σελιδοποίηση, μπορείτε κοιτάξτε μέσα από την παρουσίαση του συγγραφέα. Μπορείτε επίσης να βρείτε συγκριτικά σημεία αναφοράς για διαφορετικές μεθόδους εκεί).

Μία από τις διαφάνειες μιλά για αυτόότι η σελιδοποίηση με κλειδιά, φυσικά, δεν είναι παντοδύναμη - έχει τους περιορισμούς της. Το πιο σημαντικό είναι ότι δεν έχει τη δυνατότητα να διαβάζει τυχαίες σελίδες (σημείωση: ασυνεπής). Ωστόσο, στην εποχή της ατελείωτης κύλισης (σημείωση: στο μπροστινό μέρος), αυτό δεν είναι τέτοιο πρόβλημα. Ο καθορισμός ενός αριθμού σελίδας για κλικ είναι ούτως ή άλλως μια κακή απόφαση στη σχεδίαση διεπαφής χρήστη (σημείωση: γνώμη του συγγραφέα του άρθρου).

Τι γίνεται με τα εργαλεία;

Η σελιδοποίηση στα πλήκτρα συχνά δεν είναι κατάλληλη λόγω της έλλειψης υποστήριξης οργάνων για αυτήν τη μέθοδο. Τα περισσότερα εργαλεία ανάπτυξης, συμπεριλαμβανομένων των διαφόρων πλαισίων, δεν σας επιτρέπουν να επιλέξετε ακριβώς πώς θα εκτελείται η σελιδοποίηση.

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

Ωστόσο, ο αριθμός των πλαισίων που υποστηρίζουν τη σελιδοποίηση σε κλειδιά αυξάνεται σταδιακά. Να τι έχουμε αυτή τη στιγμή:

(Σημείωση: ορισμένοι σύνδεσμοι αφαιρέθηκαν λόγω του γεγονότος ότι κατά τη στιγμή της μετάφρασης ορισμένες βιβλιοθήκες δεν είχαν ενημερωθεί από το 2017-2018. Εάν ενδιαφέρεστε, μπορείτε να δείτε την αρχική πηγή.)

Αυτή τη στιγμή χρειάζεται η βοήθειά σας. Εάν αναπτύξετε ή υποστηρίζετε ένα πλαίσιο που κάνει οποιαδήποτε χρήση της σελιδοποίησης, τότε σας ζητώ, σας προτρέπω, σας παρακαλώ να παρέχετε εγγενή υποστήριξη για σελιδοποίηση σε κλειδιά. Εάν έχετε ερωτήσεις ή χρειάζεστε βοήθεια, θα χαρώ να σας βοηθήσω (форум, Twitter, Φόρμα Επικοινωνίας) (σημείωση: από την εμπειρία μου με τον Marcus, μπορώ να πω ότι είναι πραγματικά ενθουσιασμένος με τη διάδοση αυτού του θέματος).

Εάν χρησιμοποιείτε έτοιμες λύσεις που πιστεύετε ότι αξίζει να έχετε υποστήριξη για σελιδοποίηση με πλήκτρα, δημιουργήστε ένα αίτημα ή ακόμα και προσφέρετε μια έτοιμη λύση, αν είναι δυνατόν. Μπορείτε επίσης να συνδέσετε αυτό το άρθρο.

Συμπέρασμα

Ο λόγος για τον οποίο μια τόσο απλή και χρήσιμη προσέγγιση όπως η σελιδοποίηση με πλήκτρα δεν είναι ευρέως διαδεδομένη δεν είναι ότι είναι δύσκολο να εφαρμοστεί τεχνικά ή απαιτεί μεγάλη προσπάθεια. Ο κύριος λόγος είναι ότι πολλοί έχουν συνηθίσει να βλέπουν και να εργάζονται με offset - αυτή η προσέγγιση υπαγορεύεται από το ίδιο το πρότυπο.

Ως αποτέλεσμα, λίγοι άνθρωποι σκέφτονται να αλλάξουν την προσέγγιση στη σελιδοποίηση, και εξαιτίας αυτού, η οργανική υποστήριξη από πλαίσια και βιβλιοθήκες δεν αναπτύσσεται ανεπαρκώς. Επομένως, εάν η ιδέα και ο στόχος της σελιδοποίησης χωρίς offset είναι κοντά σας, βοηθήστε στη διάδοσή του!

Πηγή: https://use-the-index-luke.com/no-offset
Συγγραφέας: Markus Winand

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο