2009-09-18 7 views

Odpowiedz

230

Jeśli używasz SQL Server 2005 iw górę, można również użyć tego:

SELECT 
    t.NAME AS TableName, 
    i.name as indexName, 
    p.[Rows], 
    sum(a.total_pages) as TotalPages, 
    sum(a.used_pages) as UsedPages, 
    sum(a.data_pages) as DataPages, 
    (sum(a.total_pages) * 8)/1024 as TotalSpaceMB, 
    (sum(a.used_pages) * 8)/1024 as UsedSpaceMB, 
    (sum(a.data_pages) * 8)/1024 as DataSpaceMB 
FROM 
    sys.tables t 
INNER JOIN  
    sys.indexes i ON t.OBJECT_ID = i.object_id 
INNER JOIN 
    sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id 
INNER JOIN 
    sys.allocation_units a ON p.partition_id = a.container_id 
WHERE 
    t.NAME NOT LIKE 'dt%' AND 
    i.OBJECT_ID > 255 AND 
    i.index_id <= 1 
GROUP BY 
    t.NAME, i.object_id, i.index_id, i.name, p.[Rows] 
ORDER BY 
    object_name(i.object_id) 

W moim opinia jest łatwiejsza w obsłudze niż wyjście sp_msforeachtable.

+0

dzięki marc_s, które powinny być łatwiejsze do zarządzania – kristof

+1

Każdy pomysł, dlaczego filtruje tabele o nazwie zaczynającej się od "dt"? Widziałem ten skrypt w całej sieci, ale żadnych wyjaśnień na temat tych kryteriów. Czy wszyscy jesteśmy trolled? – Skaue

+6

@Skaue: jeśli zainstalujesz funkcję "Diagram bazy danych" w swojej bazie danych, będziesz miał kilka tabel, takich jak 'dtProperties' i tak dalej; ponieważ są to tabele "systemowe", nie chcę ich zgłaszać. –

1

Pierwszą rzeczą, która przyszła mi do głowy było wykorzystanie sp_msForEachTable

exec sp_msforeachtable 'select count(*) from ?' 

że nie wymienia nazwy tabel choć , więc można go rozszerzyć na

exec sp_msforeachtable 'select parsename(''?'', 1), count(*) from ?' 

Problem polega na tym, że jeśli d atabase ma ponad 100 tabel otrzymasz następujący komunikat o błędzie:

Zapytanie przekroczyła maksymalną liczbę zestawów wyników, które mogą być wyświetlane w siatki wyników. Tylko pierwszych 100 zestawów wyników to wyświetlane w siatce.

Więc skończyło się za pomocą zmiennej tabela do przechowywania wyników

declare @stats table (n sysname, c int) 
insert into @stats 
    exec sp_msforeachtable 'select parsename(''?'', 1), count(*) from ?' 
select 
    * 
from @stats 
order by c desc 
-1

Jeśli używasz mysql> 4.x można użyć to:

select TABLE_NAME, TABLE_ROWS from information_schema.TABLES where TABLE_SCHEMA="test"; 

Należy pamiętać, że dla niektórych silników składowania, TABLE_ROWS jest przybliżeniem.

+6

Wspomniał o "sql-server" w swoim poście (jako tag), który jest Microsoft SQL Server –

6

As seen here, to zwróci prawidłowe liczby, w przypadku których metody korzystające z tabel danych meta będą zwracać jedynie szacunki.

CREATE PROCEDURE ListTableRowCounts 
    AS 
    BEGIN 
     SET NOCOUNT ON 

     CREATE TABLE #TableCounts 
     ( 
      TableName VARCHAR(500), 
      CountOf INT 
     ) 

     INSERT #TableCounts 
      EXEC sp_msForEachTable 
       'SELECT PARSENAME(''?'', 1), 
       COUNT(*) FROM ? WITH (NOLOCK)' 

     SELECT TableName , CountOf 
      FROM #TableCounts 
      ORDER BY TableName 

     DROP TABLE #TableCounts 
    END 
    GO 
+0

To brzmi jak kompromis polegający na użyciu nieudokumentowanego stora proc sp_msForEachTable vs używanie tabel systemowych z czasami nie najbardziej aktualnymi informacjami. +1 i dzięki za link – kristof

73

fragment znalazłem w http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=21021 że pomógł mi:

select t.name TableName, i.rows Records 
from sysobjects t, sysindexes i 
where t.xtype = 'U' and i.id = t.id and i.indid in (0,1) 
order by TableName; 
+7

Znacznie prostsze rozwiązanie i działa świetnie! –

+0

garść skryptu –

+1

Podoba mi się to rozwiązanie, chociaż użyłbym składni 'JOIN' z sysobjects t sprzężenia wewnętrznego sysindexes i na i.id = t.id i i.indid w (0,1) gdzie t .xtype = 'U'' – Shnugo

11

Aby uzyskać te informacje w SQL Management Studio, kliknij prawym przyciskiem myszy na bazie danych, a następnie wybierz Raporty -> Raporty standardowe -> Użycie dysku według tabeli.

+0

Niedoceniane podejście, to szybko generuje sortowalny raport z # wierszami i rozmiarem danych. – tbone

-1
select T.object_id, T.name, I.indid, I.rows 
    from Sys.tables T 
    left join Sys.sysindexes I 
    on (I.id = T.object_id and (indid =1 or indid =0)) 
where T.type='U' 

Tutaj indid=1 oznacza indeksu klastrowego i indid=0 jest kupa

+4

Witam i witamy w Stack Overflow. Ta odpowiedź jest identyczna z tą, która ma już [rok] (http://stackoverflow.com/a/14163881/458741) ... nie trzeba było jej ponownie publikować. – Ben

7
SELECT 
    T.NAME AS 'TABLE NAME', 
    P.[ROWS] AS 'NO OF ROWS' 
FROM SYS.TABLES T 
INNER JOIN SYS.PARTITIONS P ON T.OBJECT_ID=P.OBJECT_ID; 
+2

Ta kwerenda zwróci wynik wierszy dla każdego indeksu na każdej tabeli. Dodaj WHERE P.INDEX_ID IN (0,1) , aby ograniczyć zestaw wyników zwracanych do kupek lub indeksów klastrowych tylko w razie potrzeby. –

2
sp_MSForEachTable 'DECLARE @t AS VARCHAR(MAX); 
SELECT @t = CAST(COUNT(1) as VARCHAR(MAX)) 
+ CHAR(9) + CHAR(9) + ''?'' FROM ? ; PRINT @t' 

wyjściowa:

studio zarządzanie

enter image description here

1

Cóż szczęście SQL Server daje wskazówkę na jak to zrobić. Czyńcie to,

  1. rozpocząć śledzenie SQL Server i otwórz aktywność robisz (filtr przez logowania ID, jeśli nie jesteś sam i ustawić nazwę aplikacji Microsoft SQL Server Management Studio), pauza śledzić i odrzucić wszelkie wyniki, które zapisałeś do tej pory;
  2. Następnie kliknij prawym przyciskiem myszy tabelę i wybierz właściwość z wyskakującego menu;
  3. ponownie rozpocznij śledzenie;
  4. Teraz w SQL Server Management studio wybierz element właściwości magazynu po lewej;

Zatrzymaj śledzenie i zobacz, co TSQL jest generowane przez Microsoft.

W prawdopodobnie ostatniego zapytania widać oświadczenie zaczynając exec sp_executesql N'SELECT

podczas kopiowania wykonywany kod do visual studio można zauważyć, że ten kod generuje wszystkie dane inżynierowie Microsoft używane do wypełnienia okna właściwości .

podczas dokonywania umiarkowanych modyfikacje tego zapytania będzie można dostać się do mniej więcej tak:

SELECT 
SCHEMA_NAME(tbl.schema_id)+'.'+tbl.name as [table], --> something I added 
p.partition_number AS [PartitionNumber], 
prv.value AS [RightBoundaryValue], 
fg.name AS [FileGroupName], 
CAST(pf.boundary_value_on_right AS int) AS [RangeType], 
CAST(p.rows AS float) AS [RowCount], 
p.data_compression AS [DataCompression] 
FROM sys.tables AS tbl 
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and idx.index_id < 2 
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) AND p.index_id=idx.index_id 
LEFT OUTER JOIN sys.destination_data_spaces AS dds ON dds.partition_scheme_id = idx.data_space_id and dds.destination_id = p.partition_number 
LEFT OUTER JOIN sys.partition_schemes AS ps ON ps.data_space_id = idx.data_space_id 
LEFT OUTER JOIN sys.partition_range_values AS prv ON prv.boundary_id = p.partition_number and prv.function_id = ps.function_id 
LEFT OUTER JOIN sys.filegroups AS fg ON fg.data_space_id = dds.data_space_id or fg.data_space_id = idx.data_space_id 
LEFT OUTER JOIN sys.partition_functions AS pf ON pf.function_id = prv.function_id 

Teraz zapytanie nie jest idealny i można go zaktualizować do spełnienia inne pytania można mieć, chodzi o to, możesz wykorzystać wiedzę z Microsoft Microsoftu, aby uzyskać większość pytań, które masz, wykonując dane, które Cię interesują, i śledzić TSQL wygenerowany za pomocą profilera.

Myślę, że inżynierowie MS wiedzą, jak działa serwer SQL, i wygeneruje TSQL, który działa na wszystkich elementach, z którymi można pracować, używając wersji na SSMS, z której korzystasz, więc jest całkiem niezły w wielu wydaniach. prerwium, obecne i przyszłe.

Pamiętaj, nie kopiuj, spróbuj zrozumieć, jak również możesz znaleźć niewłaściwe rozwiązanie.

Walter

1

Przyjęte rozwiązanie nie działa dla mnie na Azure SQL, oto one że nie jest to super szybki i zrobił dokładnie to, co chciałem:

select t.name, s.row_count 
from sys.tables t 
join sys.dm_db_partition_stats s 
    ON t.object_id = s.object_id 
    and t.type_desc = 'USER_TABLE' 
    and t.name not like '%dss%' 
    and s.index_id = 1 
order by s.row_count desc 
0

myślę, że najkrótsza, najszybsza i najprostsza droga będzie:

SELECT 
    object_name(object_id) AS [Table], 
    SUM(row_count) AS [Count] 
FROM 
    sys.dm_db_partition_stats 
WHERE 
    --object_schema_name(object_id) = 'dbo' AND 
    index_id < 2 
GROUP BY 
    object_id 
0

można spróbować to:

SELECT OBJECT_SCHEMA_NAME(ps.object_Id) AS [schemaname], 
     OBJECT_NAME(ps.object_id) AS [tablename], 
     row_count AS [rows] 
FROM sys.dm_db_partition_stats ps 
WHERE OBJECT_SCHEMA_NAME(ps.object_Id) <> 'sys' AND ps.index_id < 2 
ORDER BY 
     OBJECT_SCHEMA_NAME(ps.object_Id), 
     OBJECT_NAME(ps.object_id) 
0

zbliża ten wykorzystuje ciąg konkatenacji produkować oświadczenie ze wszystkich tabel i ich liczby dynamicznie, jak na przykład (y) podane w oryginalnym pytanie:

  SELECT COUNT(*) AS Count,'[dbo].[tbl1]' AS TableName FROM [dbo].[tbl1] 
UNION ALL SELECT COUNT(*) AS Count,'[dbo].[tbl2]' AS TableName FROM [dbo].[tbl2] 
UNION ALL SELECT... 

Wreszcie ten jest wykonywany z EXEC:

DECLARE @cmd VARCHAR(MAX)=STUFF(
        (
         SELECT 'UNION ALL SELECT COUNT(*) AS Count,''' 
           + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME) 
           + ''' AS TableName FROM ' + QUOTENAME(t.TABLE_SCHEMA) + '.' + QUOTENAME(t.TABLE_NAME) 
         FROM INFORMATION_SCHEMA.TABLES AS t 
         WHERE TABLE_TYPE='BASE TABLE' 
         FOR XML PATH('') 
        ),1,10,''); 
EXEC(@cmd); 
Powiązane problemy