Η ασπιρίνη δεν είναι η συνιστώμενη θεραπεία για τραύμα από πυροβολισμό
στο κεφάλι. Ούτε η χρήση του query timeout για την αντιμετώπιση ενός query που
παίρνει ώρες ή μέρες.
Υποψιάζομαι ότι το query που περιγράφεις δημιουργεί κάποιο report. Αν το
query όπως λες παίρνει μέρες θα πρέπει να ξαναγραφτεί επειγόντως. Όλα τα άλλα
μέτρα είναι απλά "ασπιρίνες" οι οποίες μπορεί να ελαφρύνουν στιγμιαία το
πρόβλημα. Το πρόβλημα θα επιστρέψει όμως, πολύ συντομότερα απ' ότι νομίζεις και
σε πολύ χειρότερη μορφή. Έχω αντιμετωπίσει κι εγώ queries τα οποία ήθελαν 4
μέρες να τελειώσουν και οι προηγούμενοι προγραμματιστές είχαν προσπαθήσει να τα
αντιμετωπίσουν με "ασπιρίνες". Το αποτέλεσμα ήταν ότι στο τέλος κανείς δεν ήξερε
όχι πως συμπεριφερόταν το query, αλλά ούτε καν αν τα αποτελέσματα του ήταν
αξιόπιστα (δεν ήταν). Και το query αυτό επέστρεφε χρηματικά ποσά αξίας πολλών
χιλιάδων ευρώ. Τα οποία στέλνονταν ως statement στους πελάτες χρηματιστιριακής.
Και ήταν σχεδόν πάντα λάθος.
Πρόβλημα. Ασπιρίνη. Όοοοοοοχιιιιιι.
Μετά υπήρχε και το άλλο πρόβλημα. Τελικά το query, λόγω ενός κακώς (ή μάλλον
τυχαία) σχεδιασμένου loop ανά πελάτη, ανά μήνα, ανά μετοχή, έπρεπε να τρέξει
μέχρι τέλους για να φέρει σωστά αποτελέσματα. Το αποτέλεσμα ήταν ότι όταν το
query σταμάταγε είτε λόγω timeout είτε επειδή ο χρήστης πάταγε το Cancel, τα
αποτελέσματα που επέστρεφε ήταν λάθος, όχι όμως με τον ίδιο τρόπο. Για άλλους
πελάτες μπορεί να ήταν σωστά, για άλλους λάθος.
Long Query. Timeout. Noooooooooooo.
Από εκεί και πέρα, αντί να καλείς ένα μεγάλο query μέσω του server σου και να
βασίζεσαι στα timeouts υπάρχουν άλλοι, πολύ καλύτεροι τρόποι να το κάνεις και να
ελέγξεις τη συμπεριφορά του. Μπορείς καταρχήν να συνδεθείς απευθείας από τον
κώδικα σου με το remote server και να εκτελέσεις το περίεργο query ασύγχρονα και
να γράψεις τα αποτελέσματα σε temporary πίνακες στη δική σου βάση. Ακόμη
καλύτερη λύση είναι να περιορίσεις την ανάγκη για τέτοια πολύ μεγάλα queries. Αν
μπορείς, καλό είναι να αποθηκεύεις παλαιότερα αποτελέσματα σε ένα ειδικό πίνακα
για να μην χρειάζεται να τα ξαναϋπολογίσεις. Μπορείς να αντιγράψεις κάποια
δεδομένα από τον άλλο server στο δικό σου και έτσι να περιορίσεις την ανάγκη να
μιλάς με τον άλλο server. Μπορείς να φτιάξεις ένα κύβο στα Analysis services που
θα σου δώσει τα ίδια αποτελέσματα σε χρόνο δευτερολέπτων όμως αντί για μέρες ή
ώρες.
Από την άλλη, αν το query δεν έχει να κάνει με reporting αλλά π.χ. με update
δεδομένων, πάλι θα πρέπει να βελτιώσεις το query αλλά αυτή τη φορά τα επόμενα
βήματα είναι διαφορετικά. Η μία λύση είναι πάντα να καλέσεις το query ασύγχρονα
από τον κώδικα σου. Μία καλύτερη λύση είναι να χρησιμοποιήσεις το Service Broker
του SQL Server για να εκτελέσει αυτός το query για σένα ασύγχρονα στον άλλο
server. Έτσι δεν χρειάζεται να γράψεις επιπλέον κώδικα για την ασύγχρονη
εκτέλεση και την αντιμετώπιση σφαλμάτων.
Τελικά μάζεψα εκείνο το query που ήθελε 4 ημέρες και το έκανα να τρέχει σε 2
ώρες. Αν είχα χρησιμοποιήσει Analysis Services θα το είχα κάνει να τρέχει σε 15
λεπτά, αλλά η εταιρεία ήθελε να τρέχει λέει η χρηματιστηριακή εφαρμογή και σε
... Windows XP με SQL Server 2000.
Μεγάλα Queries. Ασπιρίνες. Όχι άλλο κάρβουνο!
Παναγιώτης Καναβός, Freelancer
Twitter: http://www.twitter.com/pkanavos