DBCC OPTIMIZER_WHATIF


Εισαγωγή

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

Η ανάγκη

Ας έρθουμε όμως στο ζουμί. Σαν DBA / DB Dev καθημερινά γράφεις queries. Αρκετές φορές κάποια πάνε σφαίρα κάποια πάνε αργά και γενικά είσαι μέσα σε μια ατέρμονη διαδικασία τα αργά να τα κάνεις να πάνε γρήγορα και τα γρήγορα γρηγορότερα.

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

Αρκετές φορές εκτελώντας ένα query αναρωτιέσαι πως αυτό θα συμπεριφέρονταν αν είχες περισσότερους ή λιγότερους πόρους είτε σε CPU είτε σε Memory.

Αυτό αν και μπορείς να το εκτιμήσεις έχοντας σαν όπλο την εμπειρία σου, εντούτοις θέλεις να μπορείς και να το μετρήσεις. Αλλά πώς θα το κάνεις αυτό καθώς έχεις δεδομένο το hardware στο οποίο εκτελείται το συγκεκριμένο query;

Με απλά λόγια θέλεις να κάνεις ένα what if σενάριο χωρίς όμως να μπεις στην βάσανο να προμηθευτείς hardware!!!

Μέχρι τώρα μπορούσα να κάνω κάτι τέτοιο όσον αφορά τον αριθμό των CPU cores που ο SQL Server θα χρησιμοποιεί με ένα τρυκ. Εκμεταλλευόμενος το γεγονός ότι γνωρίζω το πώς λειτουργεί ο SQL Server μέσω του SQLOS και των schedulers που δημιουργούνται, αλλά και της παραμέτρου –P που υπάρχει στο service του SQL Server με την οποία μπορείς να ορίσεις τον αριθμό των schedulers που θα φτιάχνει ο SQL Server όταν ξεκινάει.

Απλά για την ενημέρωση σας αναφέρω ότι ο SQL Server για κάθε cpu core που θα δει φτιάχνει ένα scheduler και αυτοί χρησιμοποιούνται κατά την εκτέλεση των εργασιών που κάνουμε πάνω σε αυτόν. Σας προτείνω να διαβάσετε τα post μου που αναφέρονται στο SQLOS και υπάρχουν σε αυτό το χώρο.

Μπορώ δηλαδή με το να πειράζω την συγκεκριμένη παράμετρο ακόμα και εάν έχω ένα σύστημα που έχει πχ δύο cpu cores να εξομοιώσω ότι έχω 4/8/16/… cores και να δοκιμάζω τα queries μου συγκρίνοντας σε κάθε περίπτωση τα execution plans. Αυτό είναι κάτι το οποίο γνώριζα και όπου μπορούσα το εφάρμοζα και λέω όπου μπορούσα διότι για να γίνει το πείραμα με τις διάφορες εναλλαγές έπρεπε κάθε φορά να κάνω restart το service του SQL Server και όπως είναι αυτονόητο αυτό δεν ήταν εύκολο να γίνει. Για το λόγο αυτό συνήθιζα να κάνω τέτοιες δοκιμές σε off hours ή σε δικά μου labs.

Η χρήση

Σήμερα ψάχνοντας για διάφορα πράγματα όμως ανακάλυψα την DBCC OPTIMIZER_WHATIF μια undocumented dbcc που όπως θα σας δείξω μου επιτρέπει να κάνω τέτοιου είδους πειράματα και συγκρίσεις χωρίς χρειάζεται να κάνω restart το service.

Ψάχνοντας στο Bing για αυτή καθώς όπως σας είπα δεν είναι documented δεν βρήκα πολλά πράγματα για αυτή αλλά τουλάχιστον βρήκα το πώς συντάσσεται και το τι παραμέτρους παίρνει και αυτό έγινε  μέσα από ένα άρθρο του Itzik Ben-Gan που σε κάποιο σημείο την αναφέρει.

Η συγκεκριμένη παίρνει δύο παραμέτρους. Στην πρώτη πάντα περνάμε την τιμή 1 και στην δεύτερη περνάμε τον αριθμό των cpu cores.

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

Για το παράδειγμα μου θα χρησιμοποιήσω ένα virtual machine σε hyper-v το οποίο έχει ένα cpu core και 2GB μνήμη, φτωχό μεν αλλά μια χαρά για την περίπτωση μας.

Για το υλοποίηση του παραδείγματος θα χρησιμοποιήσω το παρακάτω script το οποίο όμως πριν το τρέξετε θα πρέπει να ορίζεται στο query windows να τρέξει σε SQLCMD Mode.

SET NOCOUNT ON;

USE tempdb;

IF OBJECT_ID('dbo.T') IS NOT NULL DROP TABLE dbo.T1;

CREATE TABLE dbo.T
(
  f1 INT NOT NULL,
  f2 INT NOT NULL,
  data char(200) NOT NULL CONSTRAINT DFT_data DEFAULT('ABCDEFGHIJKLMONPQRSTUVWXYZ')
);
GO

INSERT INTO T (f1,f2) VALUES (1,1);
GO 1000000

DECLARE @i1 int = 0 , @i2 int = 0;
UPDATE T set 
            @i1=f1=@i1+1,
            @i2=f2=@i2+2;
GO

ALTER TABLE T 
ADD CONSTRAINT PK_T PRIMARY KEY (f1);
GO

Αφού ολοκληρωθεί η εκτέλεση θα έχουμε στα χέρια μας ένα πίνακα (Τ) με 1.000.000 εγγραφές. Σε αυτόν ζητήσουμε να δούμε των παρακάτω queries τα execution plans με διαφορετικές ρυθμίσεις που αφορούν τον αριθμό των cpu cores.

SELECT f1, f2, data FROM dbo.T WHERE f2 <=  50000 OPTION (RECOMPILE);

SELECT f1, f2, data FROM dbo.T WHERE f2 <= 100000 OPTION (RECOMPILE);

SELECT f1, f2, data FROM dbo.T WHERE f2 <= 500000 OPTION (RECOMPILE);

Χωρίς να έχω κάνει κάποια ρύθμιση τα execution plans τα οποία έχω είναι τα παρακάτω, απλά να θυμίσω ότι είμαι virtual machine με ένα cpu core.
Το αποτέλεσμα μου είναι το παρακάτω:
 image
Αναρωτιέμαι τώρα πως αυτά θα εκτελούνταν αν είχα δύο (2) cpu cores και για αυτό πλέον κάνοντας χρήση της DBCC όπως παρακάτω :

DBCC OPTIMIZER_WHATIF (1,2);
GO

Το αποτέλεσμα μου είναι
 

image

Είναι ομολογουμένως ενδιαφέρον δεν βρίσκετε;
Αν είχα τέσσερα (4) ή οκτώ (8) cpu cores πως θα ήταν τα πράγματα;
Αν επέλεγα 8 cores το αποτέλεσμα μου θα ήταν το παρακάτω
 image

 

Παρατηρησεις – Επισημάνσεις

  • Εάν τώρα θα ήθελα να γυρίσω στην αρχική μου κατάσταση το μόνο που έχω να κάνω είναι να εκτελέσω την DBCC ξανά απλά βάζω μηδέν στην δεύτερη παράμετρο στην οποία ορίζω τον αριθμό των cores  (DBCC OPTIMIZER_WHATIF(1,0)).
  • Να επισημάνω ότι η DBCC αυτή δεν επηρεάζει την γενικότερη συμπεριφορά του SQL Server αλλά το συγκεκριμένο session στο οποίο γίνεται η εκτέλεση της.
  • Τέλος θα πρέπει να τονίσω ιδιαίτερα ότι αυτή θα πρέπει να χρησιμοποιηθεί με ανάληψη του ρίσκου από εσάς και φυσικά δεν ενδείκνυται να χρησιμοποιείται για άλλους σκοπούς πλην της έρευνας.
     

 

/*antonch*/

3 thoughts on “DBCC OPTIMIZER_WHATIF

  1. ΟΚ. Αλλά γενικότερα σε ένα core i7 πχ που έχει 4 πυρήνες και 2 thread ανα πυρήνα συνολικά 8 λογικούς πυρήνες. Δεν εκτελώ την εντολή που αναφέρεις. Ο SQL Server θα το εκτελέσει το ερώτημα σου παράλληλα και στα 8 hardware threads που έχω ? H θα πρέπει να κάνω κάτι ώστε να τα εκτελεί παράλληλα αν δει διαθέσιμους πυρήνες ??

  2. Δεν χρειάζεται να κανείς τίποτα. Το αν θα χρησιμοποιούν πάνω απο ένα core είναι θέμα αν το κόστος στο συγκεκριμένο query ξεπερνάει αυτο που έχει ορισθεί στο cost threshold for parallelism Option, δεν το κάνει έτσι και αλλιώς καθώς έχει κόστος αν το έκανε πάντα διότι σε αυτές τις περιπτώσεις έχω ακόμα ένα thread που εμπλέκεται και ο ρόλος του είναι συντονιστικος για τα άλλα που παράλληλα τρέχουν. Έχω μιλήσει για αυτο το θέμα σε παλαιότερο post.

    Αν τώρα θέλεις να δοκίμασεις το παράδειγμα μου σε αυτο το post και δεν έχει πειράξει το cost threshold for parallelism και εφόσον ο SQL server βλέπει όλα τα core δλδ δεν έχεις πειράξει κάτι στις ρυθμίσεις CPU που βλέπει ο SQL τότε θα πρέπει να δεις παραλληλια.

    Απλα να τονίσω ότι η παραλληλια στον SQL server δεν είναι αυτοσκοπός και ούτε την εφαρμόζουμε πάντα πχ δεν θελουμε καθόλου να εμφανίζεται σε insert, update, deletes πλην ελαχίστων και σπάνιων περιπτώσεων.

    Θα πρέπει ακόμα να τονίσω ότι για αυτο αλλα και για αλλα θέματα ο SQL server έχει το SQLOS, βρες τα άρθρα μου για αυτο και θα καταλάβεις γιατι στο λέω

  3. Δεν μας έφταναν όλα τα υπόλοιπα, μπαίνουμε και σε αχαρτογράφητα ύδατα πλέον 🙂 ….πολύ καλό post Αντώνη, μου έλυσες μια απορία που πάντα είχα και πείραζα τα VM settings για να βγάλω άκρη…Thanks!

Comments are closed.