[MySQL] Global item IDs

Βρήκες ή ψάχνεις κάτι ενδιαφέρον για τους τομείς των Μαθηματικών, της Φυσικής ή της Πληροφορικής; Για πέρνα να τα πούμε...

Συντονιστές: kostas213, markelos, Tulis

Απάντηση
Άβαταρ μέλους
drcypher
Portal Administrator
Portal Administrator
Δημοσιεύσεις: 2299
Εγγραφή: Τετ Νοέμ 01, 2006 7:33 am
Real Name: Κώτσος Φίλ
Gender: Male
Τοποθεσία: Μπροστά στην οθόνη

[MySQL] Global item IDs

Δημοσίευση από drcypher »

Να'μαι πάλι με τις βαρετές απορίες μου. Παρακαλώ όποιον έχει ελάχιστη εμπειρία (ή και επαγγελματική) να με βοηθήσει λίγο σε ένα "σχεδιαστικό" πρόβλημα που έχω.

Υπάρχουν λίγες δεκάδες (3-4) tables στα οποία είναι καταχωρημένα διαφορετικού τύπου δεδομένα. Χρήστες, ομάδες μελών, μαθήματα, εξετάσεις, αρχεία, υλικό, κτλ. (ένα παράδειγμα για το semfe.gr). Κάθε group από χρήστες έχει μια σειρά από δικαιώματα (READ, WRITE, MODERATE):
  • READ: Μπορεί μόνο να αναγνώσει τις πληροφορίες των εγγραφών του table
  • WRITE: Μπορεί να δημιουργήσει, τροποποιήσει ή διαγράψει μια εγγραφή, αλλά η "εντολή" του δεν υλοποιείται άμεσα. Περνάει σε έναν πίνακα στον οποίο αναμένει για έγκριση από κάποιον moderator
  • MODERATE: Μπορεί να κάνει ό,τι και αυτός που έχει πρόσβαση WRITE χωρίς να ζητήσει έγκριση ή να περιμένει, και ελέγχει και εγκρίνει/απορρίπτει τις "αιτήσεις" καταχωρήσεων των χρηστών με WRITE πρόσβαση.
Το σημαντικό είναι ότι προκύπτουν κάποια πρακτικά προβλήματα: Κάθε εγγραφή πρέπει να έχει έναν ιδιοκτήτη, κάθε moderator πρέπει να βλέπει το σύνολο των εγγραφών που εκκρεμούν και πρέπει να εξετάσει (και μπορεί να προέρχονται από πολλά διαφορετικά tabls). Οπότε μια υποομάδα του συνόλου όλων των tables της εφαρμογής πρέπει να έχουν τέτοια λειτουργικότητα (αλλά όχι όλη). Επίσης ο μηχανισμός πρέπει να δουλεύει με τρόπο που να μην χρειάζεται να δηλώνεται κάθε τρεις και λίγο το ποια είναι αυτά τα tables.

Άλλη μια λειτουργία είναι ο συσχετισμός εγγραφών διαφορετικών tables οι οποίοι συνδέονται και εντάσσονται σε έναν φάκελο. Π.χ. υπάρχει μια εγγραφή τύπου "Αρχείο" και μια εγγραφή (σε άλλο table) τύπου "Μάθημα", και θέλω να συσχετίσω αυτά τα δυο και να τα εντάξω στον φάκελο "Θέματα Εξετάσεων".

Να σημειώσω, επίσης, ότι η εφαρμογή έχει μηχανισμό με τον οποίο αντιστοιχίζει ένα σταθερό και μοναδικό ID για κάθε table ώστε να αναγνωρίζεται μονοσήμαντα και εύκολα.

Οι παραπάνω, καθώς και άλλες ακόμα λειτουργίες και εφαρμογές, (ειδικά όταν μιλάμε για σχέσεις many-to-many όπως στoυς Φακέλους με υλικό και μαθήματα, κτλ.) χρειάζονται κάποια "cross-table" references. Έτσι έχουν προκύψει αρκετοί πίνακες που πρέπει να έχουν αναφορές σε αντικείμενα (rows/items) που μπορεί να ανήκουν σε ένα από πολλά υποψήφια tables. Άρα εκτός από το ID, για να περιγραφεί το item πρέπει να αποδοθεί και το ID του πίνακα.

Φτάνουμε, λοιπόν, να έχουμε (προς το παρόν τουλάχιστον, ποτέ δεν ξέρεις τι προκύπτει) ένα σωρό tables τα οποία χρειάζονται δυο στοιχεία (table id, item id) για να περιγραφούν. Δεν με ενοχλεί ο χώρος τόσο πολύ (πρέπει να έχεις δυο columns), όσο το ότι προγραμματιστικά γίνεται λίγο δύσκαμπτο αυτό το σύστημα.

Σκέφτηκα, λοιπόν, να κάνω το εξής: Να ορίσω ένα table στο οποίο εγγραφές που χρησιμοποιούνται σε παραπάνω λειτουργίες, να ορίζουν εκεί το table στο οποίο βρίσκονται καθώς και άλλες unique ιδιότητες (που μοιράζονται ΟΛΕΣ οι εγγραφές, ανεξαρτήτως table, όπως στοιχεία δημιουργίας, επίπεδα πρόσβασης, κτλ.) και να τα συσχετίζω σε ένα global ID. Η αρχική δομή που σκέφτηκα ήταν η εξής:
  • global_item_id: Το unique (global) ID που χαρακτηρίζει τη συγκεκριμένη εγγραφή μέσα στον πίνακα (index, auto_increment)
    item_table: Τον πίνακα στον οποίο ανήκει η εγγραφή στην οποία αναφερόμαστε
    local_item_id: Το ID της εγγραφής τοπικά μέσα στον πίνακα. Αυτό αντιστοιχεί στο id (index, auto_increment) που έχει οριστεί στον πίνακα (item_table).
Ως προς τον χώρο, για κάθε εγγραφή θα έχουμε:
  • Στον πίνακα τοπικά, ένα ID που θα ξεχωρίζει την εγγραφή από τις άλλες στο ίδιο table. Ο τύπος μπορεί να είναι από tinyint μέχρι int.
  • Στον global πίνακα ένα index που θα ξεχωρίζει τα διαφορετικά μεταξύ τους cross-table item references. Θα έιναι int ώστε να μην εξαντληθεί
  • Στον global Πίνακα, αντίγραφο του τοπικού ID ώστε να εντοπίζεται εύκολα. Θα είναι int καθώς η χειρότερη περίπτωση local ID είναι int
  • Στον ίδιο global πίνακα, το ID του table στο οποίο κατοικεί πραγματικά η εγγραφή. Ένα tinyint (αν έχεις πάνω από 255 πίνακες έχεις άλλα προβλήματα)
Το αντίγραφο του local ID στον global πίνακα θα μπορούσε μαζί με το table id να ορίσει ένα unique key ώστε να ξεχωρίζουν μεταξύ τους οι εγγραφές και να γίνεται γρήγορα η αναζήτηση. Αλλά έτσι μεγαλώνει πολύ το index της βάσης.

Αυτό προς το οποίο κλίνω είναι να καταργήσω τελείως το local ID. Δηλ. κάθε πίνακας του οποίου οι εγγραφές πρόκεται να έχουν τέτοια κομφορτ, δε θα ορίζουν ένα δικό τους auto_increment id (που θα'ναι και index). Επίσης, έτσι θα αφαιρεθεί και το Local item id από τον global πίνακα. Αντ' αυτού σκέφτομαι να κάνω το εξής:
Όποτε πρέπει να προστεθέι μια εγγραφή σε κάποιον πίνακα, πάω πρώτα και κάνω μια καταχώρηση στον Global. Το global ID θα μου δώσει ένα Unique ID (μεγέθους int) το οποίο θα είναι τώρα Unique ανάμεσα σε ΟΛΟΥΣ τους πίνακες που διαθέτω. Όταν πάρω αυτό το ID θα κάνω καταχώρηση της εγγραφής στον ιδιαίτερο πίνακά της, καθ θα βάλω στη θέση του πάλαι ποτέ local unique ID το ID που μου έδωσε η global Καταχώρηση.

Έτσι παντού οι εγγραφές (και στους ίδιους τους πίνακες που ορίζονται, και σε εκείνους που κάνουν συνδέσεις ή προσφέρουν επιπλέον πληροφορίες, όπως αυτά που ανέφερα αρχικά) θα αναφέρονται με ένα Unique global ID (μεγέθους Int) γλιτώνοντας τα tinyints που χρειαζόμουν για τα tables.

Υπάρχουν, όμως, κάποια αρνητικά:
  • Ενώ το local id κάθε εγγραφής είχε μέγεθος που αντιστοιχούσε στις πραγματικές ανάγκες, τώρα αναγκαστικά θα γίνει Int (καθώς έτσι επιβάλλει το global ID)
  • Αυτό προκύτπτει από το γεγονός ότι τα IDs είναι αραιά όταν τα βλέπει κανείς τοπικά. Δηλ. μπορεί σε έναν πίνακα η πρώτη εγγραφή σου να είναι η ID=3 και η επόμενη να έχει ID=42300. Κι αυτό όχι επειδή οι ενδιάμεσες διαγράφηκαν, αλλά επειδή αποδόθηκαν ως ID σε εγγραφές άλλων tables.
  • Αντιστοίχως μεγαλώνουν τα indexes της MySQL καθώς πρέπει να αποθηκεύουν IDs μεγέθους int.
Δεν ξέρω, λοιπόν, αν η ενοποιημένη περιγραφή με μοναδικό τρόπο των εγγραφών σε διαφορετικά tables αξίζει τα παραπάνω αρνητικά (και όσα μπορεί να μην έχω σκεφτεί), αλλά αν κάποιος το έχει επιχειρείσει, ή έχει μαρτυρίες ανθρώπους που το σκέφτηκαν και πέτυχε ή απέτυχε, θα με γλίτωνε ενδεχομένως από ΠΑΡΑ ΠΟΛΥ ΚΟΠΟ ;)
Από τούδε και στο εξής ως στρογγυλοί αριθμοί ορίζονται τα πολλαπλάσια του 5 και οι δυνάμεις του 2.
lookfwd
Δημοσιεύσεις: 13
Εγγραφή: Τρί Νοέμ 28, 2006 4:56 am

Δημοσίευση από lookfwd »

Auto pou 8eleis na kaneis einai map ton polumorfismo twn antikeimenwn autwn se tables tis Database. Des Chapter 6 se auto to book gia tis epiloges pou exeis an kai diais8itika tis vrikes oles. Auto pou les einai to "one table per hierarchy".

Skeftesai san ma8imatikos. Poly formal.  :D  Auto einai kalo kai kako. Kalo giati mporeis na egkui8eis oti auto pou kaneis einai swsto, kako giati pairnei polu perissotero xrono to design. Pio sugkekrimena se apasxolei to size tis DB kai twn indexes kati pou pleon sto CS den einai design aspect at all.

Me analogo pneuma asxoleisai me to size twn IDs an 8a einai int i tinyint. Suni8ws ta vazeis ola int kai 3emperdeveis akoma kai an den xreiazetai. Ta tinyint kai polla alla perierga mporei na einai polu pio arga apo ta ints (logw twn apaitoumenwn alignment operations) kai gi'auto se polles DBs ginontai map eswterika se ints outws i allws.

Vasika to Global ID h Local IDs den mou fainetai na exei kamia simantiki diafora. Apla otan 8a kaneis nea kataxwrisi stin mia periptwsi dimiourgeis prwta to entry sto Global kai meta sto Local enw stin deuteri periptwsi to anti8eto. An den xrisimopoieis transactions (pou mallon den xrisimopoieis) einai kapws pio asfales to Local IDs. An (kai mallon etsi 8a einai) 3ekinas ta select queries sou apo to Global table kai pas meta sta Local, tote an kaneis Insert vazontas prwta Global, meta pairneis ID kai meta Local, 8a uparxoun merika ns opou 8a uparxei entry sto Global table kai den 8a uparxei sto Local me sunepoia na skaei i efarmogi sou. Kata ta alla den vlepw kamia ousiastiki diafora anamesa stis duo epiloges.
Έτσι παντού οι εγγραφές (και στους ίδιους τους πίνακες που ορίζονται, και σε εκείνους που κάνουν συνδέσεις ή προσφέρουν επιπλέον πληροφορίες, όπως αυτά που ανέφερα αρχικά) θα αναφέρονται με ένα Unique global ID (μεγέθους Int) γλιτώνοντας τα tinyints που χρειαζόμουν για τα tables.
Outws i allws mporeis na kaneis ola ta association tables na kanoun Refer sto unique ID tou Global Table me kostos ena join parapanw sta select sou.

Ena pragma pou einai pragmatika simantiko einai na kaneis swsto abstraction apo application side gia na mporeis na kaneis refactor tin DB xwris na skaei to sumpan. Mallon 8a to kaneis idi alla anyway, an exeis mia class mesa stin opoia exeis ola ta SQL kai sou epistrefei apla ta ResultSets stin kanoniki php selida 8a exeis kai maximum reuse kai DB abstraction.Me auton ton tropo mporeis na paizeis aneta gia na kaneis tune to performance.
Απάντηση

Επιστροφή στο “Ζητήματα Μαθηματικών - Φυσικής - Πληροφορικής”