I have a very big database which is about to used all of the space. So I want to check all of the big tables if they have been all compressed. I have get some script about list all of the uncompression table, but if anyone could tell me how to run a query can list all the uncompression table order by table size.
This should get you what you need. Specifically, look at data_compression_desc.
use <DatabaseName, sysname, >
go
set nocount on
go
select
IndexName = i.Name,
TableName = object_name(p.object_id),
IndexRows = p.rows,
DataCompression = data_compression_desc,
ps.in_row_data_page_count,
ps.in_row_used_page_count,
ps.in_row_reserved_page_count,
ps.lob_used_page_count,
ps.lob_reserved_page_count,
ps.row_overflow_used_page_count,
ps.row_overflow_reserved_page_count,
ps.used_page_count,
ps.reserved_page_count,
ps.row_count
from sys.partitions p
inner join sys.dm_db_partition_stats ps
on p.partition_id = ps.partition_id
and p.object_id = ps.object_id
inner join sys.indexes i
on p.object_id = i.object_id
and p.index_id = i.index_id
where p.object_id = object_id('<DatabaseName, sysname, >.dbo.<TableName, sysname, >')
Diagnosis
There are some standard reports in SSMS which you can use to see all the disk spaced used by all the tables and also if there is any unused disk space allocated to any of the tables.
If you Right Click on a database name in Object explorer and go to Reports, you can find many built-in reports. In your case Disk Usage by Top Tables is the one you should be looking at.
Fix
Once you have found the culprits , tables with a lot of unused space you can make use DBCC CLEANTABLE command to reclaim the unused space.
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]
What happens on the SQL Server engine side when I'm deleting an index from one of my tables?
Details: I have a database running into production.
In this database, I have a query that creates deadlocks on a regular basis. I've found the query creating the deadlock, ran it on my computer, showing its execution plan. SQL Server Management Studio proposes to add an index on one specific table.
The index makes sense to me but my problem is that, on this table I already have 3 indexes and, to be honest, I cannot be sure if they're properly used or if they've been created for a specific role.
I could simply add one more index on the table but I'm concerned about the cost I'll pay each time I add/update/delete data on the table.
I made a few attempts on my machine and it seems that I need to delete at least two other indexes to make the engine select the index I'm creating today (looks odd to me). As soon as I force the engine to take my index (because I deleted everything else), the query runs 10 times faster.
Can I simply use the DROP Index command without much problem? I don't have to rebuild or anything?
A non-clustered index is a secondary data structure - it's not "integrated" into the main data structure of the clustered index or heap.
As such, deleting one should be a relatively fast and pain-free experience, since all the system should need to do is remove metadata about the index and mark the index's pages as unallocated.
There shouldn't be a need to "rebuild" or do anything else.
You can run this query to get know whether the indexes of a table are used or not
SELECT TOP 50
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
, 'DROP INDEX ' + QUOTENAME(i.name)
+ ' ON ' + QUOTENAME(s.name) + '.'
+ QUOTENAME(OBJECT_NAME(dm_ius.OBJECT_ID)) AS 'drop statement'
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 o.name='your_table_name'
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
Then go with the DROP index statement if any of them are not used.
Before dropping, ensure the server has been UP for a long time enough so the indexes got the chance to get used.
Also, having three indexes on a table is not many. Just check they are useful to your queries.
Using SQL Server 2005, upgrading to 2012
If I have an ETL the does the following(Simplified)
TRUNCATE TABLE detination
INSERT INTO detination
SELECT *
FROM source
Does this clear the index and rebuild it with the inserts? Will I have fragments?
Assume it would not truncate the indexes. That would mean the database was physically inconsistent. So it cannot be this way.
Truncate logically removes all rows and physically creates fresh b-trees for all partitions. As the trees are fresh no fragmentation exists.
Actually I'm not sure if the trees have 0 or 1 pages allocated to them. But it doesn't matter. I believe for temp tables there is a special case that has to do with temp table caching. Also doesn't matter.
The insert from your question works the same way as any other insert. It is not influenced by the previous truncate in a cross-statement communication way. Whether it causes fragmentation is dependent on your specific case and, IMHO, best-placed in a new question.
Challenging #sjaan reponse
MSDN "TRUNCATE TABLE removes all rows from a table, but the table structure and its columns, constraints, indexes, and so on remain."
SQL team is saying that indexes will exist but with no data pages... You could easily check that with reference
If you check the size of indexes on that table it will be zero
SELECT *
FROM
(
SELECT OBJECT_NAME(i.OBJECT_ID) AS TableName,
i.name AS IndexName,
i.index_id AS IndexID,
8 * SUM(a.used_pages) AS 'Indexsize(KB)'
FROM sys.indexes AS i
JOIN sys.partitions AS p ON p.OBJECT_ID = i.OBJECT_ID
AND p.index_id = i.index_id
JOIN sys.allocation_units AS a ON a.container_id = p.partition_id
GROUP BY i.OBJECT_ID,
i.index_id,
i.name
) a
WHERE A.TableName LIKE '%table%'
ORDER BY Tablename,
indexid;
"TRUNCATE TABLE removes all rows from a table, but the table structure and its columns, constraints, indexes, and so on remain."
see article: https://msdn.microsoft.com/en-us/library/ms177570.aspx
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
I have a huge database with some 100 tables and some 250 stored procedures. I want to know the list of tables affected by a subset of stored procedures. For example, I have a list of 50 stored procedures, out of 250, and I want to know the list of tables that will be affected by these 50 stored procedures. Is there any easy way for doing this, other than reading all the stored procedures and finding the list of tables manually?
PS: I am using SQL Server 2000 and SQL Server 2005 clients for this.
This would be your SQL Server query:
SELECT
[NAME]
FROM
sysobjects
WHERE
xType = 'U' AND --specifies a user table object
id in
(
SELECT
sd.depid
FROM
sysobjects so,
sysdepends sd
WHERE
so.name = 'NameOfStoredProcedure' AND
sd.id = so.id
)
Hope this helps someone.
sp_depends 'StoredProcName' will return the object name and object type that the stored proc depends on.
EDIT: I like #KG's answer better. More flexible IMHO.
I'd do it this way in SQL 2005 (uncomment the "AND" line if you only want it for a particular proc):
SELECT
[Proc] = SCHEMA_NAME(p.schema_id) + '.' + p.name,
[Table] = SCHEMA_NAME(t.schema_id) + '.' + t.name,
[Column] = c.name,
d.is_selected,
d.is_updated
FROM sys.procedures p
INNER JOIN sys.sql_dependencies d
ON d.object_id = p.object_id
AND d.class IN (0,1)
INNER JOIN sys.tables t
ON t.object_id = d.referenced_major_id
INNER JOIN sys.columns c
ON c.object_id = t.object_id
AND c.column_id = d.referenced_minor_id
WHERE p.type IN ('P')
-- AND p.object_id = OBJECT_ID('MyProc')
ORDER BY
1, 2, 3
One very invasive option would be to get a duplicate database and set a trigger on every table that logs that something happened. Then run all the SP's. If you can't do lots of mods to the DB that wont work
Also, be sure to add the logging to existing triggers rather than replace them with logging if you also want tables that the SP's effect via triggers.