Tuesday, May 1, 2012

ReIndexing and Defragmentation - SQL server script












Reindexing and Defragmentation is one of the routines a SQL DBA should perform on a database for maximizing the performance of a SQL Database.
How to know whether you need to reindex and consider doing a maintenance on your DB.

SELECT OBJECT_NAME(OBJECT_ID), index_id,index_type_desc,index_level,
 avg_fragmentation_in_percent,avg_page_space_used_in_percent,page_count
 FROM sys.dm_db_index_physical_stats
 (DB_ID(N'<DBNAME>'), NULL, NULL, NULL , 'SAMPLED' ORDER BY avg_fragmentation_in_percent DESC


The column Defragmentation percentage and Defrag_space used gives you information about Reindexing and Defragmentation. The following is the script I used for Reindexing and after that updating of stats can be done by a command or by stored procedure "EXEC dbo.sp_updatestats"  If there are any updates.
 
--Re-indexing
SET NOCOUNT ON;
DECLARE @objectid int;
DECLARE @indexid int;
DECLARE @partitioncount bigint;
DECLARE @schemaname nvarchar(130);
DECLARE @objectname nvarchar(130);
DECLARE @indexname nvarchar(130);
DECLARE @partitionnum bigint;
DECLARE @partitions bigint;
DECLARE @frag float;
DECLARE @command nvarchar(4000);
DECLARE @db_id SMALLINT;

SET @db_id = DB_ID('<DBNAME>');
-- Conditionally select tables and indexes from the sys.dm_db_index_physical_stats function
-- and convert object and index IDs to names.

SELECT
    object_id AS objectid,
    index_id AS indexid,
    partition_number AS partitionnum,      
    avg_fragmentation_in_percent AS frag
INTO #work_to_do

FROM sys.dm_db_index_physical_stats (@DB_ID, NULL, NULL , NULL, 'LIMITED') WHERE avg_fragmentation_in_percent > 10.0 AND index_id > 0;

-- Declare the cursor for the list of partitions to be processed.
DECLARE partitions CURSOR FOR SELECT * FROM #work_to_do;

-- Open the cursor.
OPEN partitions;

-- Loop through the partitions.
WHILE (1=1)

    BEGIN;
        FETCH NEXT
           FROM partitions
           INTO @objectid, @indexid, @partitionnum, @frag;
        IF @@FETCH_STATUS < 0 BREAK;

        SELECT @objectname = QUOTENAME(o.name), 
        @schemaname = QUOTENAME(s.name)
        FROM sys.objects AS o
       JOIN sys.schemas as s ON s.schema_id = o.schema_id
        WHERE o.object_id = @objectid;
        SELECT @indexname = QUOTENAME(name)
        FROM sys.indexes
        WHERE  object_id = @objectid AND index_id = @indexid;
        SELECT @partitioncount = count (*)
        FROM sys.partitions
        WHERE object_id = @objectid AND index_id = @indexid;

 -- 30 is an arbitrary decision point at which to switch between reorganizing and rebuilding.

        IF @frag < 30.0
            SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REORGANIZE';

        IF @frag >= 30.0
            SET @command = N'ALTER INDEX ' + @indexname + N' ON ' + @schemaname + N'.' + @objectname + N' REBUILD';

        IF @partitioncount > 1
            SET @command = @command + N' PARTITION=' + CAST(@partitionnum AS nvarchar(10));
        EXEC (@command);
        PRINT N'Executed: ' + @command;
    END;

-- Close and deallocate the cursor.
CLOSE partitions;

DEALLOCATE partitions;


-- Drop the temporary table.
DROP TABLE #work_to_do;


GO

Handy SQL Queries used by DBA's













Finding the 10 longest running Query in SQL Server:

Run following query to find longest running query using T-SQL.

SELECT DISTINCT TOP 10
t.
TEXT QueryName,
s.execution_count AS ExecutionCount,
s.max_elapsed_time AS MaxElapsedTime,
ISNULL(s.total_elapsed_time s.execution_count0AS AvgElapsedTime,
ISNULL(s.execution_count DATEDIFF(ss.creation_timeGETDATE()), 0AS FrequencyPerSec
FROM sys.dm_exec_query_stats s
CROSS APPLY sys.dm_exec_sql_texts.sql_handle t
ORDER BY
s.max_elapsed_time DESC

Note: sys.dm_exec_query_stats is the System view in master Database which has the query status.


Finding the ROW COUNT in tables of a Database:


 This Example uses the Adventureworks database you can run in a Newquery  window with already selected database or just give the name in use to use the specific database.

GOSELECT OBJECT_NAME(OBJECT_IDTableNamest.row_count
FROM sys.dm_db_partition_stats st
WHERE index_id 2
ORDER BY st.row_count DESC
GO


  Finding the Running Queries in Server:

SELECT sqltext.TEXT,
 req.session_id,
 req.status,
 req.command,
 req.cpu_time,req.total_elapsed_time FROM sys.dm_exec_requests req
 CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS sqltext


 Last Sucessfull Queries:
SELECT deqs.last_execution_time AS [Time], dest.TEXT AS [Query] FROM sys.dm_exec_query_stats AS deqs CROSS APPLY sys.dm_exec_sql_text(deqs.sql_handle) AS dest

ORDER BY deqs.last_execution_time DESC
Checking for a column name in all the tables
SELECT name FROM sysobjects WHERE id IN ( SELECT id FROM syscolumns WHERE name like '%Terminal%' or name like '%Merchant%' )

Check the Percentage of backup happening

SELECT A.NAME,B.TOTAL_ELAPSED_TIME/60000 AS [Running Time],B.ESTIMATED_COMPLETION_TIME/60000 AS [Remaining],B.PERCENT_COMPLETE as [%],(SELECT TEXT FROM sys.dm_exec_sql_text(B.SQL_HANDLE))AS COMMAND FROM MASTER..SYSDATABASES A, sys.dm_exec_requests B WHERE A.DBID=B.DATABASE_ID AND B.COMMAND LIKE '%BACKUP%' order by percent_complete desc,B.TOTAL_ELAPSED_TIME/60000 desc

Finding the active sessions of a user:

The sys.dm_exec_sessions will have all the active sessions of a user.  The details like session_id, Login time can be known from the below queries. Once the active sessions are found they can be killed using KILL command.
SELECT session_id
FROM sys.dm_exec_sessions
WHERE login_name <User_name>
KILL <session_id>
The below is the query which can be used for to see how much time elapsed after the user was logged in.
select login_name,session_id,LOGIN_time, DATEDIFF(s,login_time,getdate())/60 as 'TimeElapsedinminutes' from sys.dm_exec_sessions where login_name='<any valid Username>'

Finding The Tables count in a database

USE <DBNAME>
SELECT COUNT(*) from information_schema.tables WHERE table_type = 'base table'