Mittwoch , 17 Juli 2019

Anzahl der Tabellenzeilen schnell und einfach abfragen

Der klassische Ansatz

Die Fragestellung "Wie viele Zeilen hat diese Tabelle" taucht wohl bei jedem Entwickler immer mal wieder auf.
Die Standardantwort lautet dann:

SELECT COUNT(*)
FROM [dbo].[Tabelle]

Allerdings können hierbei zwei Probleme auftreten:

  1. Der SQL Server muss zum Bearbeiten dieser Abfrage einen Table-Scan durchführen.
    Das kann bei Tabellen mit mehreren Millionen Datensätzen eine Weile dauern.
  2. Man kann mit dieser Abfrage nur jeweils eine Tabelle gleichzeitig abfragen.
    Was macht man aber, wenn man die Zeilenanzahl aller Tabellen einer Datenbank bestimmen möchte?

Um das erste Problem zu lösen, kann man die Gespeicherte Prozedur sp_spaceused verwenden.
Ohne Parameter ausgeführt, zeigt diese den Speicherverbrauch der aktuellen Datenbank an.
Mit einem Tabellennamen als Parameter, wird der Speicherverbrauch der Tabelle inkl. Zeilenanzahl zurückgegeben.

Um das zweite Problem zu lösen, muss man mittels Curserprogrammierung jede Tabelle einzeln abfragen oder die undokumentierte Gespeicherte Prozedur sp_MSforeachtable verwenden.

Alternativ kann man mit folgenden Abfragen die beiden Probleme lösen:

 

Abfrage mit Hilfe der sysindexes

Wenn der SQL 2000 verwendet wird, muss die Abfrage wie folgt aussehen:

-- Zeigt alle Benutzertabellen mit zugehöriger Zeilenanzahl
-- i.indid < 2 filtert nach "clustered index" (1) und "hash table" (0).
-- Entfernen Sie den "OBJECTPROPERTY(o.id, 'IsMSShipped') = 0" filter,
-- um Systemtabellen anzuzeigen
SELECT o.name, i.rowcnt
FROM sysindexes AS i
INNER JOIN sysobjects AS o
ON  i.id = o.id
WHERE i.indid < 2
AND OBJECTPROPERTY(o.id, 'IsMSShipped') = 0
ORDER BY o.name

 

Abfrage mit Hilfe der DMVs

Beim SQL 2005 / 2008 kann die Abfrage, mit Hilfe der DMVs, wie folgt aussehen:

-- Zeigt alle Benutzertabellen mit zugehöriger Zeilenanzahl
-- i.index_id < 2 filtert nach "clustered index" (1) und "hash table" (0).
-- Entfernen Sie den is_ms_shipped = 0 filter, um Systemtabellen anzuzeigen
SELECT o.name, ddps.row_count
FROM sys.indexes AS i
INNER JOIN sys.objects AS o
ON i.OBJECT_ID = o.OBJECT_ID
INNER JOIN sys.dm_db_partition_stats AS ddps
ON i.OBJECT_ID = ddps.OBJECT_ID
AND i.index_id = ddps.index_id
WHERE i.index_id < 2
AND o.is_ms_shipped = 0
ORDER BY o.name

4 Kommentare

  1. Danke Sascha, genau sowas suchte ich

  2. Moin und danke für den Tipp mit sysindexes.
    Aber: Wie verfahre ich, wenn ich es nicht mit einer Tabelle, sondern mit einem View zu tun habe? Komm ich hier irgendwie um einen Table-Scan herum?
    Grüße!

    • Hallo Hendrik!

      Bei Views wirst Du wahrscheinlich nicht um eine Art Table-Scan drum rum kommen (Je nachdem was Du in den Views machst).
      Ggf. wären Indexed Views eine Option.

      Ich schau mir das aber mal im Detail an und meld mich dann nochmal bei Dir.

      Viele Grüße,
      Sascha

  3. Vielen Dank!