I ran this query:
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.Stu')
ORDER BY i.name
and the largest index returned had a NULL name. What does this mean?
From sys.indexes:
Name of the index...
NULL = Heap
So those are heaps.
The sys.indexes view shows not only indexes, but also tables which don't have indexes on them. Such tables are called heaps. In such case, there is no name of the index. This can be misleading, I agree.
SELECT i.object_id, i.type_desc,
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.Stu')
ORDER BY i.object_id, i.name
Basically if the query you posted returns NULL index name, it means there is no clustered index on your table dbo.Stu.
I would recommend creating a clustered index on the table.
Imortant addition to above answers:
Index name in sys.indexes catalog view can be NULL in TWO cases:
1) As specified in MSDN, if it is actually a heap, i.e. table has no clustered index. For each nunclustered table there is one such a record in sys.indexes view (even if table has other, nonclustered indexes).
2) If this is a statistic (MSDN surprisingly keeps silence about this!). At least, I observed such a condition on one of my databases under SQL 2008 R2 server.
Related
I am trying to understand how to check if any table in my db has data using entity framework. I can check for one table but how can I check for all tables at once? DO we have any option with ef6?
using (var db = new CreateDbContext())
{
if(!db.FirstTable.Any())
{
// The table is empty
}
}
Any pointers on how to loop through entities would be helpful.
Here is one way you could do this with t-sql. This should be lightning fast on most systems. This returned in less than a second on our ERP database. It stated 421 billion rows in more than 15,000 partition stats.
select sum(p.row_count)
from sys.dm_db_partition_stats p
join sys.objects o on o.object_id = p.object_id
where o.type not in ('S', 'IT') --excludes system and internal tables.
Similar to #SeanLange, but shows schema name and table name for tables without any rows.
SELECT Distinct OBJECT_SCHEMA_NAME(p.object_id) AS [Schema],
OBJECT_NAME(p.object_id) AS [Table]
FROM sys.partitions p
INNER JOIN sys.indexes i
ON p.object_id = i.object_id
AND p.index_id = i.index_id
WHERE OBJECT_SCHEMA_NAME(p.object_id) != 'sys'
And p.Rows = 0
ORDER BY [Schema], [Table]
I have created indexes on my DB the last 2 months. Everything works fine. However, now I have to move those indexes to the UAT ENV. I kept track of the indexes I created. However I want to be sure I didn't miss any. How do I know the indexes created in the last 2 months using a query?
SQL Server does not maintain index creation information for indexes in a DMV. This is not information you can query.
You can get this information for PK, unique indexes or unique constraints.
See Kendra Little's blog here for some good info on this topic.
From Kendra's post:
But if you’re not looking for the create date of a Primary Key, unique index, or unique constraint, you’re out of luck.
What you probably need is to check the indexes in the database through the catalog views. Maybe something like this can help you:
SELECT
t.name AS TableName,
ind.name AS IndexName,
col.name AS ColumnName,
STATS_DATE(t.object_id,ind.index_id)
FROM sys.indexes ind
INNER JOIN sys.index_columns ic ON ind.object_id = ic.object_id and ind.index_id = ic.index_id
INNER JOIN sys.columns col ON ic.object_id = col.object_id and ic.column_id = col.column_id
INNER JOIN sys.tables t ON ind.object_id = t.object_id
WHERE STATS_DATE(t.object_id,ind.index_id) > DATEADD(mm,-2,GETDATE())
ORDER BY TableName, IndexName, ColumnName
Remember to run in the database you have to check your indexes and not in the master.
Thanks for all the responses. There is really no good way to find the indexes created in last two months. The best way is to load the indexes in a table and compare them with DEV Indexes.
I am not sure how this happened, but I have a PRIMARY KEY constraint on one of my tables and the name is NULL. I discovered it because I had to drop/recreate the table, and when I tried to add the PRIMARY KEY, the system responded that the constraint already existed.
I executed the following:
SELECT i.object_id, i.name, i.type_desc
FROM sys.indexes i
INNER JOIN sys.tables t ON i.object_id = t.object_id
AND t.name = N'Organization'
and the result is:
object_id name type_desc
1570377655 NULL HEAP
1570377655 IX_Organization_OwnedByOrganizationId NONCLUSTERED
I tried dropping and recreating the table several times and each time the index is there. How can I drop the constraint?
You can try to find the index you are trying to add using the following query:
SELECT [Table] = t.[name]
, [Index] = i.[name]
, i.*
FROM sys.indexes i
INNER JOIN sys.tables t
ON t.[object_id] = i.[object_id]
Martin has the right answer to index you find with the NULL name.
How do I list tables without indexes in my SQL 2008 database?
Edit
I want the Schema name and the Table name.
This should cover what your looking for. i.e. tables that are heaps (no clustered index) and do not have any non-clustered indexes. It uses the new sys. table objects used in 2005/2008.
in addition, you probably want to look for tables that do have a clustered index, but have no nonclustered indexes (this is the 2nd part of the statement which I've left commented out.
SELECT
schemaname = OBJECT_SCHEMA_NAME(o.object_id)
,tablename = o.NAME
FROM sys.objects o
INNER JOIN sys.indexes i ON i.OBJECT_ID = o.OBJECT_ID
-- tables that are heaps without any nonclustered indexes
WHERE (
o.type = 'U'
AND o.OBJECT_ID NOT IN (
SELECT OBJECT_ID
FROM sys.indexes
WHERE index_id > 0
)
)
-- OR
-- table that have a clustered index without any nonclustered indexes
--(o.type='U'
-- AND o.OBJECT_ID NOT IN (
-- SELECT OBJECT_ID
-- FROM sys.indexes
-- WHERE index_id>1))
Here's an example:
select SCHEMA_NAME(schema_id), name from sys.tables
where OBJECTPROPERTY(object_id, 'IsIndexed')= 0
In addition to #Philip Fourie's suggestion you might want to think about which indexes to create.
Once you have been accessing your data, SQL Server 2008 keeps track of places where it thinks indexes will be helpful (it refers to these as "missing indexes." There are a hand full of new Dynamic Managed Views which can show these missing indexes and some info about them.
From MSSQlTips:
sys.dm_db_missing_index_details - Returns detailed information about a missing index
sys.dm_db_missing_index_group_stats - Returns summary information about missing index groups
sys.dm_db_missing_index_groups - Returns information about a specific group of missing indexes
sys.dm_db_missing_index_columns(index_handle) - Returns information about the database table columns that are missing for an index. This is a function and requires the index_handle to be passed.
select shema = s.name, table_name = o.name
from sys.objects o
join sys.schemas s on o.schema_id = s.schema_id
where type = 'U'
and not exists (select i.index_id
from sys.indexes i
where i.type <> 0 --ignore default heap index row
and o.object_id = i.object_id )
Edit:
I have updated the SQL to include the Schema name as requested. (Note I had to sys.objects instead of sysobjects to cater for schemas that were introduced in SQL 2005)
The catalog tables are documented in the SQL Server documentation, see this link.
This FAQ contains more samples and might also be useful.
Note that these are system tables and can change between SQL server versions, where possible rather use the system table-independent views called Information Schema Views.
This code gives all the details about the indexes for all the tables:
SELECT
sch.name AS [Schema],
obj.name AS TableName,
indx.name AS IndexName,
CASE
WHEN indx.type_desc = 'HEAP' THEN 'N/A'
ELSE indx.type_desc
END AS IndexType
FROM sys.objects obj
JOIN sys.indexes indx ON indx.object_id = obj.object_id
JOIN sys.schemas AS sch ON sch.schema_id = obj.schema_id
WHERE
obj.type = 'U'
ORDER BY
obj.name
Suppose I have a UNIQUE CLUSTERED INDEX on a table which has 3 columns. What would be an efficient way to get the columns on providing this index name?
The following example returns all indexes and index columns for the table myTbl.
SELECT i.name AS index_name
,COL_NAME(ic.object_id,ic.column_id) AS column_name
,ic.index_column_id
,ic.key_ordinal
,ic.is_included_column
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.object_id = OBJECT_ID('myTbl');
Source here
Well, you can go to the Index folder in SSMS under that DB > Table and script out the Index to see everything about it. Or just right click on the index and click Properties, and the columns will be listed under General