Jump to content

antonch

Administrators
  • Posts

    1030
  • Joined

  • Last visited

  • Days Won

    7

Blog Entries posted by antonch

  1. antonch
    Ίσως όσα θα αναφερθούν παρακάτω να είναι γνωστά, και το post αυτό να μην είναι ενδιαφέρον. Όμως έχω την υποχρέωση να τα αναφέρω ξανά γιατί θεωρώ ότι είναι πράγματα στα οποία δεν δίνουμε ιδιαίτερη σημασία και τα οποία όταν διογκώνονται είναι δύσκολα στην επίλυση τους.
    Θα μιλήσουμε εδώ γιa την αρχιτεκτονική μιας database στον SQL Server, από τι αποτελείτε μια database, πιο είναι το ιδανικό αρχικό μέγεθος δημιουργίας της, τι πολιτική να ορίσω για το growth της.
    Μια database στον SQL Server αποτελείτε από τουλάχιστον 2 αρχεία. Το ένα από αυτά είναι το data αρχείο και το άλλο είναι το log αρχείο. Εάν δεν ορίσω κάτι συγκεκριμένο κατά την δημιουργία της database, αυτή είναι ένα πιστό αντίγραφο της model database που έχει ο SQL Server. Δηλαδή έχει όλα τα περιεχόμενα και το μέγεθος της model database. Γενικότερα να γνωρίζεται ότι κάθε φορά που φτιάχνεται μια database αυτή είναι ένα αντίγραφο της model database τουλάχιστον ως προς τα περιεχόμενα της, μιας και κατά την δημιουργία έχουμε την δυνατότητα να αλλάξουμε το μέγεθος, το location που θα είναι τα αρχεία της database και ένα σωρό άλλα options και παραμέτρους.
    Αν αναρωτιέστε ποια είναι τα περιεχόμενα της model database, αυτά είναι τα database system catalogs και τυχόν δικά μας objects όπως tables, views, stored procedures κλπ που έχουμε φτιάξει στην model με σκοπό να τα έχουμε διαθέσιμα στις νέες δικιές μας databases. (Παρατήρηση: Εάν έχω ήδη δικίες μου databases και φτιάξω στην model ένα νέο δικό μου object (πχ table) τότε αυτό δεν θα πάει και στις ήδη υπάρχουσες αλλά μόνο στις νέες).
    Όπως είπα και πιο πάνω μια database έχει τουλάχιστον 2 αρχεία το data file και το log file. Μια database μπορεί να έχει μέχρι 32.767 αρχεία. Το μέγεθος της μπορεί να φτάσει στα 524.258 ΤΒ για τις εκδόσεις 2005 και 2008 και στα 1.048.512 ΤΒ για τις εκδόσεις 2000 και 7.0. Κάθε data file δεν μπορεί να είναι μεγαλύτερο από 16 ΤΒ για τις εκδόσεις 2005 και 2008 και 32 ΤΒ για 2000 και 7.0, ενώ το κάθε log file δεν μπορεί να είναι μεγαλύτερο των 2 ΤΒ για τις εκδόσεις 2005 και 2008, 32 ΤΒ στην έκδοση 2000 και 4 ΤΒ στην έκδοση 7.0.
    Όταν δημιουργούμε μια database συνήθως ορίζουμε το αρχικό μέγεθος δημιουργίας της, τόσο για το data όσο και για το log file. O χώρος αυτός καταλαμβάνεται άμεσα από το δίσκο μας. Δηλαδή αν φτιάξω μια βάση με 10 ΜΒ data file και 3 ΜΒ log file τότε έχω μείον 13 ΜΒ από τα διαθέσιμα του δίσκου μου.
    Κάθε data file χωρίζεται εσωτερικά σε σελίδες (pages) των 8ΚΒ (8.192 Β), στις οποίες αποθηκεύονται τα δεδομένα που έχω στην βάση (data, metadata, indexes). Κάθε 8 συνεχόμενες σελίδες μου κάνουν ένα extent (64 ΚΒ ήτοι 16 extents / 1 ΜΒ). Υπάρχουν δύο είδη extent τα uniform (και οι 8 σελίδες ανήκουν στον ίδιο object πχ. Table) και τα mixed (οι 8 σελίδες δεν ανήκουν στο ίδιο object αλλά σε περισσότερα από ένα) .
     
    Σε κάθε data file οι πρώτες 8 σελίδες είναι εξ ορισμού δεσμευμένες από κάποιες ειδικού χειρισμού σελίδες που στην ουσία κάνουν trace τον ελεύθερο και δεσμευμένο χώρο σε αυτό. Αυτές είναι οι File Header (FH), Page Free Space (PFS), Global Allocation Map (GAM), Shared Global Allocation Map (SGAM) (περισσότερα)
    Κάθε σελίδα όπως είπα και πιο πάνω είναι 8 ΚΒ. Από αυτά τα 96 ΚΒ είναι ο page header στον οποίο είναι αποθηκευμένες οι εξής πληροφορίες page number, page type, το ποσό του free space στην σελίδα, και το allocation unit ID του object στο οποίο ανήκει η σελίδα. Με το που βάζω το πρώτο record αυτό μπαίνει αμέσως μετά από τον header και στο τέλος της σελίδα υπάρχει το record offset το οποίο μπαίνει με την αντίστροφη σειρά της εισαγωγής. Άρα ο πραγματικός ωφέλιμος χώρος που έχω πάνω σε κάθε σελίδα είναι 8060 bytes. Αυτό είναι και το μέγιστο record length που μπορώ να έχω πάνω σε ένα πίνακα. Δηλαδή εάν έχω ένα πίνακα που το record length του είναι 100 bytes αυτό σημαίνει ότι σε κάθε σελίδα χωράνε 80 records, και αν ο πίνακας έχει 200 εγγραφές τότε θέλω 3 σελίδες για να αποθηκευτούν τα δεδομένα του. (περισσότερα). Επίσης θα πρέπει να το τονίσω σε αυτό το σημείο ότι ένα record ανήκει πάντα σε μια σελίδα, δεν υπάρχει ποτέ περίπτωση να είναι το μισό σε μια και το άλλο σε άλλη. Θα προλάβω μερικούς συναδέλφους που θα πουν για τα datatypes varchar(max), nvarchar(max), text, ntext, images, varbinary(max) ότι είναι σε άλλες σελίδες αλλά είναι εκεί λόγω μεγέθους.
    Αυτό που σας έχω αναφέρει μέχρι τώρα είναι αρκετά σημαντικό για τον σχεδιασμό των tables, indexes σε μια database στον SQL Server. Διότι κυρίες και κύριοι συνάδελφοι εάν κάποιος αρχίζει και βάζει πεδία μέσα στον πίνακα (μέχρι 1024 πεδία μπορεί να έχει ένας πίνακας) και φτιάξει ένα record length 5000 bytes αυτό σημαίνει ότι μέσα σε μια σελίδα μπαίνει ένα και μόνο ένα record και μένουν ανεκμετάλλευτα 3000 bytes. Εάν λοιπόν ο πίνακας μου έχει 10.000 records σημαίνει ότι θέλω και 10.000 σελίδες που στην κάθε μία χάνω 3.000 bytes, άρα 3.000 bytes x 10.000 σελίδες = 30.000.000 bytes / 1024 bytes = 29296 KB / 1024 KB=28 MB χαμένου χώρου στον δίσκο, μιας και αν θεωρήσουμε ότι υπάρχει μόνο αυτός ο πίνακας στην βάση μας (κάτι φυσικά που δε συμβαίνει στην πραγματικότητα) το data file μας έχει δεσμεύσει χώρο στο δίσκο ίσο με 78 ΜΒ. Όπως γίνεται άμεσα κατανοητό ο κακός σχεδιασμός επηρεάζει άμεσα και το performance πώς? η απάντηση σε λίγο.
    Επίσης όταν δημιουργούμε μια database σκόπιμο θα είναι να έχουμε κάνει μια εκτίμηση για το μέγεθος για τους πρώτους 3 μήνες της ζωής της ώστε να δεσμεύσουμε τον χώρο αυτό κατά την στιγμή της δημιουργίας της. Ο σκοπός του να γίνει κάτι τέτοιο είναι σημαντικός διότι αν δώσουμε κάτι το οποίο είναι μικρό και σε συνδυασμό με το τι έχουμε ορίσει σαν file growth policy, που συνήθως το αφήνουμε μικρό, και έχουμε μεγάλο αριθμό από transactions αυτό θα μας οδηγήσει μαθηματικά στο να έχουμε συνεχόμενο ΙΟ στον δίσκο μας επειδή ο SQL Server θα αιτείτε συνέχεια επιπλέον χώρο σε αυτόν μέσω του λειτουργικού συστήματος καθώς η database θα γεμίζει συχνότερα. Αυτό είναι καταστροφικό σε συστήματα που έχουν πολλά transactions.
    Πριν προχωρήσω στην διαδικασία θα επισημάνω την λέξη εκτίμηση. Αυτό σημαίνει ότι μετά από πάροδο μερικών ημερών κάνω έναν έλεγχο για να δω αν η εκτίμηση μου είναι σωστή και αναλόγως πράττω, μεγαλώνω ή μικραίνω την database. Τώρα πως κάνουμε την εκτίμηση αυτή.
    Πρώτα από όλα επιλέγουμε μια χρονική περίοδο για την εκτίμηση μας πχ 1 μήνα , 2 μήνες κλπ ανάλογα με το είδος της εφαρμογής που χρησιμοποιεί την database, πχ σε ένα ERP θα μπορούσαμε διαλέξουμε 3 μήνες.
    Έπειτα βρίσκω το record length του κάθε πίνακα αυτό το πολλαπλασιάζω με τον αριθμό των records που εκτιμώ ότι θα μπουν στην χρονική περίοδο που έχω διαλέξει. Το αποτέλεσμα τα κάνω σελίδες και τις σελίδες τις κάνω MB. Το ίδιο αλλά κάπως διαφοροποιημένο το κάνω και για τους indexes. Το άθροισμα όλων αυτών μου δίνει το αρχικό μέγεθος δημιουργίας της database μου.
    Δεν θα το αναλύσω περισσότερο εδώ απλά θα σας παραπέμψω στα books online όπου έχει αναλυτικά όλη την διαδικασία. Απλά κάντε αναζήτηση για Estimating the Size of a Database.
    Μέχρι τώρα δεν έχω αναφέρει τίποτα για το άλλο αρχείο που έχει μια database, το log αρχείο. Προσωπικά πιστεύω ότι είναι το σημαντικότερο αρχείο σε μία database. Σε αυτό καταγράφονται όλα εκτός από τα select statements και τα blob πεδία αν και αυτά έχω την επιλογή να πω να καταγράφονται. Συνήθως το αρχικό μέγεθος δημιουργίας του είναι το 30% του αρχικού μεγέθους του ή των data αρχείου (αρχείων). Δηλαδή αν έχω 100 ΜΒ data φτιάχνω log ίσο με 30ΜΒ. Βέβαια αυτό αν και είναι κανόνας, πάντα υπάρχει περιθώριο καταστρατήγησης του, όπως για παράδειγμα αν έχω heavily transactional databases, όπου σε αυτές τις περιπτώσεις είναι ανάλογα μεγαλύτερο. Έδω όμως θα τονίσω ότι χρειάζεται ιδιαίτερη προσοχή στην πολιτική για το πως αυτό θα μεγαλώνει όταν γεμίσει. Αυτό που έχω δει είναι ότι συνήθως βάζετε κάτι μικρό ή αφήνετε το default που είναι 10%. Αυτό είναι και το λάθος σας. Καλό είναι να βάζετε σαν πολιτική το αρχικό μέγεθος του. Δηλαδή αν έχω 30ΜΒ Log λέω στo file growth του 30ΜΒ ούτε 100% ούτε τίποτα σε ποσοστό. Και αυτό γιατί πολλοί θεωρούν το Log σαν έναν κουβά όμως τα πράγματα δεν είναι έτσι. Εσωτερικά το log χωρίζεται σε virtual logs. Ο σκοπός μου είναι να έχω πάντα ισομεγέθη virtual log ώστε να μην μου εμφανισθεί το φαινόμενο το Log file να είναι μεγαλύτερο από το ή τα data file(s). Σε κάποιο άλλο post μου θα σας πω περισσότερα για αυτό.
    Τώρα βέβαια θα πρέπει να πω ότι αν παίρνω backup την βάση μου το log γίνεται truncate. Προσοχή δεν μειώνεται σαν μέγεθος στον δίσκο αλλά εσωτερικά γίνεται truncate. Αυτό σημαίνει ότι ο εσωτερικός χώρος που ελευθερώνεται επαναχρησιμοποιείται. Λογικά αν έχω εκτιμήσει σωστά το αρχικό μέγεθος δημιουργίας του log file και κάνω καθημερινό backup δεν θα το δω ποτέ να μεγαλώνει πέρα από το αρχικό του μέγεθος.
    Για να δούμε πως χρησιμοποιείται το log. Τρεις είναι οι βασικοί παράγοντες που επηρεάζουν το performance, CPU, MEMORY, DISK IO. Δυστυχώς όμως το χειρότερο από όλα σε performance σε σχέση με τα άλλα είναι ο δίσκος. Σκοπός του SQL Server είναι να έχει το μικρότερο δυνατό disk io. Για να το κάνει αυτό χρησιμοποιεί μνήμη και φυσικά το log file.
    O SQL Server δεσμεύει ένα ποσό από την διαθέσιμη μνήμη του συστήματος. Ένα ποσό από αυτή την μνήμη ανήκει στη buffer cache. Για να δούμε όλη την διαδικασία με ένα παράδειγμα.
    Είπαμε πιο πάνω ότι τα δεδομένα μου είναι αποθηκευμένα σε σελίδες των 8KB. Έτσι όταν κάποιος χρήστης κάνει ένα select, insert, update, delete αυτό που κάνει ο SQL Server είναι να δει αν υπάρχουν στην buffer cache οι σελίδες που θα επηρεαστούν από την ενέργεια αυτή. Εάν δεν είναι τότε τις διαβάζει από τον δίσκο και τις βάζει στην buffer cache. Το επόμενο βήμα του είναι να εκτελέσει την ενέργεια πάνω στις σελίδες που είναι στην buffer cache. Για το μεν select επιστρέφει τα δεδομένα στον χρήστη, για τις άλλες ενέργειες όμως κάνει ακόμα ένα βήμα γράφει την ενέργεια στο log file. Γιατί το κάνει αυτό; Η απάντηση είναι απλή κάνει minimize το ΙΟ. Στην ουσία οι ενέργειες θα γραφτούν στο data file όταν γίνει η διαδικασία που φέρει το όνομα checkpoint process. Τι κάνει αυτή; Σε τακτά χρονικά διαστήματα έρχεται ο SQL Server και διαβάζει το log είτε από την αρχή εάν είναι η πρώτη φορά είτε από το σημείο που είχε σταματήσει την προηγούμενη φορά η διαδικασία αυτή. Και όσα transactions είναι commited βλέπει ποιες είναι οι σελίδες που έχουν επηρεασθεί από αυτά και τις γράφει στον data file δηλαδή στον δίσκο. Τώρα κάποιος θα αναρωτηθεί και αν πέσει το ρεύμα πριν γίνει η διαδικασία αυτή; ΔΕΝ ΥΠΑΡΧΕΙ ΚΑΝΕΝΑ ΠΡΟΒΛΗΜΑ. Διότι κάθε φορά που ο SQL Server ξεκινάει κοιτάζει το Log file και ότι transaction είναι ολοκληρωμένο και δεν υπάρχει στα data file αναπαράγετε, ότι ήταν σε εξέλιξη γίνεται rollback. Η διαδικασία αυτή λέγεται recovery process. Άρα θα έχω όλα μου τα δεδομένα εκτός βέβαια από αυτά που δεν είχαν προλάβει να ολοκληρωθούν.
    Σας χρωστάω μια απάντηση από πιο πάνω. Θυμηθείτε το παράδειγμα με τις 10.000 σελίδες όπου στην κάθε μία έχω ένα record. Βάλτε με το μυαλό σας τι θα γίνει αν απλά θελήσω να διαβάσω όλα τα δεδομένα του πίνακα. Απλά θα έχω "τσακίσει" τους τρεις βασικούς παράγοντες που επηρεάζουν την απόδοση του SQL Server, και αυτό γιατί για να κινηθούν οι κεφάλες στον δίσκο θα πρέπει να δώσει η εντολή η CPU αυτές θα διαβάσουν τα δεδομένα , άρα μεγάλο ΙΟ και αυτά θα πρέπει αν μεταφερθούν στην μνήμη.
    Έτσι απλά! τα φόρτωσα όλα, και αυτό γιατί όταν σχεδίαζα την βάση μου δεν έλαβα υπόψη μου την αρχιτεκτονική του SQL Server.
  2. antonch
    Πότε τελικά λέμε ότι αυτός ο άνδρας είναι φαλακρός;
    Η φαλάκρα είναι κάτι το οποίο σε αρκετούς άνδρες δημιουργεί ψυχολογικά προβλήματα σε άλλους πάλι κανένα, και σε κάποιους άλλους μερικές φορές τους ακουμπάει για κάποια χρονικά διαστήματα αλλά γενικά εχουν συμβιβαστεί μαζί της.
    Πέρα όμως από αυτό το ερώτημα παραμένει. Πότε τελικά κάποιος είναι φαλακρός;
    Αν για παράδειγμα από τα μαλλιά μου βγάλω μια τρίχα είμαι φαλακρός; Η προφανής απάντηση είναι όχι. Αν βγάλω και δεύτερη και τρίτη και τέταρτη αυτό με κάνει φαλακρό; Προφανώς όχι.
    Αν όμως χάσω εκατοντάδες τρίχες αυτό με κάνει φαλακρό; Ποιός μπορεί να το απαντήσει αυτό με σιγουριά.
    Αν συνεχίσω να χάνω εκατοντάδες τρίχες καθημερινά και ένα πρωινό ο γιός μου φωνάξει «Πατέρα είσαι φαλακρός» είμαι τελικά φαλακρός ή έχω αρχίσει να φαλακρένω.
    Υπάρχει τελικά κάτι το οποίο μπορεί να ορίσει το αν είμαι φαλακρός ή όχι;
    Στην φιλοσοφία αυτο είναι το Σόφισμα του σωρείτη το οποίο είναι ένα λογικό παράδοξο που ασχολείται με την ασάφεια των κατηγορημάτων σε μία λογική πρόταση δείχνοντας ότι είναι πιθανό να μην υπάρχει ένα σαφές όριο ανάμεσα σε ένα κατηγόρημα και την άρνησή του.
    Στον προγραμματισμό έχουμε μάθει να λαμβάνουμε αποφάσεις με βάση την δυαδική λογική (if/else). Έχουμε δομήσει το τρόπο σκέψης μας με αυτό το pattern. Οτιδήποτε πέρα από αυτό μας ξενίζει, μας δημιουργεί πρόβλημα, μας ανατρέπει τον τρόπο σκέψης μας.
    Θυμάμαι χαρακτηριστικά το CheckBox Control το οποίο όταν πρωτοβγήκε δημιούργησε θύελα αντιδράσεων και αυτό γιατί είχε τρεις διαφορετικές περιπτώσεις checked/unchecked/indeterminate. Η τελευταία ήταν αυτή που δημιουργούσε το πρόβλημα. Δεν μπορούσαμε να καταλάβουμε το λόγο ύπαρξης της. Τι σημαίνει ούτε ναι ούτε όχι. Ταλαιπώρησε και συνεχίζει να ταλαιπωρεί αρκετό κόσμο της πληροφορικής.
    Το να γράψεις λογισμικό τελικά δεν είναι μια δυαδική λογική ή είναι;
    Η τρίτη επιλογή πρέπει να λαμβάνεται υπόψη ή όχι;
    Ποιος μπορεί να δώσει ασφαλή απάντηση, και μιλάω για μια απάντηση η οποία να είναι αποδεκτή από όλους. (Δύσκολο)
    Προς τους αδερφούς developers
    Την επόμενη φορά που θα γράψετε software μη σκεφτήτε το άλλο το περίεργο.
    Σκεφτήτε με την λογική του if/else αλλά αλλάξτε το στη τελική σας υλοποίηση με τη switch αφήνοντας ένα παράθυρο στην πιθανότητα
    Καλές Διακοπές
  3. antonch
    Σήμερα λέω να κάνω κάτι που ίσως να σας αλλάξει πολλά στον τρόπο με τον οποίο αντιμετωπίζετε το transaction log.
    Είμαι σίγουρος ότι οι περισσότεροι έχετε το πρόβλημα το transaction log να μεγαλώνει ανεξέλεγκτα και να φωνάζετε βοήθεια.
    Να διαμαρτύρεστε που η Microsoft κατάργησε την TRUNCATE_ONLY.
    Αλλά είπα ήδη πολλά, δείτε το video και θα εξηγηθούν πολλά.

    Αυτά και ελπίζω να σας άρεσε.
    Υ.Γ Αυτό ήταν ένα video το οποίο πραγματικά γούσταρα που το έκανα για αυτό και τρόπος με τον οποίο μίλαγα, δεν έχει να κάνει με τίποτα άλλο.
  4. antonch
    Δύο μέρες ΔΩΡΕΑΝ SQL Server Training
    Σήμερα ξεκινάμε το διήμερο free SQL Server training με 24ώρα live webcasts όπου θα δείτε στιγμιότυπα από το PASS Summit 2011. Με την υποστήριξη της Dell, το μέρος αυτό του 24 Hours of PASS θα σας παρουσιάσει τα σημαντικότερα νέα του SQL Server κατευθείαν στον υπολογιστή σας σε δύο 12ωρα, 7-8 Σεπτ., όπου κάθε 12ωρο ξεκινά στις 15:00 ώρα Ελλάδας. Εγγραφείτε εδώ για να παρακολουθήσετε τα αγαπημένα σας θέματα!
    Δείτε τι λένε γνωστοί ομιλητές για το 24 Hours of PASS:
    More Free Training from PASS - Rob Farley Watch Me (and 23 Others!) During 24 Hours of PASS: Summit Preview - Jes Schultz Borland Register for 24 Hours of PASS NOW! - Tim Radney Presenting Hardware 301 at 24 Hours of PASS on September 7 - Glenn Berry Βιαστείτε – Οι θέσεις είναι περιορισμένες!

    Δείτε το #24hop στο Twitter για τις τελευταίες συζητήσεις κ’ ενημερώσεις!
  5. antonch
    Πριν ξεκινήσω να περιγράφω το συγκεκριμένο εργαλείο, οφείλω να καταθέσω την άποψη μου γι’ αυτό. ΕΙΝΑΙ ΚΑΤΑΠΛΗΚΤΙΚΟ!!!.
    Όσοι έχετε ασχοληθεί από παλία με τον SQL Server, προσωπικά ασχολούμαι από την έκδοση 6.0 (1996), θα έχετε παρακολουθήσει την εξέλιξη του συγκεκριμένου εργαλείου. Σε κάθε έκδοση είχαμε κάποιες βελτιώσεις. Όμως στην έκδοση του SQL Server 2008 πιστεύω ότι έχουμε τις περισσότερες αλλά και τις σημαντικότερες βελτιώσεις. Eίναι μια διαφορετική υλοποίηση του εργαλείου που δίνει μια πληρέστερη εικόνα τόσο στον Database Admin όσο και στον Database Developer.
    Ας ξεκινήσω λοιπόν την περιήγηση στο εργαλείο αυτό.
    Πρώτη αλλαγή είναι το πως τον ξεκινάς. Δεν είναι πλεόν στο Management του SSMS (SQL Server Management Studio). Αλλά πρέπει να κάνεις δεξί κλικ στον server στον Object Explorer και να επιλέξεις την επιλογή Activity Monitor από το menu επιλογών.

    Μετά από αυτο θα δούμε το νέο Activity Monitor

    Όπως θα δείτε υπάρχουν τέσσερα γραφήματα τα οποία δείχνουν
    % Processor Time
    Το ποσοστό του χρόνου που έχει διανυθεί και τον οποίο ο επεξεργαστής έχει δαπανήσει για να εκτελέσει non-idle threads για τον SQL Server σε όλες τις CPUs.
    Waiting Tasks
    Ο αριθμός των tasks τα οποία περιμένουν πόρους είτε του επεξεργαστή, είτε για Ι/Ο, είτε για μνήμη.
    Database I/Ο
    Το transfer rate σε MB/Sec για την μεταφορά των δεδομένων είτε από την μνήμη στον δίσκο, είτε από το δίσκο στη μνήμη, είτε από δίσκο σε δίσκο.
    Batch Requests/sec
    Ο αριθμός των batches που έχουν σταλθεί στον SQL Server.
    Ακριβώς κάτω από τα γραφήματα υπάρχουν τέσσερεις λίστες
    Processes


    Εδώ βλέπουμε κάθε connection που έχει γίνει στον SQL Server και τι ακριβώς κάνει. Η λίστα περιέχει τις εξής πληροφορίες


    Session ID

    Ο μοναδικός αριθμός που παίρνει κάθε connection το γνωστό SPID. Αν δείτε δίπλα του μια κλεψύδρα εύκολα θα καταλάβετε ότι κάτι περιμένει ή είναι μπλοκαρισμένο από κάποιο άλλο connection.

    User Process Flag



    Δείχνει τα αν το συγκεκριμένο process είναι internal (τιμή 0) ή user (τιμή 1). By default δείχνει μόνο τα user αλλά μπορείτε να το αλλαξετε πατώντας το drop down που υπάρχει στο header της κολώνας. Υπάρχει και η τιμή All που τα δείχνει όλα.

    Login



    Το login name με το οποίο το συγκεκριμένο process έχει γίνει.

    Database



    Η τρέχουσα database στην οποία το connection είναι συνδεδεμένο.

    Task State



    Δείχνει εάν το process είναι ενεργό ή όχι. Εδώ μπορώ να έχω τις εξής τιμές
    Done: Ολοκλήρωση Pending: Το process περιμένει ένα worker thread Runnable: Κάτι έχει κάνει λίγο πριν αλλά αυτή την στιγμή δεν κάνει τίποτα αλλά είναι ακόμα συνδεδεμένο. Running: Κάτι κάνει αυτή την στιγμή Suspended: Το process αν και έχει δουλειά να κάνει, έχει σταματήσει γιατί κάτι το εμποδίζει να συνεχίσει. Δες το γιατί από την κολώνα Wait Type.
    Σχόλιο: Διευκρίνηση για το αφεντικό, αυτό δεν δείχνει αν χρήστης το φυσικό πρόσωπο δηλαδή κοιμάτε ή όχι πάνω στο πληκτρολόγιο του. Το λέω γιατί κάποιος πελάτης, μου είπε κάτι τέτοιο στο παρελθόν!!!.


    Command



    Δείχνει το command type (πχ SELECT, DBCC, INSERT, AWAITING COMMAND,…) το οποίο εκτελείτε. Προσοχή δεν δείχνει το πραγματικό command. Εαν θέλετε να δείτε το πραγματικό κάντε δεξί κλικ και επιλέξτε Details.

    Application



    Δείχνει την εφαρμογή με την οποία έχει γίνει το connection. Αυτό μπορεί να ορισθεί από τον developer πάνω στο connection string με το keyword Application Name.

    Wait Time (ms)



    Εαν το process είναι bloked δείχνει τον χρόνο που είναι σε αναμονή σε milliseconds αλλιώς δείχνει 0.

    Wait Type



    Δείχνει το event το οποίο περιμένει το process για να συνεχίσει.

    Wait Resource



    Δείχνει το resource το οποίο περιμένει το process να ελευθερώθεί για να συνεχίσει.

    Blocked By



    Δείχνει το SPID (Session ID) το οποίο έχει μπλοκάρει το process αυτό.

    Head Blocker



    Εαν η τιμή είναι 1 αυτό σημαίνει ότι το Session ID που φαίνεται στην Blocked By κολώνα είναι ο επικεφαλής στην αλυσίδα των μπλοκαρισμάτων.

    Memory Use (KB)



    Δείχνει το ποσό της μνήμης η οποία χρησιμοποιείται από το process αυτό.

    Host



    Δείχνει το computer name από όπου έχει γίνει το connection αυτό.

    Workload Group



    Δείχνει το όνομα του Resource Governor workload group για το query αυτό.
    Resource Waits


    Η λίστα αυτή δείχνει πληροφορίες για την αναμονή στα resources και περιλαμβάνει τις εξής πληροφορίες:
    Wait Category

    Είναι οι κατηγορίες που συγκεντρώνονται για τα wait type statistics. Κάτι αντίστοιχο μπορώ να πάρω με την dmv sys.dm_os_wait_stats.
    Wait Time (ms/sec)
    Ο χρόνος wait time σε ms/sec για όλα τα task τα οποία περιμένουν κάποιο ή κάποια resources στην συγκεκριμένη κατηγορία από το τελευταίο update interval.
    Recent Wait Time (ms/sec)
    O σταθμικός μέσος του wait time ms/sec για όλα τα task τα οποία περιμένουν ένα ή περισσότερα resources στην κατηγορία από το τελευταίο update interval.
    Average Waiter Count
    Ο αριθμός των tasks που περιμένουν για κάποιο ή κάποια resources στην συγκεριμένη κατηγορία σε μια δεδομένη στιγμή.
    Cumulative Wait Time (sec)
    Ο συνολικός χρόνος που τα tasks πρέπει να περιμένουν για ένα ή περισσότερα resources στην κατηγορία από τοτε που ξεκίνησε ο SQL Server ή από τότε που εκτελέσθηκε τελευταία φορά ή DBCC SQLPERF.

    Data File I/O


    Η λίστα αυτή δείχνει πληροφορίες για τα database files των databases που υπάρχουν στον SQL Server, και περιέχει τις εξής πληροφορίες:
    Database

    Το όνομα της βάσης. File Name

    Το όνομα (φυσικό) του αρχειου της βάσης. MB/sec Read

    Το τελευταίο read activity, σε megabytes ανά second, για το database file. MB/sec Written

    Το τελευταίο write activity, σε megabytes ανά second, για το database file. Response Time (ms)

    Ο Μ.Ο του response time, σε milliseconds, για το τελευταίο read-and-write activity στο database file.
    Recent Expensive Queries


    Η λίστα αυτή δείχνει πληροφορίες για τα πιό ακριβά σε resources queries τα οποία έχουν τρέξει στον SQL Server τα τελευταία 30 sec.
    H πληροφορία βγαίνει από την ένωση των dmv sys.dm_exec_requests και sys.dm_exec_query_stats και περιλαμβάνει queries τα οποία είναι σε εξέλιξη αλλά και αυτά τα όποία έχουν τελειώσει μέσα στην χρονική περίοδο των 30 sec, και περιλαμβάνει τις εξης πληροφορίες:
    Query

    Το query statement το οποίο γίνεται monitor.
    Executions/min

    Τα executions ανα λεπτό για το query.
    CPU (ms/sec)

    Η χρήση της CPU από το query
    Physical Reads/sec

    Η χρήση ανα second των physical reads από το query.
    Logical Writes/sec

    Η χρήση ανά second των logical writes από το query.
    Logical Reads/sec

    Η χρήση ανά second των logical reads από το query.
    Average Duration (ms)

    Η μέση διάρκεια εκτέλεσης του query σε milliseconds.
    Plan Count

    O αριθμός των cached query plans για αυτό το query. Ένας μεγάλος αριθμός δείχνει ότι χρειάζεται να στρέψουμε την προσοχή μας στο query αυτό.
  6. antonch
    Μέσα σε έναν οργανισμό θα συναντήσουμε πολλές batabase οι οποίες περιέχουν business-critical data. Πάνω από αυτές θα βρούμε applications τα οποία διαχειρίζονται τα δεδομένα αυτά. Καθώς ο όγκος των δεδομένων γεωμετρικά αυξάνετε, αλλά και ο αριθμός των χρηστών που ζητούν πρόσβαση σε αυτά μεγαλώνει, είναι κατανοητό σε όλους ότι η διαθεσιμότητα των δεδομένων πρέπει να είναι αδιάλειπτη, όπως επίσης και η ταχύτητα απόκρισης στα ερώτημα και στα transactions των χρηστών πρέπει να είναι μεγάλη και σταθερή. Ο SQL Server 2008 παρουσίασε μια σειρά από εργαλεία τα οποία σκοπό έχουν να βοηθήσουν τον DBA στο να παρέχει τα παραπάνω. Ένα από αυτά τα εργαλεία είναι και ο RESOURCE GOVERNOR με τον οποίο θα ασχοληθώ σε αυτό το post μου.
    Το πρόβλημα
    Στις προηγούμενες εκδόσεις του SQL Server όταν ήμασταν σε ώρες αιχμής κάποιες βασικές εφαρμογές βλέπαμε να υποφέρουν κυριολεκτικά σε performance και αυτό διότι υπήρχαν άλλες λιγότερο βασικές εφαρμογές που έτρεχαν παράλληλα εκτελούσαν "βαριές εργασίες". Όμως ακόμα και στην περίπτωση που έχουμε μια βασική εφαρμογή αλλά μεγάλο αριθμό χρηστών, που ο καθένας όμως κάνει εργασία με διαφορετικό βάρος στην παραγωγική διαδικασία της ημέρας, πόσες φορές έχουμε έρθει αντιμέτωποι με προβλήματα όπως η τιμολόγηση ή το λογιστήριο ή ακόμα χειρότερα το αφεντικό να "σέρνονται"; Η αιτία για όλα αυτά είναι ότι όλες οι εφαρμογές και όλοι οι χρήστες έπαιρναν στο μέτρο του δυνατού ισόποσα ποσοστά χρήσης τόσο της μνήμης όσο και της CPU.
    Την λύση στα παραπάνω ήρθε να δώσει ο Resource Governor.
    Τί είναι ο Resource Governor?
    Ταξινομεί τα εισερχόμενα connections και τα βάζει το καθένα σε προκαθαρισμένο workload group. Ομαδοποιεί τα resources σε resource pools, που το κάθε ένα ορίζει όρια όσον αφορά την χρήση της CPU και της μνήμης. Συνδέει τα workload groups σε resource pools. Παρακολουθεί τα resources χρησιμοποιώντας το workload group. Ορίζει την προτεραιότητα μεταξύ των workload groups. Τι είναι τα Resource Pools?
    Ένα recourse pool συσχετίζεται με τους φυσικούς πόρους που ο server μας έχει. Με την ολοκλήρωση της εγκατάστασης του SQL Server 2008 έχω εκ προοιμίου δύο resource pools, τα default (χρησιμοποιείται για όλα τα groups που δεν τους έχω ορίσει pool) και internal (είναι για τις εσωτερικές εργασίες του SQL Server). Μπορώ να φτιάξω και τα δικά μου και κάθε resource pool μπορώ να ορίσω (δεν μπορώ να το κάνω στα default και Internal) τα εξής:
    Minimum CPU percentage (0->100) Maximum CPU percentage (100->0) Minimum memory percentage (0->100) Maximum memory percentage (100->0) Τι είναι τα Workload Groups?
    Είναι ο container για τα session requests τα οποία τα ίδια κριτήρια ταξινόμησης. Με την ολοκλήρωση της εγκατάστασης του SQL Server 2008 έχω εκ προοιμίου δύο workload groups τα default και internal, τα οποία εξ' ορισμού ανήκουν στα default & internal resource pools. Εδώ θα πρέπει να επισημάνω ότι και αυτά που θα φτιάξω εγώ μπορούν να ανήκουν σε ένα και μόνο ένα resource pool. Σε κάθε workload group μπορώ να ορίσω τα εξής:
    Assign a Priority Ορίζω το priority (Low, Medium, High).
    Limit Maximum Requests Ορίζω τον αριθμό των ταυτόχρονων requests τα οποία επιτρέπονται να εκτελεστούν στο συγκεκριμένο workload group.
    Limit CPU Time (Sec) Ορίζω το maximum χρόνο της CPU που ένα request μπορεί να χρησιμοποιήσει.
    Limit Memory Grant % Ορίζω το maximum ποσοστό μνήμης που ένα request μπορεί να πάρει από το pool.
    Limit Grant Timeout (Sec) Ορίζω το maximum του χρόνου που ένα query θα περιμένει ένα resource να γίνει διαθέσιμο πριν αποτύχει.
    Limit Degree of Parallelism Ορίζω τον maximum αριθμό επεξεργαστών που το request μπορεί να χρησιμοποιήσει.
    Τι είναι τo Classifier Function?
    Είναι το function αυτό με το οποίο γίνεται η ανάθεση του νέου session/εφαρμογή σε workload group. Αυτό είναι ένα και μόνο ένα κάθε φορά δηλαδή δεν μπορώ να έχω ταυτόχρονα δύο classifier functions. Μετά από κάθε αλλαγή σε αυτό θα πρέπει να κάνω reconfigure τον R.G.
    Μέσα σε αυτό το function μπορώ να χρησιμοποιήσω system functions για να κατατάξω το session/εφαρμογή στο workload group όπως τα
    HOST_NAME APP_NAME Προσοχή σε αυτό διότι είναι κάτι το οποίο ορίζεται μέσα στο connection string της εφαρμογής και μπορεί να αλλαχθεί ανά πάσα στιγμή από κάποιον με σκοπό να πάρει καλύτερο workload group.
    SUSER_NAME SUSER_SNAME IS_SRVROLEMEMBER IS_MEMBER ORIGINAL_DB_ΝΑΜΕ και άλλα Δέστε στα BOL τι κάνει το καθένα.
    Υπάρχουν περιορισμοί?
    Βέβαια υπάρχουν και περιορισμοί και αυτοί είναι:
    Δουλεύει μόνο με το Database Engine. Δηλαδή όχι Analysis, Integration, Reporting Services. Ορίζεται ξεχωριστά για κάθε instance. Δηλαδή δεν έχω κεντρική διαχείριση για όλα τα instances του SQL Server. Δεν έχω την δυνατότητα να ελέγξω IO allocations μόνο MEMORY & CPU (μάλλον στην επόμενη έκδοση) Σε καμία περίπτωση δεν μπορώ να πως σε ένα συγκεκριμένο query να πάει γρηγορότερα. Ο Resource Governor είναι διαθέσιμος μόνο στην Enterprise Edition του SQL Server 2008. Παρατηρήσεις
    Ο R.G εφαρμόζεται μόνο όταν υπάρχει ανάγκη να εφαρμοστεί. Πχ. έχω μια εφαρμογή η οποία ανήκει σε ένα workload group στο οποίο έχω ορίσει max CPU 40%. Εφόσον την δεδομένη χρονική στιγμή που εκτελείται η εφαρμογή δεν υπάρχει κάποια άλλη που να είναι σε κάποιο άλλο group με μεγαλύτερο ποσοστό, δύναται να χρησιμοποιήσει όλη την CPU. To άθροισμα των μικρότερων (minimum) τιμών δεν μπορεί να περνάει το 100% Ότι πόρους αφήνουν ελεύθερους τα pools αυτά μοιράζονται. DEMO
    Την υλοποίηση του demo την έκανα με T-SQL. Βέβαια υπάρχει και γραφικό περιβάλλον για να υλοποιήσεις τον Resource Governor όπως θα δείτε και στα παρακάτω screen shoots.


    To demo θα το βρείτε εδώ
     
    Τα σχόλια σας είναι πάντα ευπρόσδεκτα!
  7. antonch
    Πρόσφατα με έναν συνεργάτη μου που είναι dealer μια ελληνικής εταιρίας που έχει ERP αντιμετωπίσαμε το παρακάτω πρόβλημα όταν πήγαμε να εγκαταστήσουμε τον SQL Server 2005 Standard Edition σε pc που είχε εγκατεστημένο Window XP Pro Ελληνικό.
    Σε συνεργασία μαζί του (ευχαριστώ Δημήτρη) σας παρουσιάζουμε την λύση.
    Κατά την στιγμή της εγκατάστασης του SQL Server 2005 ή 2008 παίρνουμε το παρακάτω μήνυμα λάθους στο σημείο που πάει να ενημερώσει τον MSXML Parser.

    The Windows Installer service cannot update the system file C:\WINDOWS\system32\msxml6r.dll because the file is protected by Windows. You may need to update your operating system for this program to work correctly

     
    Αυτό γίνεται διότι η εγκατάσταση του SQL Server 2005 και του 2008 πάει να γράψει στα παραπάνω αρχεία αλλά επειδή είναι File protected δεν σε αφήνει. Αυτό έχει συμβεί με την εγκατάσταση του SP3 των Windows XP Pro ελληνικά διότι η Microsoft τα έχει ενσωματώσει στον κώδικά της.
     
     
    Η λύση κατόπιν επικοινωνίας με την Microsοft είναι η ακόλουθη :
     
    Απεγκατάσταση του MSXML 6 Parser με το utility που θα βρείτε στο παρακάτω link :http://download.microsoft.com/download/e/9/d/e9d80355-7ab4-45b8-80e8-983a48d5e1bd/msicuu2.exe Κατόπιν πάμε στην Registry και στο σημείο HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\Winlogon όπου βρίσκουμε την μεταβλητή SFCDisable (REG_DWORD) και από 0 την κάνουμε 1 Κάνουμε την εγκατάσταση του SQL Server (θα μας ξαναβγάλει το μήνυμα λάθους αλλά πατάμε ok) και όλα πάνε καλά. Κάνουμε restart και ελέγχουμε ξανά την registry να έχει πάλι η μεταβλητή την τιμή 1 (εάν έχει γίνει 0 την αλλάζουμε). Εγκαθιστούμε το SP2 ή το SP3 του SQL2005 και ξανακάνουμε restart. Στο τέλος ελέγχουμε την μεταβλητή στην registry να είναι 0. Το link της Microsoft για τα παραπάνω είναι το ακόλουθο : http://support.microsoft.com/kb/222473
     
    Εάν τα Windows XP Pro με SP3 είναι αγγλικά δηλαδή ίδια γλώσσα με τον SQL Server δεν ισχύουν τα παραπάνω.
  8. antonch
    Όλοι ξέρουμε το pagefile του λειτουργικού και την χρηστικότητα του.
    Όμως ποιό είναι το ιδανικό μέγεθος του σε ένα server που έχει εγκατεστημένο SQL Server;
    Πρέπει το Pagefile να είναι 1,5 φορές μεγαλύτερο από την φυσική μνήμη του server.
    Εάν έχω ή πρόκειτε να χρησιμοποιήσω full-text search τότε πρέπει να είναι τουλάχιστον τρεις φορές μεγαλύτερο από την φυσική μνήμη του server.
    Για ακόμα καλύτερα αποτελέσματα καλό θα είναι το pagefile να είναι σε ξεχωριστό φυσικό από αυτό του λειτουργικού.
  9. antonch
    Τόσα χρόνια στον χώρο της πληροφορικής έχω μάθει να προσπαθώ να καταλάβω τι γίνεται πίσω από την σκηνή με αυτό που ασχολούμαι. Ο SQL Server είναι ένα από αυτά, και στο οποίο έχω αφιερώσει αρκετές τρίχες της κεφαλής μου. Σήμερα θα σας πάρω λίγο από τον πολύτιμο χρόνο σας για να σας μεταφέρω μια γνώση που θα σας φανεί αρκετά χρήσιμη.
    Όλοι λίγο ή πολύ έχετε γράψει ένα sql query. Άλλες φορές αυτό λειτούργησε άψογα άλλες φορές όχι. Το μυστικό για να γράψεις ένα καλό sql query είναι να έχεις κατανοήσει πως αυτό λογικά εκτελείται, ιδιαίτερα στην μηχανή που χρησιμοποιείς, στην δικιά μας περίπτωση ο SQL Server.
    Ένα sql query περιέχει κάποιες εκφράσεις μέσα του, εδώ θα ασχοληθούμε με τι βασικές, Έτσι ένα sql query είναι της μορφής αυτής. Στους αριθμούς μέσα στις παρενθέσεις φαίνεται η σειρά, βήμα, φάση εκτέλεσης.
    Κάθε βήμα δημιουργεί έναν virtual table ο οποίος είναι το input για το επόμενο βήμα. Αυτά το virtual tables δεν είναι διαθέσιμα σε κανένα πλήν του SQL Server, εκτός του τελευταίου που είναι και αυτό που παίρνουμε σαν απάντηση. Εάν στο sql query μας δεν έχουμε κάποια έκφραση απλά αυτή αγνοείτε και πάει στο επόμενο βήμα.
     
    (8) SELECT (9) DISTINCT (11)
    (1) FROM
    (3) JOIN
    (2) ON
    (4) WHERE
    (5) GROUP BY
    (6) WITH {CUBE | ROLLUP}
    (7) HAVING
    (10) ORDER BY
     
    Ας δούμε τα πράγματα λίγο αναλυτικά με ένα παράδειγμα που θα δημιουργήσουμε με το παρακάτω script
    SET NOCOUNT ON;
    USE tempdb;
    GO
    IF OBJECT_ID('dbo.Orders') IS NOT NULL
    DROP TABLE dbo.Orders;
    GO
    IF OBJECT_ID('dbo.Customers') IS NOT NULL
    DROP TABLE dbo.Customers;
    GO
    CREATE TABLE dbo.Customers
    (
    customerid CHAR(5) NOT NULL PRIMARY KEY,
    city VARCHAR(10) NOT NULL
    );

    INSERT INTO dbo.Customers(customerid, city) VALUES('ANTON', 'Athens');
    INSERT INTO dbo.Customers(customerid, city) VALUES('NASOS', 'Athens');
    INSERT INTO dbo.Customers(customerid, city) VALUES('FANIS', 'Athens');
    INSERT INTO dbo.Customers(customerid, city) VALUES('CHRIS', 'Salonica');

    CREATE TABLE dbo.Orders
    (
    orderid INT NOT NULL PRIMARY KEY,
    customerid CHAR(5) NULL REFERENCES Customers(customerid)
    );

    INSERT INTO dbo.Orders(orderid, customerid) VALUES(1, 'NASOS');
    INSERT INTO dbo.Orders(orderid, customerid) VALUES(2, 'NASOS');
    INSERT INTO dbo.Orders(orderid, customerid) VALUES(3, 'FANIS');
    INSERT INTO dbo.Orders(orderid, customerid) VALUES(4, 'FANIS');
    INSERT INTO dbo.Orders(orderid, customerid) VALUES(5, 'FANIS');
    INSERT INTO dbo.Orders(orderid, customerid) VALUES(6, 'CHRIS');
    INSERT INTO dbo.Orders(orderid, customerid) VALUES(7, NULL);
    Μετά από την εκτέλεση του θα έχουμε δύο πίνακες τους Customers, Orders οι οποίοι είναι related μεταξύ τους και τα δεδομένα τους θα είναι τα εξής
    Customers Table Data
    customerid
    city
    ANTON
    Athens
    CHRIS
    Salonica
    FANIS
    Athens
    NASOS
    Athens
     
    Orders Table Data
    Orderid
    customerid
    1
    NASOS
    2
    NASOS
    3
    FANIS
    4
    FANIS
    5
    FANIS
    6
    CHRIS
    7
    NULL
     
    Ας πάρουμε σαν σενάριο ότι θέλουμε να βούμε τους πελάτες της Αθήνας που έχουν κάτω από τρεις παραγγελίες.
    Έτσι το sql query μας θα είναι σαν αυτό.
    SELECT C.customerid, COUNT(O.orderid) AS numorders
    FROM dbo.Customers AS C
    LEFT OUTER JOIN dbo.Orders AS O
    ON C.customerid = O.customerid
    WHERE C.city = 'Athens'
    GROUP BY C.customerid
    HAVING COUNT(O.orderid) 3
    ORDER BY numorders;
    Το αποτέλεσμα της εκτέλεσης του είναι το παρακάτω
    Customerid
    numorders
    ANTON
    0
    NASOS
    2
     
    Ποιά είναι όμως η λογική του εκτέλεση; Ας δούμε λοιπόν τα βήματα της εκτέλεσης.
    Βήμα 1ο - Cross Join
    FROM dbo.Customers AS C ... JOIN dbo.Orders AS O
     
    Εδώ φτιάχνει το καρτεσιανό γινόμενο των δύο πινάκων και το βάζει στο 1ο virtual table (VT1). Το περιεχόμενο του πίνακα αυτού είναι 28 γραμμές ( 4x7).
    Customerid
    City
    Orderid
    customerid
    ANTON
    Athens
    1
    NASOS
    ANTON
    Athens
    2
    NASOS
    ANTON
    Athens
    3
    FANIS
    ANTON
    Athens
    4
    FANIS
    ANTON
    Athens
    5
    FANIS
    ANTON
    Athens
    6
    CHRIS
    ANTON
    Athens
    7
    NULL
    CHRIS
    Salonica
    1
    NASOS
    CHRIS
    Salonica
    2
    NASOS
    CHRIS
    Salonica
    3
    FANIS
    CHRIS
    Salonica
    4
    FANIS
    CHRIS
    Salonica
    5
    FANIS
    CHRIS
    Salonica
    6
    CHRIS
    CHRIS
    Salonica
    7
    NULL
    FANIS
    Athens
    1
    NASOS
    FANIS
    Athens
    2
    NASOS
    FANIS
    Athens
    3
    FANIS
    FANIS
    Athens
    4
    FANIS
    FANIS
    Athens
    5
    FANIS
    FANIS
    Athens
    6
    CHRIS
    FANIS
    Athens
    7
    NULL
    NASOS
    Athens
    1
    NASOS
    NASOS
    Athens
    2
    NASOS
    NASOS
    Athens
    3
    FANIS
    NASOS
    Athens
    4
    FANIS
    NASOS
    Athens
    5
    FANIS
    NASOS
    Athens
    6
    CHRIS
    NASOS
    Athens
    7
    NULL
     
    Βήμα 2ο - Apply Join condition ON Filter
    ON C.customerid = O.customerid
    Στο βήμα αυτό εφαρμόζεται το ON που υπάρχει στο Join και μόνο τα rows εκείνα τα οποία ικανοποιούν το βήμα πηγαίνουν στον VT2 που θα είναι το αποτέλεσμα του βήματος αυτού.
    Έτσι αν πάρω τον VT1 και εφαρμόσω στο παράδειγμα μας το ON θα έχω το εξής αποτέλεσμα
    Customerid
    City
    Orderid
    customerid
    ΟΝ Filter
    ANTON
    Athens
    1
    NASOS
    FALSE
    ANTON
    Athens
    2
    NASOS
    FALSE
    ANTON
    Athens
    3
    FANIS
    FALSE
    ANTON
    Athens
    4
    FANIS
    FALSE
    ANTON
    Athens
    5
    FANIS
    FALSE
    ANTON
    Athens
    6
    CHRIS
    FALSE
    ANTON
    Athens
    7
    NULL
    UNKNOWN
    CHRIS
    Salonica
    1
    NASOS
    FALSE
    CHRIS
    Salonica
    2
    NASOS
    FALSE
    CHRIS
    Salonica
    3
    FANIS
    FALSE
    CHRIS
    Salonica
    4
    FANIS
    FALSE
    CHRIS
    Salonica
    5
    FANIS
    FALSE
    CHRIS
    Salonica
    6
    CHRIS
    TRUE
    CHRIS
    Salonica
    7
    NULL
    UNKNOWN
    FANIS
    Athens
    1
    NASOS
    FALSE
    FANIS
    Athens
    2
    NASOS
    FALSE
    FANIS
    Athens
    3
    FANIS
    TRUE
    FANIS
    Athens
    4
    FANIS
    TRUE
    FANIS
    Athens
    5
    FANIS
    TRUE
    FANIS
    Athens
    6
    CHRIS
    FALSE
    FANIS
    Athens
    7
    NULL
    UNKNOWN
    NASOS
    Athens
    1
    NASOS
    TRUE
    NASOS
    Athens
    2
    NASOS
    TRUE
    NASOS
    Athens
    3
    FANIS
    FALSE
    NASOS
    Athens
    4
    FANIS
    FALSE
    NASOS
    Athens
    5
    FANIS
    FALSE
    NASOS
    Athens
    6
    CHRIS
    FALSE
    NASOS
    Athens
    7
    NULL
    UNKNOWN
     
    Δηλαδή ο VT2 θα είναι τελικά ο παρακάτω
    Customerid
    City
    Orderid
    customerid
    CHRIS
    Salonica
    6
    CHRIS
    FANIS
    Athens
    3
    FANIS
    FANIS
    Athens
    4
    FANIS
    FANIS
    Athens
    5
    FANIS
    NASOS
    Athens
    1
    NASOS
    NASOS
    Athens
    2
    NASOS
     
    Βήμα 3ο - Apply OUTER Join
    FROM dbo.Customers AS C LEFT OUTER JOIN dbo.Orders AS O
    Στην περίπτωση μας μόνο ένας είναι ο πελάτης από την πίνακα τον πελατών που δεν υπάρχει στον VT2 o ΑΝΤΟΝ οπότε μπαίνει και αυτό στον VT3 που είναι το αποτέλεσμα του βήματος αυτού
    Customerid
    City
    Orderid
    customerid
    CHRIS
    Salonica
    6
    CHRIS
    FANIS
    Athens
    3
    FANIS
    FANIS
    Athens
    4
    FANIS
    FANIS
    Athens
    5
    FANIS
    NASOS
    Athens
    1
    NASOS
    NASOS
    Athens
    2
    NASOS
    ΑΝΤΟΝ
    Athens
    NULL
    NULL
     
    Βήμα 4ο - Apply WHERE filter
    WHERE C.city = 'Athens'
    Το αποτέλεσμα είναι ο VT4
    Customerid
    City
    Orderid
    customerid
    FANIS
    Athens
    3
    FANIS
    FANIS
    Athens
    4
    FANIS
    FANIS
    Athens
    5
    FANIS
    NASOS
    Athens
    1
    NASOS
    NASOS
    Athens
    2
    NASOS
    ΑΝΤΟΝ
    Athens
    NULL
    NULL
     
    Βήμα 5ο - Apply Grouping
    GROUP BY C.customerid
    Το αποτέλεσμα είναι ο VT5
    Customerid
    City
    Orderid
    customerid
    FANIS
    Athens
    3
    FANIS
    FANIS
    Athens
    4
    FANIS
    FANIS
    Athens
    5
    FANIS
    NASOS
    Athens
    1
    NASOS
    NASOS
    Athens
    2
    NASOS
    ΑΝΤΟΝ
    Athens
    NULL
    NULL
     
    Βήμα 6ο - Apply Cube or Rollup
    Δεν έχουμε κάτι τέτοιο στο query μας οπότε πάει στο επόμενο βήμα.
    Βήμα 7ο - Apply HAVING Filter
    HAVING COUNT(O.orderid) 3
    Το αποτέλεσμα είναι ο VT7
    Customerid
    City
    Orderid
    customerid
    NASOS
    Athens
    1
    NASOS
    NASOS
    Athens
    2
    NASOS
    ΑΝΤΟΝ
    Athens
    NULL
    NULL
     
    Βήμα 8ο - Apply SELECT List
    SELECT C.customerid, COUNT(O.orderid) AS numorders
    Το αποτέλεσμα είναι ο VT8
    Customerid
    numorders
    NASOS
    2
    ANTON
    0
    Βήμα 9ο - Apply DISTINCT
    Δεν έχουμε κάτι τέτοιο στο query μας οπότε πάει στο επόμενο βήμα.
    Βήμα 10ο - Apply ORDER BY
    SELECT C.customerid, COUNT(O.orderid) AS numorders
    Το αποτέλεσμα είναι ο VT10
    Customerid
    numorders
    ANTON
    0
    NASOS
    2
    Βήμα 11ο - Apply TOP
    Δεν έχουμε κάτι τέτοιο στο query μας οπότε καταλήγουμε στο τελικό μας αποτέλεσμα.
    ΥΓ. Επίτηδες παρέλειψα κάποια βήματα για να μην σας κουράσω. Αν υπάρχει απαίτηση από εσάς μέσω των σχολίων σας θα προχωρήσω βαθύτερα και σε αυτά
  10. antonch
    Λοιπόν μιας και απέκτησα και εδω ένα blog είπα να κάνω σεφτέ με κάτι που λίγο ή πολύ όσοι ασχολούμαστε με SQL Server αντιμετωπίζουμε.
    Πως θα βρω τα queries που κάνουν υψηλή χρήση της CPU;
    H απάντηση στο ερώτημα αυτό είναι η παρακάτω custom stored procedure η οποία δουλεύει σε SQL Server 2005 & 2008
     
    create procedure spFindQueriesThatUseHighCPU
    as
    Set NOCOUNT ON
    SELECT TOP 100
    (a.total_worker_time/a.execution_count) as [Avg_CPU_Time], -- the time is in ms
    Convert(Varchar,Last_Execution_Time) as 'Last_execution_Time',
    Total_Physical_Reads,
    SUBSTRING(b.text,a.statement_start_offset/2,
    (case
    when a.statement_end_offset = -1 then len(convert(nvarchar(max), b.text)) * 2
    else
    a.statement_end_offset end - a.statement_start_offset)/2) as Query_Text,
    dbname=Upper(db_name(b.dbid)),
    b.objectid as 'Object_ID'
    FROM sys.dm_exec_query_stats a
    cross apply sys.dm_exec_sql_text(a.sql_handle) as b
    ORDER BY [Avg_CPU_Time] DESC
    go
  11. antonch
    Σημέρα ένας αγαπητός συνάδελφος έρχεται στο γραφείο μου και μου κάνει την εξής ερώτηση:
    «Υπάρχει κανένας τρόπος με τον οποίο μπορώ να δω το μέγεθος των πραγματικών δεδομένων που έχουν αποθηκευτεί στην βάση μου σε ένα πεδίο τύπου image;»
    Σίγουρα η πρώτη σκέψη όλων μας θα πάει στην LEN(), αλλά αυτή όμως δεν παίζει με πεδία τύπου image, text, ntext.
    Αντί για αυτή μπορούμε να χρησιμοποιήσουμε την DATALENGTH() η οποία επιστρέφει το μέγεθος σε bytes και η οποία φυσικά μπορεί να χρησιμοποιηθεί και για όλα τα άλλα data types του SQL Server.
    Ένα παράδειγμα
    Έστω ότι έχω τον πίνακα Α
    CREATE TABLE A ( ID INT PRIMARY KEY NOT NULL, PHOTO IMAGE )
    Μπορώ να διαβάζω το πραγματικό αποθηκευμένο μέγεθος στο πεδίο PHOTO με ένα απλό query
    SELECT ID, DATALENGTH(PHOTO) SizeInBytes, DATALENGTH(PHOTO)/1024 SizeInKB FROM A
    Αυτά για την ώρα, καλή σας ημέρα και καλό SQL Server programming


  12. antonch
    Αφορμή για αυτό το post είναι ο Blackman. Σε μια ωραία συζήτηση που είχαμε μου εξέφρασε την επιθυμία για αυτό επειδή μια εφαρμογή που έχει του αφήνει ανοικτά sessions.
    Σε αυτό το σημείο θα πρέπει να αναφέρω ότι κάτι τέτοιο μπορεί να συμβεί είτε διότι η εφαρμογή δεν έχει γραφτεί σωστά, είτε έπειδή ο σταθμός εργασίας που έχει ανοίξει το session σταμάτησε να λειτουργεί είτε η εφαρμογή σταμάτησε απότομα.
    Ο SQL Server βέβαια έχει τους μηχανισμούς για να τα “σκοτώνει” αυτόματα αλλά απαιτείται να πειράξεις registry (http://msdn.microsoft.com/en-us/library/aa275788(SQL.80).aspx) αν θέλεις να γίνεται σε πιο σύντομο διάστημα. Όμως όπως θα δείτε και στο link που σας έδωσα στην ουσία πειράζει το πρωτόκολο επικοινωνίας, και αυτό ίσως να μην το θέλεις αν έχεις και άλλα services.
    Εαν πάντως δεν θέλεις να κάνεις την παραπάνω αλλαγή σας παρέχω 2 τρόπους για να κάνετε kill τα idle sessions.
    ΤΡΟΠΟΣ Α.
    Αυτό ο τρόπος “σκοτώνει” όλα τα idle session σε όλες τις databases εκτός από τις system databases και το session με το οποίο κάνουμε την εκτέλεση της εργασίας.
    Για να το κάνετε αυτό πρέπει πρώτα να πάρετε τον παρακάτω κώδικα να να τον τρέξετε μέσα από ένα query στον SQL Server με επιλεγμένη βάση την master. Αυτός θα σας φτίαξει μια stored procedure σε αυτή την οποία μπορείτε να την εκτελέσετε ως εξής
    EXEC dbo.spKillAllIdleSession
    : είναι ο χρόνος σε λεπτά που το session δεν κάνει τίποτα δηλαδή αν πούμε 20 σημαίνει “σκότωσε όλα τα session που πάνω από 20 λεπτά δεν κάνουν τίποτα.
    π.χ EXEC dbo.spKillAllIdleSession 20




    CREATE PROC dbo.spKillAllIdleSessions
                @IdleTime int    -- Parameter to set your desirable idle time for session in minutes
    /*
        This stored procedure kills all idle processes in sql server 2005, 2008
        except the current process and all processes on system databases
        
        Created by Antonios Chatzipavlis Sep 27, 2009
    */
    as

        DECLARE @killCommand varchar(50)
        DECLARE IdleSessions CURSOR FOR
            SELECT 'KILL ' + Convert(VARCHAR(5), p.spid)
                FROM master.sys.sysprocesses AS p
                    WHERE  p.spid > 50
                    AND p.spid @@SPID
                    AND DateDiff(minute, p.last_batch, GetDate()) > @IdleTime
                    AND p.dbid not in (DB_ID('master'),DB_ID('model'),DB_ID('msdb'),DB_ID('tempdb'),
                                        DB_ID('ReportServer'),DB_ID('ReportServerTempDB'),DB_ID('distribution'))
                    
        OPEN IdleSessions
        FETCH IdleSessions INTO @killCommand

        WHILE 0 = @@fetch_status
        BEGIN
            EXECUTE (@killCommand) -- Actually execute the command
            FETCH IdleSessions INTO @killCommand
        END

        CLOSE IdleSessions
        DEALLOCATE IdleSessions
    GO




    ΤΡΟΠΟΣ Β.
    Αυτό ο τρόπος “σκοτώνει” όλα τα idle session σε συγκεκριμένη database εκτός από το session με το οποίο κάνουμε την εκτέλεση της εργασίας.
    Για να το κάνετε αυτό πρέπει πρώτα να πάρετε τον παρακάτω κώδικα να να τον τρέξετε μέσα από ένα query στον SQL Server με επιλεγμένη βάση την master. Αυτός θα σας φτίαξει μια stored procedure σε αυτή την οποία μπορείτε να την εκτελέσετε ως εξής
    EXEC dbo.spKillAllIdleSessionInDatabase ,
    : είναι ο χρόνος σε λεπτά που το session δεν κάνει τίποτα δηλαδή αν πούμε 20 σημαίνει “σκότωσε όλα τα session που πάνω από 20 λεπτά δεν κάνουν τίποτα.
    : είναι το όνομα της database.
    π.χ EXEC dbo.spKillAllIdleSessionInDatabase 20, ‘MyDB’



    CREATE PROC dbo.spKillAllIdleSessionsInDatabase
                @IdleTime int    -- Parameter to set your desirable idle time for session in minutes
    ,            @DBName varchar(50) -- Parameter to set database name            
    /*
        This stored procedure kills all idle processes in a specific database
        Created by Antonios Chatzipavlis Sep 27, 2009
    */
    as

        DECLARE @killCommand varchar(50)
        DECLARE IdleSessions CURSOR FOR
            SELECT 'KILL ' + Convert(VARCHAR(5), p.spid)
                FROM master.sys.sysprocesses AS p
                    WHERE  p.spid > 50
                    AND p.spid @@SPID
                    AND DateDiff(minute, p.last_batch, GetDate()) > @IdleTime
                    AND p.dbid =DB_ID(@DBName)
                    
        OPEN IdleSessions
        FETCH IdleSessions INTO @killCommand

        WHILE 0 = @@fetch_status
        BEGIN
            EXECUTE (@killCommand) -- Actually execute the command
            FETCH IdleSessions INTO @killCommand
        END

        CLOSE IdleSessions
        DEALLOCATE IdleSessions
    GO




    ΠΑΡΑΤΗΡΗΣΕΙΣ
    Τόσο κατά την δημιουργία, όσο και κατά την εκτέλεση ο χρήστης με τον οποίο έχετε κάνει login στον SQL Server θα πρέπει να είναι στον system role sysadmins. Εαν θέλετε να το φτιάξετε για SQL Server 2000 απλά αλλάξε το σημείο FROM master.sys.sysprocesses AS p σε FROM master.dbo.sysprocesses AS p  
  13. antonch
    Σήμερα δεν ξημέρωσε καλά για κάποιον συνάδελφο.

    Δυστυχώς για αυτόν είχε να αντιμέτωπίσει ένα σοβαρό θέμα μιας και η βάση του ERP του ήταν suspect. Πραγματικά είχα καιρό να ακούσω για κάτι τέτοιο και τις περισσότερες φορές αιτία είναι hard disk failures.

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

    Βέβαια η καλύτερη λύση σε αυτές τις περιπτώσεις είναι να κάνεις restore το backup σου που θα σου εξασφαλίσει ότι δεν θα έχει απώλειες δεδομένων.

    Στην παρακάτω λύση πάμε όταν δεν έχουμε backup. Κάτι το οποίο το θεωρώ αδιανόητο αλλά δυστυχώς ο συνάδελφος δεν είχε backup!

    Κανόνας Απαράβατος

    ΔΕΝ ΚΑΝΟΥΜΕ ΠΟΤΕ DETACH MIA SUSPECT DATABASE

    Από εκεί και μετά εκτελούμε μια μια τις παρακάτω εντολές

    ALTER DATABASE dbname SET EMERGENCY;
    GO
    ALTER DATABASE dbname SET SINGLE_USER;
    GO
    DBCC CHECKDB (dbname, REPAIR_ALLOW_DATA_LOSS) WITH NO_INFOMSGS, ALL_ERRORMSGS;
    GO

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

    Το μόνο που μας μένει είναι να ξαναφέρουμε την βάση σε χρήση για πολλαπλούς χρήστες
    ALTER DATABASE dbname SET MULTI_USER;
    GO
  14. antonch
    Σήμερα το πρωί σε μια συνάντηση που είχαμε όλοι οι Έλληνες MCTs ένας συνάδελφος μου έκανε μια ερώτηση.
    “Θέλω να καταγράφω τα events που γίνονται σε μια βάση στο Windows Event Log γιατί θέλω να τα βλέπω από το MOM;”
    Η απάντηση σε αυτό είναι η παρακάτω, όμως θα πρέπει να επισημάνω ότι είναι για SQL Server 2005 μιας και στον SQL Server 2008 δεν υπάρχει η ανάγκη να κάνουμε κάτι τέτοιο μιας και υπάρχει build-in δυνατότητα την οποία υπόσχομαι να παρουσιάσω σε ένα άλλο μου post.
    Η προσέγγιση θα μπορούσε να γίνει και αλλιώς πχ με Event Notifications αλλά επέλεξα την παρακάτω λύση λόγο της απλότητας της.
    Για την υλοποίηση της λύσης, η οποία είναι draft και μπορεί με την βοήθεια σας να γίνει καλύτερη, θα αξιοποιήσω δύο πράγματα.
    Το πρώτο είναι οι DDL Triggers και το δεύτερο η extented stored procedure xp_logevent.
    Έτσι σε κάθε database που θέλω τα event της να καταγράφονται στο windows event log δημιουργούμε τον παρακάτω ddl trigger.
    Θα πρέπει να τονίσω ότι καταγράφονται μόνο τα DDL statements και όχι τα DML statements.
    CREATE TRIGGER WriteToEventLog
    ON DATABASE
    FOR DDL_DATABASE_LEVEL_EVENTS
    AS
    DECLARE @ed XML
    DECLARE @logmsg char(255)

    SELECT @ed = EVENTDATA()

    -- ΕΠΕΛΕΞΑ ΝΑ ΦΕΡΝΩ ΜΟΝΟ ΤΟ T-SQL COMMAND
    -- ΑΛΛΑ ΜΠΟΡΕΙΤΕ ΝΑ ΔΕΙΞΕΤΕ ΚΑΙ ΑΛΛΑ ΣΤΟΙΧΕΙΑ
    -- ΠΟΥ ΥΠΑΡΧΟΥΝ ΣΤΟ XML ΠΟΥ ΕΠΙΣΤΡΕΦΕΙ Ο TRIGGER
    -- ΜΕΣΩ ΤΗΣ EVENTDATA FUNCTION

    SET @logmsg =
    @ed.VALUE('(/EVENT_INSTANCE/TSQLCommand/CommandText[1]','char(255)')

    EXEC xp_logevent 50001,@logmsg,'WARNING'
    go





    Περιμένω τα σχόλια σας.









  15. antonch
    Αρκετοί με ρωτούν όταν μέσα στα μαθήματα που κάνω όταν λέω SQL Server τον προφέρω "sequel server", ενώ όταν αναφέρομαι στην γλώσσα Transact SQL λέω "transact ess kyoo ell".
    Θα σας δώσω λοιπόν την εξήγηση, την οποία εχω υιοθετήσει. Την έχω διαβάσει σε αρκετά sites και βιβλία, αλλά έχω ρωτήσει και αρκετά άτομα από το SQL Server Development Team της Microsoft στο τελευταίο μου ταξίδι στο Microsoft Campus στο Redmond πέρσι.
    Υπάρχουν δύο βασικοί λόγοι. Ο ένας είναι ιστορικός και ο άλλος γλωσσολογικός.
    Ο ιστορικός λόγος είναι γιατί το 1970 η IBM ανέπτυξε μια γλώσσα την οποία ονόμασε SEQUEL σαν απόρροια ακρωνυμίου από το Structured English QUEry Language. Η γλώσσα αυτή φτιάχτηκε για να κάνει maniplulate data τα οποία ήταν αποθηκευμένα στην database System R η οποία βάση, ήταν βασισμένη πάνω στο RDBMS μοντέλο του Dr. Edgar F. Codd (εαν βρείτε το βιβλίου του διαβάστε το αξίζει ).
    Το 1986 το ANSI υιοθέτησε σαν standard την γλώσσα αυτή και το 1987 την έκανε ISO κόβοντας ταυτόχρονα το όνομα σε SQL και δηλώνοντας και τον τρόπο προφοράς της σε "ess kyoo ell".
    Ο γλωσσολογικός λόγος είναι η απλότητα που δίνεται στην προφορά για όλους τους αγγλόφωνους.
    Τώρα γιατί έχει "καθιερωθεί" ο Microsoft SQL Server να προφέρετε Microsoft Sequel Server; Για να δείξουν ότι είναι RDBMS και όχι γλώσσα δεδομένων υιοθέτησαν την αρχική ονομασία.
    Και για να προλάβω μερικούς...
    Την ονομασία αυτή δεν την έδωσε η Microsoft αλλά οι εταιρίες που αρχικά έφτιαξαν τον SQL Server, για την ιστορία ήταν οι Sybase, Ashton Tale (dBase) και Microsoft, και αυτό έγινε το 1987 που ξέρουμε ποιός από τους τρεις ήταν ο ισχυρός.
  16. antonch
    Το Madison είναι ένας highly scalable data warehouse προσαρμογέας ο οποίος προσφέρει high performance σε χαμηλό κόστος μέσω μιας Massively Parallel Processing (MPP) αρχιτεκτονικής για τον SQL Server.
    Σε σχέση με τον ανταγωνισμό το Madison προσφέρει “hardware flexibility with configurations from the major hardware vendors and low cost through industry standard hardware”, όπως χαρακτηριστικά λεει η ανακοίνωση.
    Με αυτό το project η Microsoft μεγαλώνει το μέγεθος των data warehouses από τα περίπου 50GB που είναι σήμερα πάνω από το 1 Petabyte μέσω scaling out, αυτή την στιγμή έχουν φτάσει στα 20 nodes.
    Μέχρι σήμερα στην δοκιμή αυτή συμμετέχουν 10 πελάτες της Microsoft από 7 διαφορετικές επιχειρηματικές δραστηριότητες. Τα πρώτα αποτελέσματα είναι εντυπωσιακά όπως
    Data loading rate 1 TB / hour Processing query executions > 1,5 ΤΒ / min Για να συμμετέχει κάποιος σε αυτό το CTP θα πρέπει να έχει κάποιες προϋποθέσεις που έχουν ορισθεί, και ο αριθμός των συμμετεχόντων θα είναι περιορισμένος. Για όσους επιθυμούν να συμμετέχουν σε αυτό θα πρέπει να στείλουν mail στο [email protected]
    Για περισσότερες πληροφορίες για το Madison Project θα βρείτε εδώ
    · Madison Website: http://www.microsoft.com/sqlserver/2008/en/us/madison.aspx
    · SQL Server 2008 Website: http://www.microsoft.com/sqlserver/2008/en/us/default.aspx
×
×
  • Create New...