March 2008 - Posts

select
    case when dbid = 32767
        then 'resource'
        else db_name(dbid)
    end [db_name]
    , object_schema_name(objectid,dbid) [schema_name]
    , object_name(objectid,dbid) [object_name]
    , sum(usecounts) [executions]
    , max(max_execution_time) [last_execution_time]
    , sum(total_logical_reads) [total_logical_reads]
    , sum(total_logical_reads) / sum(usecounts) * 1.0 [avg_logical_reads]
    , sum(total_elapsed_time) / 1000 [total_elapsed_time_ms]
    , ( sum(total_elapsed_time) / sum(usecounts) * 1.0 ) / 1000 [avg_elapsed_time_ms]
from
    sys.dm_exec_cached_plans cp
    cross apply sys.dm_exec_sql_text(cp.plan_handle) qt
    join (
        select
            plan_handle
            , max(last_execution_time) [max_execution_time]
            , sum(total_elapsed_time) [total_elapsed_time]
            , sum(total_logical_reads) [total_logical_reads]
        from
            sys.dm_exec_query_stats
        group by
            plan_handle
        ) r on r.plan_handle = cp.plan_handle
where
    objtype = 'Proc'
    and qt.text LIKE '%create%proc%'
    --and db_name(dbid) = 'some_database'
    --and object_name(objectid,dbid) = 'some_stored_procedure'
group by
    dbid, objectid
order by
    db_name(dbid), object_name(objectid,dbid)

 

thanks to this article for the inspiration.

Great useful base diag scripts! Snipped from http://glennberrysqlperformance.spaces.live.com/blog/cns!45041418ECCAA960!893.entry 
-- SQL Server 2005 Emergency Diagnostic and Performance Queries
-- Glenn Berry 3-17-2008


-- Step 1 - Check Task Manager. Are all CPUs above 90-95% for an extended period of time?
-- If yes, run HIGH CPU queries below:

-- Step 2 - Check Performance Monitor
-- SQL Server Buffer Manager: Buffer Cache Hit Ratio and Page Life Expectancy
-- SQL Server Memory Manager: Memory Grants Pending and Memory Grants Pending
-- Physical Disk: Avg disk sec/Read and Avg disk sec/Write

-- Step 3 - Check for locking, blocking and missing indexes
-- Run the BLOCKING queries below:

-- Step 4 - Is the transaction log full?
-- Run the TRANSACTION LOG FULL queries below:

-- Step 5 - Check for IO Problems
-- Run the IO ISSUES queries below



-- HIGH CPU *******
-- Get the most CPU intensive queries
SET NOCOUNT ON;

DECLARE @SpID smallint
DECLARE spID_Cursor CURSOR
FAST_FORWARD FOR

SELECT TOP 25 spid
FROM master..sysprocesses
WHERE status = 'runnable'
AND spid > 50 -- Eliminate system SPIDs
AND spid <> @@SPID
ORDER BY CPU DESC

OPEN spID_Cursor

FETCH NEXT FROM spID_Cursor
INTO @spID
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT 'Spid #:' + STR(@spID)
EXEC ('DBCC INPUTBUFFER (' + @spID + ')')

FETCH NEXT FROM spID_Cursor
INTO @spID
END

-- Close and deallocate the cursor
CLOSE spID_Cursor
DEALLOCATE spID_Cursor


-- HIGH CPU *******
-- Isolate top waits for server instance
WITH Waits AS
(
SELECT
wait_type,
wait_time_ms / 1000. AS wait_time_s,
100. * wait_time_ms / SUM(wait_time_ms) OVER() AS pct,
ROW_NUMBER() OVER(ORDER BY wait_time_ms DESC) AS rn
FROM sys.dm_os_wait_stats
WHERE wait_type NOT LIKE '%SLEEP%'
)
SELECT
W1.wait_type,
CAST(W1.wait_time_s AS DECIMAL(12, 2)) AS wait_time_s,
CAST(W1.pct AS DECIMAL(12, 2)) AS pct,
CAST(SUM(W2.pct) AS DECIMAL(12, 2)) AS running_pct
FROM Waits AS W1
INNER JOIN Waits AS W2
ON W2.rn <= W1.rn
GROUP BY W1.rn, W1.wait_type, W1.wait_time_s, W1.pct
HAVING SUM(W2.pct) - W1.pct < 90 -- percentage threshold
ORDER BY W1.rn;

-- HIGH CPU *******
-- Total waits are wait_time_ms (high signal waits indicates CPU pressure)
SELECT '%signal (cpu) waits' = CAST(100.0 * SUM(signal_wait_time_ms) / SUM (wait_time_ms) AS NUMERIC(20,2)),
'%resource waits'= CAST(100.0 * SUM(wait_time_ms - signal_wait_time_ms) / SUM (wait_time_ms) AS NUMERIC(20,2))
FROM sys.dm_os_wait_stats;

-- HIGH CPU *******
-- Check SQL Server Schedulers to see if they are waiting on CPU (runnable tasks above 10 is very bad)
SELECT scheduler_id, current_tasks_count, runnable_tasks_count
FROM sys.dm_os_schedulers
WHERE scheduler_id < 255

-- HIGH CPU *******
-- Who is running what at this instant
SELECT st.text AS [Command text], login_time, [host_name],
[program_name], sys.dm_exec_requests.session_id, client_net_address,
sys.dm_exec_requests.status, command, db_name(database_id) AS DatabaseName
FROM sys.dm_exec_requests
INNER JOIN sys.dm_exec_connections
ON sys.dm_exec_requests.session_id = sys.dm_exec_connections.session_id
INNER JOIN sys.dm_exec_sessions
ON sys.dm_exec_sessions.session_id = sys.dm_exec_requests.session_id
CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS st
WHERE sys.dm_exec_requests.session_id >= 51
AND sys.dm_exec_requests.session_id <> @@spid
ORDER BY sys.dm_exec_requests.status

-- HIGH CPU *******
-- Get a snapshot of current activity
SELECT LTRIM (st.text) AS 'Command Text',[host_name], der.session_id AS 'SPID',
der.status, db_name(database_id) AS DatabaseName, ISNULL(der.wait_type, 'None')AS 'Wait Type', der.logical_reads
FROM sys.dm_exec_requests AS der
INNER JOIN sys.dm_exec_connections AS dexc
ON der.session_id = dexc.session_id
INNER JOIN sys.dm_exec_sessions AS dexs
ON dexs.session_id = der.session_id
CROSS APPLY sys.dm_exec_sql_text(sql_handle) AS st
WHERE der.session_id >= 51
AND der.session_id <> @@spid
ORDER BY der.status

-- BLOCKING ************
-- Detect blocking
SELECT blocked_query.session_id AS blocked_session_id,
blocking_query.session_id AS blocking_session_id,
sql_text.text AS blocked_text, sql_btext.text AS blocking_text, waits.wait_type AS blocking_resource
FROM sys.dm_exec_requests AS blocked_query
INNER JOIN sys.dm_exec_requests AS blocking_query
ON blocked_query.blocking_session_id = blocking_query.session_id
CROSS APPLY
(SELECT * FROM sys.dm_exec_sql_text(blocking_query.sql_handle)
) sql_btext
CROSS APPLY
(SELECT * FROM sys.dm_exec_sql_text(blocked_query.sql_handle)
) sql_text
INNER JOIN sys.dm_os_waiting_tasks AS waits
ON waits.session_id = blocking_query.session_id

-- BLOCKING ************
-- Index Contention
SELECT dbid=database_id, objectname=object_name(s.object_id),
indexname=i.name, i.index_id, row_lock_count, row_lock_wait_count,
[block %]= CAST (100.0 * row_lock_wait_count / (1 + row_lock_count) AS NUMERIC(15,2)),
row_lock_wait_in_ms,
[avg row lock waits in ms]= CAST (1.0 * row_lock_wait_in_ms / (1 + row_lock_wait_count) AS NUMERIC(15,2))
FROM sys.dm_db_index_operational_stats (db_id(), NULL, NULL, NULL) AS s
INNER JOIN sys.indexes AS i
ON i.object_id = s.object_id
WHERE objectproperty(s.object_id,'IsUserTable') = 1
AND i.index_id = s.index_id
ORDER BY row_lock_wait_count DESC

-- TRANSACTION LOG FULL *****
-- Find the log reuse description for the transaction log
SELECT name, database_id, log_reuse_wait_desc
FROM sys.databases

-- TRANSACTION LOG FULL *****
-- Individual File Size query
SELECT name AS 'File Name' , physical_name AS 'Physical Name', size/128 AS 'Total Size in MB',
size/128.0 - CAST(FILEPROPERTY(name, 'SpaceUsed') AS int)/128.0 AS 'Available Space In MB'--, *
FROM sys.database_files;

-- IO ISSUES *****************
-- Analyze DB IO, ranked by IO Stall %
WITH DBIO AS
(
SELECT
DB_NAME(IVFS.database_id) AS db,
CASE WHEN MF.type = 1 THEN 'log' ELSE 'data' END AS file_type,
SUM(IVFS.num_of_bytes_read + IVFS.num_of_bytes_written) AS io,
SUM(IVFS.io_stall) AS io_stall
FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS IVFS
JOIN sys.master_files AS MF
ON IVFS.database_id = MF.database_id
AND IVFS.file_id = MF.file_id
GROUP BY DB_NAME(IVFS.database_id), MF.type
)
SELECT db, file_type,
CAST(1. * io / (1024 * 1024) AS DECIMAL(12, 2)) AS io_mb,
CAST(io_stall / 1000. AS DECIMAL(12, 2)) AS io_stall_s,
CAST(100. * io_stall / SUM(io_stall) OVER()
AS DECIMAL(10, 2)) AS io_stall_pct,
ROW_NUMBER() OVER(ORDER BY io_stall DESC) AS rn
FROM DBIO
ORDER BY io_stall DESC;

-- HIGH CPU ************
-- Get Top 100 executed SP's ordered by execution count
SELECT TOP 100 qt.text AS 'SP Name', qs.execution_count AS 'Execution Count',
qs.execution_count/DATEDIFF(Second, qs.creation_time, GetDate()) AS 'Calls/Second',
qs.total_worker_time/qs.execution_count AS 'AvgWorkerTime',
qs.total_worker_time AS 'TotalWorkerTime',
qs.total_elapsed_time/qs.execution_count AS 'AvgElapsedTime',
qs.max_logical_reads, qs.max_logical_writes, qs.total_physical_reads,
DATEDIFF(Minute, qs.creation_time, GetDate()) AS 'Age in Cache'
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE qt.dbid = db_id() -- Filter by current database
ORDER BY qs.execution_count DESC

-- HIGH CPU *************
-- Get Top 20 executed SP's ordered by total worker time (CPU pressure)
SELECT TOP 20 qt.text AS 'SP Name', qs.total_worker_time AS 'TotalWorkerTime',
qs.total_worker_time/qs.execution_count AS 'AvgWorkerTime',
qs.execution_count AS 'Execution Count',
ISNULL(qs.execution_count/DATEDIFF(Second, qs.creation_time, GetDate()), 0) AS 'Calls/Second',
ISNULL(qs.total_elapsed_time/qs.execution_count, 0) AS 'AvgElapsedTime',
qs.max_logical_reads, qs.max_logical_writes,
DATEDIFF(Minute, qs.creation_time, GetDate()) AS 'Age in Cache'
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE qt.dbid = db_id() -- Filter by current database
ORDER BY qs.total_worker_time DESC


select top 10
    t.text
    , s.last_execution_time
    , *
from
    sys.dm_exec_query_stats s
    cross apply sys.dm_exec_sql_text(s.sql_handle) t
where
    t.objectid is not null
    and text like '%procname%'
order by
    s.last_execution_time desc

 

obviously replace procname with the procname you want to find. you might get multiple results, and you can probably clean it up some, but it works fine for what i generally need to get the info for. while i was researching this, i also came accross this pretty cool query:

 

-- Get Top 200 executed SP's ordered by calls/minute
SELECT TOP 200 qt.text AS 'SP Name', qs.execution_count AS 'Execution Count',
qs.total_worker_time/ISNULL(qs.execution_count, 1) AS 'AvgWorkerTime',
qs.total_worker_time AS 'TotalWorkerTime',
qs.total_elapsed_time/ISNULL(qs.execution_count, 1) AS 'AvgElapsedTime',
qs.max_logical_reads, qs.max_logical_writes, qs.creation_time,
DATEDIFF(Minute, qs.creation_time, GetDate()) AS 'Age in Cache',
qs.execution_count/ISNULL(DATEDIFF(Minute, qs.creation_time, GetDate()), 1) AS 'Calls/Minute',
qs.execution_count/ISNULL(DATEDIFF(Second, qs.creation_time, GetDate()), 1) AS 'Calls/Second'
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS qt
WHERE qt.dbid = 5 -- Change this for the database you are interested in
ORDER BY qs.execution_count/ISNULL(DATEDIFF(Minute, qs.creation_time, GetDate()), 1) DESC

quoted from: http://glennberrysqlperformance.spaces.live.com/blog/cns!45041418ECCAA960!248.entry 


quoted from http://www.dotnet247.com/247reference/msgs/7/38630.aspx

Ok, to get you started, herewith a simple sample, the C# file contains a single class and one method.
After compiling the file, you need to register the class using regasm.
Regasm requires the assembly to have a strong name, therefore you ned to run sn -k to create a assembly key file (here called
MyKey.snk).

Once the class registered, load the stored procedure in SQL queryanalyzer and run the Proc.

More info on COM interop is found in the MSDN docs.

C# file:

using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Runtime.CompilerServices;

[assembly: AssemblyTitle("CSServer")]
[assembly: AssemblyDescription("Test SQL .NET interop")]
[assembly: AssemblyVersion("1.0.0.1")]
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("MyKey.snk")]
namespace SQLInterop {
public interface ITest{
string SayHello();
}

[ClassInterface(ClassInterfaceType.AutoDual)]
public class CsharpHelper : ITest {
public string SayHello() {
return "Hello from CSharp";
}
}
}
/*
Create a key pair file, compile and register
sn -k MyKey.snk
csc /t:library Csserver.cs
regasm /tlb:Csserver.tlb csserver.dll /codebase
*/

T-SQL stored proc.

DECLARE @object int
DECLARE @hr int
DECLARE @property varchar(255)
DECLARE @return varchar(255)
DECLARE @src varchar(255), @desc varchar(255)

-- Create an object.
EXEC @hr = sp_OACreate 'SQLInterop.CsharpHelper', @object OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END

-- Call a method that returns a value.
EXEC @hr = sp_OAMethod @object, 'SayHello', @return OUT
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END
PRINT @return

-- Destroy the object.
EXEC @hr = sp_OADestroy @object
IF @hr <> 0
BEGIN
EXEC sp_OAGetErrorInfo @object, @src OUT, @desc OUT
SELECT hr=convert(varbinary(4),@hr), Source=@src, Description=@desc
RETURN
END
 

EXEC sp_configure
    @configname = 'Show Advanced Options',
    @configvalue = 1 RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure
    @configname = 'clr enabled',
    @configvalue = 1 RECONFIGURE WITH OVERRIDE
GO
EXEC sp_configure
go

Found something nifty I didn't know about today. create multiple objects in a single using statement. I figured i would include some sample code i use for compression/decompression. I'm using the #ziplib libraries, but you could use any stream based process really. The bufferSize variable you can change to fit your needs. 

 

 

//unzip data. assume we have a compressed file and are creating the output file

using (FileStream

    u = File.Create(PathToUncompressedFile),

    c = File.OpenRead(PathToCompressedFile))

using (GZipInputStream gzip = new GZipInputStream(c))

    while ((bufferSize = gzip.Read(buffer, 0, buffer.Length)) != 0)

        u.Write(buffer, 0, bufferSize);

 

//zip data. assume we have a uncompressed file and are creating the output file

using (FileStream

    u = File.OpenRead(PathToUncompressedFile),

    c = File.Create(PathToCompressedFile))

using (GZipOutputStream gzip = new GZipOutputStream(c))

    while ((bufferSize = u.Read(buffer, 0, buffer.Length)) != 0)

        gzip.Write(buffer, 0, bufferSize);