Come trovare oggetti più grandi in un database di SQL Server?


136

Come farei per trovare gli oggetti più grandi in un database di SQL Server? Innanzitutto, determinando quali tabelle (e relativi indici) sono le più grandi e quindi determinando quali righe in una determinata tabella sono più grandi (stiamo memorizzando i dati binari in BLOB)?

Ci sono strumenti là fuori per aiutare con questo tipo di analisi del database? O ci sono alcune semplici query che potrei eseguire contro le tabelle di sistema?

Risposte:


280

Sto usando questo script SQL (che ho ottenuto da qualcuno, da qualche parte - non riesco a ricostruire da chi proviene) per anni e mi ha aiutato un po 'a capire e determinare la dimensione di indici e tabelle:

SELECT 
    t.name AS TableName,
    i.name as indexName,
    sum(p.rows) as RowCounts,
    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 
ORDER BY 
    object_name(i.object_id) 

Naturalmente, puoi utilizzare un altro criterio di ordinazione, ad es

ORDER BY SUM(p.rows) DESC

per ottenere le tabelle con il maggior numero di righe oppure

ORDER BY SUM(a.total_pages) DESC

per ottenere le tabelle con il maggior numero di pagine (blocchi 8K) utilizzate.


Eccellente grazie! Ora, che ho ristretto il mio oggetto più grande a una tabella che contiene molti dati binari, comunque per capire quale delle righe di dati binari è la più grande?
Jamesaharvey,

3
per questo, dovresti fare una selezione su quella tabella e stampare DATALENGTH (campo) per ogni campo che ti interessa (in genere VARCHAR (MAX), VARBINARY (MAX) e così via)
marc_s

1
Grazie @marc_s, questo è stato molto utile. La colonna TableName può anche includere il nome dello schema conSELECT OBJECT_SCHEMA_NAME(i.object_id) + '.' + OBJECT_NAME(i.object_id) AS TableName, ...
CruiZen

2
Deve essere lo script TSQL più bello che abbia mai visto
Agustin Meriles,

2
Per includere anche gli indici NON CLUSTER, rimuovere "e i.index_id <= 1" dalla clausola WHERE.
Gordon Bell,

72

In SQL Server 2008, è anche possibile eseguire il report standard Utilizzo del disco in base alle tabelle principali. Questo può essere trovato facendo clic destro sul DB, selezionando Rapporti-> Rapporti standard e selezionando il rapporto desiderato.


8
Non stai scherzando? Questa è una risposta così rivoluzionaria. Grazie per averlo pubblicato. (Non sarcasmo. Eseguo queste query manualmente da un po 'di tempo e non posso credere che questi rapporti siano già lì!)
Jennifer Zouak

4

Questa query aiuta a trovare la tabella più grande in te è la connessione.

SELECT  TOP 1 OBJECT_NAME(OBJECT_ID) TableName, st.row_count
FROM sys.dm_db_partition_stats st
WHERE index_id < 2
ORDER BY st.row_count DESC

È bello avere qualcosa che possiamo facilmente memorizzare. Grazie per la concisione.
David Betz,

3

Puoi anche usare il seguente codice:

USE AdventureWork
GO
CREATE TABLE #GetLargest 
(
  table_name    sysname ,
  row_count     INT,
  reserved_size VARCHAR(50),
  data_size     VARCHAR(50),
  index_size    VARCHAR(50),
  unused_size   VARCHAR(50)
)

SET NOCOUNT ON

INSERT #GetLargest

EXEC sp_msforeachtable 'sp_spaceused ''?'''

SELECT 
  a.table_name,
  a.row_count,
  COUNT(*) AS col_count,
  a.data_size
  FROM #GetLargest a
     INNER JOIN information_schema.columns b
     ON a.table_name collate database_default
     = b.table_name collate database_default
       GROUP BY a.table_name, a.row_count, a.data_size
       ORDER BY CAST(REPLACE(a.data_size, ' KB', '') AS integer) DESC

DROP TABLE #GetLargest

2

Se si utilizza Sql Server Management Studio 2008 ci sono alcuni campi di dati che è possibile visualizzare nella finestra dei dettagli di Esplora oggetti. Basta navigare e selezionare la cartella delle tabelle. Nella vista dei dettagli è possibile fare clic con il pulsante destro del mouse sui titoli delle colonne e aggiungere campi al "report". Il tuo chilometraggio può variare se sei su SSMS 2008 express.


2

Ho trovato questa query anche molto utile in SqlServerCentral, ecco il link al post originale

Tabelle più grandi di SQL Server

  select name=object_schema_name(object_id) + '.' + object_name(object_id)
, rows=sum(case when index_id < 2 then row_count else 0 end)
, reserved_kb=8*sum(reserved_page_count)
, data_kb=8*sum( case 
     when index_id<2 then in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count 
     else lob_used_page_count + row_overflow_used_page_count 
    end )
, index_kb=8*(sum(used_page_count) 
    - sum( case 
           when index_id<2 then in_row_data_page_count + lob_used_page_count + row_overflow_used_page_count 
        else lob_used_page_count + row_overflow_used_page_count 
        end )
     )    
, unused_kb=8*sum(reserved_page_count-used_page_count)
from sys.dm_db_partition_stats
where object_id > 1024
group by object_id
order by 
rows desc   

Nel mio database hanno dato risultati diversi tra questa query e la prima risposta.

Spero che qualcuno lo trovi utile


1

La risposta di @ marc_s è ottima e la uso da alcuni anni. Tuttavia, ho notato che lo script manca i dati in alcuni indici columnstore e non mostra un'immagine completa. Ad esempio quando lo faiSUM(TotalSpace) con lo script e lo confronti con la proprietà del database dello spazio totale in Management Studio, i numeri non corrispondono nel mio caso (Management Studio mostra numeri più grandi). Ho modificato lo script per superare questo problema e l'ho esteso un po ':

select
    tables.[name] as table_name,
    schemas.[name] as schema_name,
    isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown') as database_name,
    sum(allocation_units.total_pages) * 8 as total_space_kb,
    cast(round(((sum(allocation_units.total_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as total_space_mb,
    sum(allocation_units.used_pages) * 8 as used_space_kb,
    cast(round(((sum(allocation_units.used_pages) * 8) / 1024.00), 2) as numeric(36, 2)) as used_space_mb,
    (sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8 as unused_space_kb,
    cast(round(((sum(allocation_units.total_pages) - sum(allocation_units.used_pages)) * 8) / 1024.00, 2) as numeric(36, 2)) as unused_space_mb,
    count(distinct indexes.index_id) as indexes_count,
    max(dm_db_partition_stats.row_count) as row_count,
    iif(max(isnull(user_seeks, 0)) = 0 and max(isnull(user_scans, 0)) = 0 and max(isnull(user_lookups, 0)) = 0, 1, 0) as no_reads,
    iif(max(isnull(user_updates, 0)) = 0, 1, 0) as no_writes,
    max(isnull(user_seeks, 0)) as user_seeks,
    max(isnull(user_scans, 0)) as user_scans,
    max(isnull(user_lookups, 0)) as user_lookups,
    max(isnull(user_updates, 0)) as user_updates,
    max(last_user_seek) as last_user_seek,
    max(last_user_scan) as last_user_scan,
    max(last_user_lookup) as last_user_lookup,
    max(last_user_update) as last_user_update,
    max(tables.create_date) as create_date,
    max(tables.modify_date) as modify_date
from 
    sys.tables
    left join sys.schemas on schemas.schema_id = tables.schema_id
    left join sys.indexes on tables.object_id = indexes.object_id
    left join sys.partitions on indexes.object_id = partitions.object_id and indexes.index_id = partitions.index_id
    left join sys.allocation_units on partitions.partition_id = allocation_units.container_id
    left join sys.dm_db_index_usage_stats on tables.object_id = dm_db_index_usage_stats.object_id and indexes.index_id = dm_db_index_usage_stats.index_id
    left join sys.dm_db_partition_stats on tables.object_id = dm_db_partition_stats.object_id and indexes.index_id = dm_db_partition_stats.index_id
group by schemas.[name], tables.[name], isnull(db_name(dm_db_index_usage_stats.database_id), 'Unknown')
order by 5 desc

Spero che sia utile per qualcuno. Questo script è stato testato su grandi database di dimensioni TB con centinaia di tabelle, indici e schemi diversi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.