2008-11-25 10 views
70

Pouvons-nous avoir une requête SQL qui aidera essentiellement à visualiser la taille des tables et d'index dans SQL Server.Tableau et la taille Index dans SQL Server

Comment SQL Server gère l'utilisation de la mémoire pour les tables/index?

+0

Il y a des réponses déjà à cela, mais je l'utilise personnellement la requête dans ce lien: http: // qualityofdata. com/2011/02/02/analise table-espace-utilisation-en-sql-server/ – naiem

+0

vous trouverez également la procédure stockée 'sp_helpdb' utile –

Répondre

65

Le exec sp_spaceused sans paramètre indique le résumé de la base de données entière. La solution foreachtable génère un jeu de résultats par table - ce que SSMS pourrait ne pas être capable de gérer si vous avez trop de tables.

J'ai créé un script qui collecte les informations de la table via sp_spaceused et affiche un résumé dans un jeu d'enregistrements unique, trié par taille.

create table #t 
(
    name nvarchar(128), 
    rows varchar(50), 
    reserved varchar(50), 
    data varchar(50), 
    index_size varchar(50), 
    unused varchar(50) 
) 

declare @id nvarchar(128) 
declare c cursor for 
select '[' + sc.name + '].[' + s.name + ']' FROM sysobjects s INNER JOIN sys.schemas sc ON s.uid = sc.schema_id where s.xtype='U' 

open c 
fetch c into @id 

while @@fetch_status = 0 begin 

    insert into #t 
    exec sp_spaceused @id 

    fetch c into @id 
end 

close c 
deallocate c 

select * from #t 
order by convert(int, substring(data, 1, len(data)-3)) desc 

drop table #t 
+4

Votre script gère uniquement les tables dans le schéma 'dbo'. Si j'ai une table dans ma base de données avec un schéma de 'Audit', sp_spaceused doit être appelé comme ceci: exec sp_spaceused 'Audit.Data'.Il est donc nécessaire de modifier le script pour lui donner le nom de la table préfacé par le nom du schéma (séparé par un point) pour qu'il renvoie des données sur les tables d'autres schémas. – Baodad

+1

Bon point @Boadad ... qui devrait être une solution super facile. Remplacement du "sélectionnez le nom de sysobjects où xtype = 'U'" avec cela devrait faire l'affaire: « select '[' + sc.name + ']. [' + S.name + ']' FROM sysobjects s ​​ INNER JOIN sys.schemas sc ON s.uid = sc.schema_id où s.xtype = 'U' " Excellent script, merci! – DCaugs

+0

au lieu d'utiliser la table temporaire peut-on insérer des données dans une autre table qui n'est pas temporaire? – ldevp

13
EXEC sp_MSforeachtable @command1="EXEC sp_spaceused '?'" 
+2

Si vous publiez code, XML ou données d'échantillons, ** ** S'IL vOUS PLAÎT mettez en surbrillance ces lignes dans l'éditeur de texte et cliquez sur le bouton "échantillons de code" ('{}') sur la barre d'outils de l'éditeur pour bien le mettre en forme et la mettre en surbrillance! –

0

Il existe une procédure stockée étendue sp_spaceused qui récupère cette information. Il est assez alambiquée de le faire à partir du dictionnaire de données, mais This link les fans sur un script qu'il fait. This stackoverflow question a un certain sortance à l'information sur les structures de données sous-jacentes que vous pouvez utiliser pour construire des estimations de la taille des tables et d'index pour la planification de capcity.

107

sp_spaceused vous donne la taille de tous les index combinés.

Si vous voulez que la taille de chaque index pour une table, utilisez l'une de ces deux requêtes:

SELECT 
    i.name     AS IndexName, 
    SUM(s.used_page_count) * 8 AS IndexSizeKB 
FROM sys.dm_db_partition_stats AS s 
JOIN sys.indexes    AS i 
ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id 
WHERE s.[object_id] = object_id('dbo.TableName') 
GROUP BY i.name 
ORDER BY i.name 

SELECT 
    i.name    AS IndexName, 
    SUM(page_count * 8) AS IndexSizeKB 
FROM sys.dm_db_index_physical_stats(
    db_id(), object_id('dbo.TableName'), NULL, NULL, 'DETAILED') AS s 
JOIN sys.indexes AS i 
ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id 
GROUP BY i.name 
ORDER BY i.name 

Les résultats sont généralement un peu différent, mais à moins de 1%.

+0

La première requête inclut des clés primaires, ce qui est un peu déroutant pour plusieurs raisons. – quillbreaker

+0

La deuxième requête jette 'Msg 102, niveau 15, état 1, ligne 5 - Syntaxe incorrecte près de '('. 'Chez moi, mais je ne vois pas de problèmes avec la syntaxe.Une idée? – Oliver

+0

Oliver, quelle version sont vous marchez? Ça marche comme ça en 2008R2 et 2012. –

15

sur SQL 2012 pour obtenir ces renseignements sur un niveau de table est devenu délicieusement simple:

SQL Management Studio -> Faites un clic droit sur Db -> Rapports -> Rapports standard -> Utilisation du disque par table!

Profitez

3

Voici version plus compacte de la réponse la plus réussie:

create table #tbl(
    name nvarchar(128), 
    rows varchar(50), 
    reserved varchar(50), 
    data varchar(50), 
    index_size varchar(50), 
    unused varchar(50) 
) 

exec sp_msforeachtable 'insert into #tbl exec sp_spaceused [?]' 

select * from #tbl 
    order by convert(int, substring(data, 1, len(data)-3)) desc 

drop table #tbl 
3

c'est d'être depuis longtemps depuis la création de ce poste, mais je voulais partager mon script:

WITH CteIndex 
AS 
(
SELECT 
    reservedpages = (reserved_page_count) 
    ,usedpages = (used_page_count) 
    ,pages = (
      CASE 
       WHEN (s.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 
      )  
    ,s.object_id 
    ,i.index_id   
    ,i.type_desc AS IndexType 
    ,i.name AS indexname 
    FROM sys.dm_db_partition_stats s 
    INNER JOIN sys.indexes i ON s.[object_id] = i.[object_id] AND s.index_id = i.index_id 
) 
SELECT DISTINCT 
DB_NAME(DB_ID()) AS DatabaseName 
,o.name AS TableName 
,o.object_id 
,ct.indexname 
,ct.IndexType 
,ct.index_id 
, IndexSpace = LTRIM (STR ((CASE WHEN usedpages > pages THEN CASE WHEN ct.index_id < 2 THEN pages ELSE (usedpages - pages) END ELSE 0 END) * 8, 15, 0) + ' KB') 
FROM CteIndex ct 
INNER JOIN sys.objects o ON o.object_id = ct.object_id 
INNER JOIN sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL, NULL , NULL) ps ON ps.object_id = o.object_id 
AND ps.index_id = ct.index_id 
ORDER BY name ASC 

il fonctionne pour:

  • SQL Server (à partir de 2008)
  • Comprend informations pour toutes les tables par base de données actuelle
2
--Gets the size of each index for the specified table 
DECLARE @TableName sysname = N'SomeTable'; 

SELECT i.name AS IndexName 
     ,8 * SUM(s.used_page_count) AS IndexSizeKB 
FROM sys.indexes AS i 
    INNER JOIN sys.dm_db_partition_stats AS s 
     ON i.[object_id] = s.[object_id] AND i.index_id = s.index_id 
WHERE s.[object_id] = OBJECT_ID(@TableName, N'U') 
GROUP BY i.name 
ORDER BY i.name; 

SELECT i.name AS IndexName 
     ,8 * SUM(a.used_pages) AS IndexSizeKB 
FROM sys.indexes AS i 
    INNER JOIN sys.partitions AS p 
     ON i.[object_id] = p.[object_id] AND i.index_id = p.index_id 
    INNER JOIN sys.allocation_units AS a 
     ON p.partition_id = a.container_id 
WHERE i.[object_id] = OBJECT_ID(@TableName, N'U') 
GROUP BY i.name 
ORDER BY i.name; 
Questions connexes