I can use sp_spaceused tablename to get the total index size for that table.
But is there a way to get all indexes of that table's size individually?
table-and-index-size-in-sql-server
Following script is copied from the above answer from Rob Garisson
SELECT
i.name AS IndexName,
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')
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
Related
i have this fine working query for determining
size,rowcount,ununsed,total mb of db..
it is mssql
thing is is there a way to modify this so it does query only one specific table in DB ? thanks alot. also any hints on how can i query more statistics ? thanks
USE [mydbname]
GO
SELECT
s.Name AS SchemaName,
t.Name AS TableName,
p.rows AS RowCounts,
CAST(ROUND((SUM(a.used_pages) / 128.00), 2) AS NUMERIC(36, 2)) AS Used_MB,
CAST(ROUND((SUM(a.total_pages) - SUM(a.used_pages)) / 128.00, 2) AS NUMERIC(36, 2)) AS Unused_MB,
CAST(ROUND((SUM(a.total_pages) / 128.00), 2) AS NUMERIC(36, 2)) AS Total_MB
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
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id
GROUP BY t.Name, s.Name, p.Rows
ORDER BY s.Name, t.Name
GO
You should just add the where condition:
WHERE t.Name = 'TABLE_NAME_GOES_HERE'
And if you have same tables in different schemas
WHERE t.Name = 'TABLE_NAME_GOES_HERE' and s.Name = 'SCHEMA_NAME_GOES_HERE'
okay finally a solution.
USE db_name
GO
SELECT
t.name AS TableName,
s.name AS SchemaName,
p.rows AS RowCounts,
SUM(a.total_pages) * 8 AS TotalSpaceKB,
SUM(a.used_pages) * 8 AS UsedSpaceKB,
(SUM(a.total_pages) - SUM(a.used_pages)) * 8 AS UnusedSpaceKB
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
LEFT OUTER JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE
t.name = 'table_name'
AND t.is_ms_shipped = 0
AND i.object_id > 255
GROUP BY
t.name, s.name, p.rows
ORDER BY
t.name;
GO
I have run the query below in order to find indexes to delete.
SELECT d.name AS DatabaseName, t.name AS TableName, i.name AS IndexName, ius.*
FROM sys.dm_db_index_usage_stats ius
JOIN sys.databases d ON d.database_id = ius.database_id
JOIN sys.tables t ON t.object_id = ius.object_id
JOIN sys.indexes i ON i.object_id = ius.object_id AND i.index_id =
ius.index_id
ORDER BY user_updates DESC
But the result set that returns is pretty confusing. I am receiving multiple rows for the same indexes with different database_ids and therefore names. Let's say we have an index and its name is IDXName and its is IDXID. This index is under TBL1 inthe DB1 database. But there are multiple rows for this index with same index name and same index id and same table name but different database ids.
I double checked the Microsoft documentation and it confirms that the database id in that view is the database where the index resides. So how come I have the ids of the databases that that index does not exist in?
Yoy didn't linit the query to current database, that's why you're seeing data on indexes from different databases:
SELECT d.name AS DatabaseName, t.name AS TableName, i.name AS IndexName, ius.*
FROM sys.dm_db_index_usage_stats ius
JOIN sys.databases d ON d.database_id = ius.database_id
JOIN sys.tables t ON t.object_id = ius.object_id
JOIN sys.indexes i ON i.object_id = ius.object_id AND i.index_id = ius.index_id
WHERE d.database_id = db_id()
ORDER BY user_updates DESC
If all you need from sys.databases is a database name, there's no need for the join at all:
SELECT db_name() AS DatabaseName, t.name AS TableName, i.name AS IndexName, ius.*
FROM sys.dm_db_index_usage_stats ius
JOIN sys.tables t ON t.object_id = ius.object_id
JOIN sys.indexes i ON i.object_id = ius.object_id AND i.index_id = ius.index_id
WHERE ius.database_id = db_id()
ORDER BY user_updates DESC
I need to identify all the primary keys in a db. The following code appears to do the job quite well:
SELECT i.name AS IndexName,
OBJECT_NAME (ic.OBJECT_ID) AS TableName,
COL_NAME (ic.OBJECT_ID, ic.column_id) AS ColumnName
FROM sys.indexes AS i
INNER JOIN sys.index_columns AS ic
ON i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
WHERE i.is_primary_key = 1
The problem I have is that some of the keys are compound keys. This query identifies which keys are compound (multiple rows for a particular indexName in the sys.indexes table) but it does not show me the order. I need to know this because:
PRIMARY KEY CLUSTERED
(
[bl_id] ASC,
[fl_id] ASC,
[rm_id] ASC
)
is not the same as:
PRIMARY KEY CLUSTERED
(
[rm_id] ASC
[fl_id] ASC,
[bl_id] ASC,
)
key_ordinal seems to do the trick:
SELECT i.name AS IndexName,
OBJECT_NAME (ic.OBJECT_ID) AS TableName,
COL_NAME (ic.OBJECT_ID, ic.column_id) AS ColumnName,
ic.Key_ordinal as ColumnOrder
FROM sys.indexes AS i
INNER JOIN sys.index_columns AS ic
ON i.OBJECT_ID = ic.OBJECT_ID AND i.index_id = ic.index_id
WHERE i.is_primary_key = 1
ORDER BY ic.OBJECT_ID, ic.Key_ordinal
I have the following:
SELECT name AS index_name,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes
Is it possible to add some information so I have an idea if each index is current and in use?
Also I'd like to return in the SELECT clause which table the index is on?
I am using the following query to find if an index is is use - if seeks,scans and look-ups are zero then it's not used.
SELECT TOP 25
o.name AS ObjectName
, i.name AS IndexName
, i.index_id AS IndexID
, dm_ius.user_seeks AS UserSeek
, dm_ius.user_scans AS UserScans
, dm_ius.user_lookups AS UserLookups
, dm_ius.user_updates AS UserUpdates
, p.TableRows
, is_disabled
,STATS_DATE(i.[OBJECT_ID], i.index_id) AS StatsUpdated
FROM sys.dm_db_index_usage_stats dm_ius
INNER JOIN sys.indexes i ON i.index_id = dm_ius.index_id AND dm_ius.object_id = i.object_id
INNER JOIN sys.objects o on dm_ius.object_id = o.object_id
INNER JOIN sys.schemas s on o.schema_id = s.schema_id
INNER JOIN (SELECT SUM(p.rows) TableRows, p.index_id, p.object_id
FROM sys.partitions p GROUP BY p.index_id, p.object_id) p
ON p.index_id = dm_ius.index_id AND dm_ius.object_id = p.object_id
WHERE OBJECTPROPERTY(dm_ius.object_id,'IsUserTable') = 1
AND dm_ius.database_id = DB_ID()
AND i.type_desc = 'nonclustered'
AND i.is_primary_key = 0
AND i.is_unique_constraint = 0
ORDER BY (dm_ius.user_seeks + dm_ius.user_scans + dm_ius.user_lookups) ASC
GO
How do you find the disk size of a specific index in sql server 2005?
USE master
SELECT SUM(used_page_count) * 8 AS [Size in kb]
FROM sys.indexes i
JOIN sys.dm_db_partition_stats p ON p.object_id = i.object_id AND i.index_id = p.index_id
WHERE i.object_id=OBJECT_ID('dbo.spt_values') AND i.name='ix2_spt_values_nu_nc'
Find out the disk size of an index:
SELECT
OBJECT_NAME(I.OBJECT_ID) AS TableName,
I.name AS IndexName,
8 * SUM(AU.used_pages) AS 'Index size (KB)',
CAST(8 * SUM(AU.used_pages) / 1024.0 AS DECIMAL(18,2)) AS 'Index size (MB)'
FROM
sys.indexes I
JOIN sys.partitions P ON P.OBJECT_ID = I.OBJECT_ID AND P.index_id = I.index_id
JOIN sys.allocation_units AU ON AU.container_id = P.partition_id
WHERE
OBJECT_NAME(I.OBJECT_ID) = '<TableName>'
GROUP BY
I.OBJECT_ID,
I.name
ORDER BY
TableName
You can use the stored procedure "sp_spaceused". it will tell you how much space is used for the index as well as the space used for data.
USE AdventureWorks2012;
GO
EXEC sp_spaceused 'Purchasing.Vendor';
GO
More info: http://msdn.microsoft.com/en-us/library/ms188776.aspx