Η δύναμη της συνήθειας είναι το μεγαλύτερο ναρκωτικό του μυαλού και δεν το αφήνει να σκεφτεί αποδοτικά. Αλήθεια πόσες φορές κάνουμε μηχανικά κάποια πράγματα επειδή τα έχουμε συνηθίσει στα τόσα χρόνια που κάνουμε αυτή την δουλειά ;
Καθημερινά ασχολούμαι με πάνω από 3500 databases και μου είναι αδύνατον να θυμάμαι όλες τις λεπτομέρειες που η κάθε μία έχει. Μεγάλος αριθμός από αυτές περιέχουν μεγάλο αριθμό από tables και rows. Συχνά κυρίως για λόγους συντήρησης χρειάζεται να ξέρω τον αριθμό των rows που όλοι ή κάποιο table έχει ώστε το script μου να γνωρίζει αυτόν.
Η δύναμη της συνήθειας για να μάθω κάτι τέτοιο είναι απλά να γράφω ένα SELECT COUNT(*) FROM <TABLE_NAME>.
Έχω γράψει στο παρελθόν άρθρο (
How a SELECT COUNT(*) query executed) για το πώς εκτελείται η COUNT(*) και δεν έχω να προσθέσω κάτι σε αυτό καθώς κάνει σωστά αυτό που πρέπει να κάνει.
Παρόλα αυτά όμως υπάρχουν περιπτώσεις που έχω πίνακες που έχουν μεγάλο αριθμό rows (> 50.000.000) και με μεγάλο record length που ακόμα και έτσι το να πάρω αποτέλεσμα από την COUNT(*) χρειάζεται πάνω από 5 sec και αυτό με κάνει να περιμένω και δεν έχω πάντα την πολυτέλεια για αυτό.
Μια τέτοια περίπτωση είχα την εβδομάδα που μας πέρασε και πάνω στην πίεση το μυαλό γύρισε mode και δεν σκέφτηκε την πεπατημένη αλλά σκέφτηκε πραγματικά και πρακτικά την αρχιτεκτονική του SQL Server.
Έτσι αντί να κάνω ένα για παράδειγμα ένα SELECT COUNT(*) FROM Customers θυμήθηκα ότι το πλήθος των εγγραφών υπάρχει σαν πεδίο στο sys.partitions DMV και έτσι με το παρακάτω query πήρα την πληροφορία που ήθελα δηλαδή των αριθμό των εγγραφών ΑΜΕΣΑ!.
SELECT object_name(object_id) as objectname,SUM(rows) as rowscount
FROM sys.partitions
WHERE index_id IN(0,1)
AND object_id=object_id('dbo.Customers')
GROUP BY object_name(object_id)
objectname rowscount
------------ -----------
Customers 91
Get rows from all database tables
Από εκεί και μετά λέω γιατί δεν φτιάχνω και ένα query που να μου γυρνάει άμεσα για κάθε πίνακα τα πλήθος των rows και το αποτέλεσμα είναι το παρακάτω
select schema_name(o.schema_id) as [schema_name]
, o.name as [table_name]
, sum(p.rows) as [rows_count]
from sys.partitions as p
inner join sys.objects as o on p.object_id=o.object_id
where o.type='U'
and
p.index_id IN(0,1)
group by schema_name(o.schema_id)
, o.name
order by [schema_name],[table_name];
schema_name table_name rows_count
------------ -------------------------- -------------
dbo Categories 8
dbo CustomerCustomerDemo 0
dbo CustomerDemographics 0
dbo Customers 91
dbo Employees 9
dbo EmployeeTerritories 49
dbo Order Details 2155
dbo Orders 830
dbo Products 77
dbo Region 4
dbo Shippers 3
dbo Suppliers 29
dbo Territories 53
Σημείωση Θα πρέπει όμως να τονίσω ότι αν θέλουμε να πάρουμε από τις εφαρμογές μας το πλήθος των rows θα πρέπει να χρησιμοποιηθεί η παραδοσιακή μέθοδος καθώς επιστρέφει πάντα σωστά αποτελέσματα καθώς η σύμφωνα με τα BOL η rows column γυρνάει approximate value κυρίως γιατί μπορεί να τρέχουν uncommitted batches.
Από την άλλη όμως δεν έχω share locks και δεν αναγκάζομαι να χρησιμοποιήσω nolock query hint.
/*antonch*/