SQL SERVER – Get Last Running Query Based on SPID

We often need to find the last running query or based on SPID need to know which query was executed. SPID is returns sessions ID of the current user process. The acronym SPID comes from the name of its earlier version, Server Process ID.

To know which sessions are running currently, run the following command:

SELECT @@SPID
GO

In our case, we got SPID 57, which means the session that is running this command has ID of 57.

Now, let us open another session and run the same command. Here we get different IDs for different sessions.

In our case, we got SPID 61. Please note here that this ID may or may not be sequential.

In session with SPID 61, we will run any query. In session with SPID 57, we will see which query was run in session with SPID 61.

Let us run a simple SELECT statement in session with SPID 61 and in session with SPID 57 run the following command.

DBCC INPUTBUFFER(61)
GO

Now, here in DBCC command we have passed the SPID of previous session; we will see the text below. The following image illustrates that we get the latest run query in our input buffer.


There are several ways to find out what is the latest run query from system table sys.sysprocesses.

DECLARE @sqltext VARBINARY(128)
SELECT @sqltext = sql_handle
FROM sys.sysprocesses
WHERE spid = 61
SELECT TEXT
FROM
sys.dm_exec_sql_text(@sqltext)
GO

The following image portrays that we get the latest run query in our input buffer.


Please note that in any session there may be multiple running queries, but the buffer only saves the last query and that is what we will be able to retrieve.

There is one more way to achieve the same thing – using function fn_get_sql

DECLARE @sqltext VARBINARY(128)
SELECT @sqltext = sql_handle
FROM sys.sysprocesses
WHERE spid = 61
SELECT TEXT
FROM
::fn_get_sql(@sqltext)
GO


All the three methods are same but I always prefer method 2 where I have used sys.sysprocesses.

Today, we have explored a very simple topic. Let me know if you find it useful.

Reference : Pinal Dave (http://blog.sqlauthority.com)

SQL SERVER – Performance Counters from System Views – By Kevin Mckenna

I just love social media and all the new concepts of Web 2.0. There are bloggers who are overwhelmed by the new concepts of technology and are not able to keep pace with it. But I like taking such challenges. Twitter has acquired tremendous popularity nowadays and just like everybody else I am also fond of this latest vogue. You can follow me at Twitter here. Through twitter I am getting to meet people like me and it’s a great experience interacting with them. I met SQL and .NET expert Kevin Mckenna on twitter itself.

Kevin is originally from Liverpool, England, and moved to the US in December 2005. He is a DBA for a large warehousing and logistics company based in the US. He has been developing software with SQL backends for approximately 6-7 years, and has been administrating SQL and Oracle databases for the past 4 years.

He is married and has 2 children.  He is a huge football (soccer for the Americans) fan, and when he is not working, he likes spending his time either reading or playing on twitter.

He has recently sent me a very interesting note on Performance Counters from System Views. I really enjoyed reading it and with his permission I am publishing the content here. Let me have your opinion on this.

Many of you are not aware of this fact that access to performance information is readily available in SQL Server and that too without querying performance counters using a custom application or via perfmon. Till now, this fact has remained undisclosed but through this post I would like to explain you can easily access SQL Server performance counter information.

Without putting much effort you will come across the system view sys.dm_os_performance_counters. As the name suggests, this provides you easy access to the SQL Server performance counter information that is passed on to perfmon, but you can get at it via tsql.

You can start with a few simple steps:

SELECT* FROM sys.dm_os_performance_counters

This returns 701 rows of data on the test machine, with information from Buffer Manager, Buffer Partition, Buffer Node, General Statistics, Locks, and so forth.

I’ll try to make you all understand by making it a bit more simple. Here, we will concentrate on Buffer Manager.

Please note that if you have an instance name, the object name will be MSSQLlt;instance name>: instead of SQLServer:

The next step is

SELECT* FROM sys.dm_os_performance_counters WHERE OBJECT_NAME = 'SQLServer:Buffer Manager'

The following screen will be displayed.

XX

As you all can notice, what is displayed above via tsql is similar to what is available via perfmon

Let’s take a look at the columns returned:

field name data type Description
object_name nchar(128) Category to which this counter belongs
counter_name nchar(128) Name of the counter
instance_name nchar(128) Name of the specific instance of the counter. Often contains the database name
cntr_value bigint Current value of the counter
cntr_type int Type of counter as defined by the Windows performance architecture

Now, if you all are wondering what can be done with this information then let me tell you that you have a few things options. We can create a job that will sample a particular value on a timed basis and add it to a table, and view an average value from it. Another option is to just take a glance at it for peace of mind!

One of the most useful things we could derive from this however is trend information.  For example, let’s chart the number of Active Transactions during the work day.

We will start with creating a table, as given below.

CREATE TABLE ActiveTrans_sqlGenus (
obj_name NCHAR(128),
counter_name NCHAR(128),
instance_name NCHAR(128),
cntr_value bigint,
cntr_type INT,
datestamp datetime
)

We can then fill up this table on a timed basis:

INSERT INTO ActiveTrans_sqlGenus
SELECT
OBJECT_NAME, counter_name, instance_name, cntr_value,
cntr_type, GETDATE()
FROM
sys.dm_os_performance_counters
WHERE
OBJECT_NAME = 'SQLServer:Databases'
ANDcounter_name = 'Active Transactions'
ANDinstance_name = 'sqlGenus'

Here, let’s assume that we are inserting into this table on a consistent basis. We can then issue the following command:

SELECT* FROM ActiveTrans_sqlGenus
WHERE datestamp BETWEEN '06/02/2009 09:00' AND '06/02/2009 17:00'

After that, we can retrieve all the entries between 9am and 5pm, our fictitious work day.

We could manipulate this data even further, averaging out the values, pulling the MAX and MIN and so on.

Obviously, this is a very simple example, and certainly not the best way to store this information over a period of time. However, with some digging into just what you need, you can provide access to your SQL Server performance in a remarkably simple manner.

The biggest disappointment in obtaining this information from SQL Server’s system views is that it only provides SQL Server information, so we do not receive information like Processor, Network and Disk information.  These values still need to be pulled via Performance Counters.  But despite this negative aspect, this view will provide ample usable information to keep your database in an excellent shape.

You can find more information on this system view from MSDN:

http://msdn.microsoft.com/en-us/library/ms187743(SQL.90).aspx

Reference : Pinal Dave (http://blog.SQLAuthority.com)

SQL SERVER – List All Objects Created on All Filegroups in Database

When I pen down any article I always keep my readers in my mind. With every topic of SQL server I cover, I try to bring readers closer to this technology. So, whenever I receive follow up questions from my readers I am exhilarated! Sometime back I had covered a topic – SQL SERVER – Create Multiple Filegroup For Single Database, for which I received a number of follow up questions. In this post I would like to discuss on a question from one of the readers Joginder “Jogi” Padiyala.

“How can I find which object belongs to which filegroup. Is there any way to know this?”

Well, finding out which object belongs to which table is very simple.
Let us first create a database having multiple filegroups.

/* Create Database
Please note that there are two Filegroups for newly created datbase.
MDF - Primary and LDF on Secondary */
CREATE DATABASE [FGTest] ON  PRIMARY
( NAME = N'FGTest',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\FGTest.mdf' ,
SIZE = 3072KB , FILEGROWTH = 1024KB ),
FILEGROUP [Secondary]
( NAME = N'FGTest_2',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\FGTest_2.ndf' ,
SIZE = 3072KB , FILEGROWTH = 1024KB )
LOG ON
( NAME = N'FGTest_log',
FILENAME = N'C:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\FGTest_log.ldf' ,
SIZE = 1024KB , FILEGROWTH = 10%)
GO

Now create a table on primary filegroup.

/* Create New table on Primary Filgroup */
USE [FGTest]
GO
CREATE TABLE [dbo].[TestTable](
[ID] [int] NOT NULL,
[Col1] [varchar](50) NOT NULL,
[Col2] [varchar](50) NOT NULL,
CONSTRAINT [PK_TestTable] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
)
ON [PRIMARY]
GO

Next, create non-clustered index on secondary filegroup.

/* Create Non Clustered Index on Secondary FileGroup */
CREATE NONCLUSTERED INDEX [IX_TestTable_Second] ON [dbo].[TestTable]
(
[Col1] ASC
) ON [Secondary]
GO

After that, we will run the following T-SQL and determine where all the objects are located on filegroup. We have already created a non-clustered index on our table. Now, non-clustered table creates its own table, which consists of pointers to clustered index. For the same reason, we will search with additional condition of object type, which will list only user created tables. Non- clustered table should be part of user created table group.

/* Get Details of Object on different filegroup
Finding User Created Tables*/
SELECT o.[name], o.[type], i.[name], i.[index_id], f.[name]
FROM sys.indexes i
INNER JOIN sys.filegroups f
ON i.data_space_id = f.data_space_id
INNER JOIN sys.all_objects o
ON i.[object_id] = o.[object_id]
WHERE i.data_space_id = f.data_space_id
AND o.type = 'U' -- User Created Tables
GO

Let us observe the same query again with different WHERE condition. Here we are retrieving everything that is on secondary filegroup. It is very easy to identify filegroup name and data by just selecting everything from system table sys.filegroups.

/* Get Detail about Filegroups */
SELECT *
FROM sys.filegroups
GO

In our case, secondary filegroup has data_space_id as 2. Now, we will run the following query and figure out which objects are located on filegroup 2.

/* Get Details of Object on different filegroup
Finding Objects on Specific Filegroup*/
SELECT o.[name], o.[type], i.[name], i.[index_id], f.[name]
FROM sys.indexes i
INNER JOIN sys.filegroups f
ON i.data_space_id = f.data_space_id
INNER JOIN sys.all_objects o
ON i.[object_id] = o.[object_id]
WHERE i.data_space_id = f.data_space_id
AND i.data_space_id = 2 -- Filegroup
GO

I hope this answers Jogi’s question and is helpful for those who were curious to know the answer to this topic.

Reference : Pinal Dave (http://blog.SQLAuthority.com)

SQL SERVER – List All the Tables for All Databases Using System Tables

Today we will go over very simple script which will list all the tables for all the database.

sp_msforeachdb 'select "?" AS db, * from [?].sys.tables'

Update: Based on comments received below I have updated this article. Thank you to all the readers. This is good example where something small like this have good participation from readers.

Reference : Pinal Dave (http://www.SQLAuthority.com)

SQL SERVER – Interesting Observation of DMV of Active Transactions and DMV of Current Transactions

This post is about a riveting observation I made a few days back. While playing with transactions I came across two DMVs  that are associated with Transactions.

1) sys.dm_tran_active_transactions – Returns information about transactions for the instance of SQL Server.

2) sys.dm_tran_current_transaction – Returns a single row that displays the state information of the transaction in the current session.

Now, what really interests me is the following observation. These two DMVs , in actual fact, display the distinction between active transactions and current transactions. Current transaction can be active transaction at the time of execution, but not all active transactions are current transactions for current transactions DMV.

Let us take a look at an example where first we will run both these DMVs together in a single transaction and then run them separately.   We will notice that in the former case (i.e., when they are run in a single transaction) both of them give same transaction ID in result. While in the latter case (i.e., when they are run separately) they give different transaction IDs in result.

SELECT * FROM sys.dm_tran_active_transactions
SELECT * FROM sys.dm_tran_current_transaction
/* Begin Transation */
BEGIN TRANSACTION
SELECT
* FROM sys.dm_tran_active_transactions
SELECT * FROM sys.dm_tran_current_transaction
COMMIT
/* End Transation */

Let us see the following result image and observe the behaviour we discussed above.

To obtain same transaction ID, both the DMVs should be between BEGIN TRANSACTION and END TRANSACTION. Same transaction ID is preserved between BEGIN and END clause of transaction.

Having said all that, now I am eager to receive answer to this question from my blog readers – In what circumstances do you think this behaviour can be useful?

If possible, please write an article on a real life scenario and send it to me.  I will be vary happy to publish it on this blog.

Reference : Pinal Dave (http://blog.SQLAuthority.com)

SQL SERVER – Reseed Identity of Table – Table Missing Identity Values – Gap in Identity Column

Some time ago I was helping one of my Junior Developers who presented me with an interesting situation. He had a table with Identity Column. Because of some reasons he was compelled to delete few rows from the table. On inserting new rows in the table he noticed that the rows started from the next identity value which created gap in the identity value. His application required all the identities to be in sequence, so this was certainly not a small issue for him.

The solution to this issue regarding gap in identity column is very simple. Let us first take a look at his application’s situation wherein there is missing identity and then we will move on to the solution.

Developers can easily deter the above issue by avoiding gap in sequence of identity column through two additional SQL Tricks of reseeding identity.

We will now see the same example with the solution to the above gap issue. On deleting records, table was reseeded with identity, which was deleted. Download complete SQL Script here.

USE AdventureWorks
GO
/* Create a table with one identity column */
CREATE TABLE TableID (ID INT IDENTITY(1,1), Col VARCHAR(10))
GO
/* Insert 10 records with first value */
INSERT INTO TableID (Col)
VALUES ('First')
GO 10
/* Check the records in table */
SELECT *
FROM TableID
GO
/* Delete last few records */
DELETE
FROM
TableID
WHERE ID IN (8,9,10)
GO
/* Check the records in table */
SELECT *
FROM TableID
GO
/* Get current Max Value and reseed table */
DECLARE @MaxID INT
SELECT
@MaxID = MAX(ID)
FROM TableID
DBCC CHECKIDENT('TableID', RESEED, @MaxID)
GO
/* Insert 10 records with second value */
INSERT INTO TableID (Col)
VALUES ('Second')
GO 5
/* Check the records in table */
SELECT *
FROM TableID
GO
/* Clean Database */
DROP TABLE TableID
GO

I hope is solution is clear to all my readers and they will use it to avoid problems related to gap in identity column. Do send me your feedback on this article and let me know if you all need further explanation.

Reference : Pinal Dave (http://blog.SQLAuthority.com)

SQL SERVER – 2008 – Optimize for Ad hoc Workloads – Advance Performance Optimization

Every batch (T-SQL, SP etc) when ran creates execution plan which is stored in system for re-use. Due to this reason large number of query plans are stored in system. However, there are plenty of plans which are only used once and have never re-used again. One time ran batch plans wastes memory and resources.

SQL Server 2008 has feature of optimizing ad hoc workloads. Before we move to it, let us understand the behavior of SQL Server without optimizing ad hoc workload.

Please run following script for testing. Make sure to not to run whole batch together. Just run each command separately to really see the effect of subject of article.

Download complete script of this article here.

/* Test 0 */
/* Clean Cache and Buffers */
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
GO
USE AdventureWorks
GO
/* Run Adhoc Query First Time */
SELECT * FROM HumanResources.Shift
GO
/* Check if Adhoc query is cached.
It will return one result */
SELECT usecounts, cacheobjtype, objtype, TEXT
FROM
sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
WHERE usecounts > 0 AND
TEXT LIKE '%SELECT * FROM HumanResources.Shift%'
ORDER BY usecounts DESC;
GO

Now let us check result of this script. It is clear from result that when we ran query once it cached its plan in memory. If we never run this again in future or if we have just ran as part of building longer query the cache plan of this query is just waste of memory.

Let us now enable the option of optimizing ad hoc workload. This feature is available in all the versions of SQL Server 2008.

sp_CONFIGURE 'show advanced options',1
RECONFIGURE
GO

sp_CONFIGURE ‘optimize for ad hoc workloads’,1
RECONFIGURE
GO

We will now run the code for Test 1 which is almost same as Test 0. Make sure to clean the cache and buffer before running the query to create real life scenario of live case.

/* Test 1 */
/* Clean Cache and Buffers */
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
GO
USE AdventureWorks
GO
/* Run Adhoc Query First Time */
SELECT * FROM HumanResources.Shift
GO
/* Check if Adhoc query is cached.
It will not return any result */
SELECT usecounts, cacheobjtype, objtype, TEXT
FROM
sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
WHERE usecounts > 0 AND
TEXT LIKE 'SELECT * FROM HumanResources.Shift%'
ORDER BY usecounts DESC;
GO

We can clear see now as we have advance option enabled we do not have query cache planed stored in database.

We are interested to know now that if we run the batch more than 1 time it will cache its execution plan.  With advance option of optimizing ad hoc workload.

/* Test 2 */
/* Clean Cache and Buffers */
DBCC FREEPROCCACHE
DBCC DROPCLEANBUFFERS
GO
/* Run Adhoc Query two  Time */
SELECT * FROM HumanResources.Shift
GO 5
/* Check if Adhoc query is cached.
It will return result with Adhoc Query ran two times*/
SELECT usecounts, cacheobjtype, objtype, TEXT
FROM
sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
WHERE usecounts > 0 AND
TEXT LIKE '%SELECT * FROM HumanResources.Shift%'
ORDER BY usecounts DESC;
GO

From our image it is quite clear that when the batch is ran for more than 1 time it caches its execution plan. This is generic behavior with or without turning on advance option.

This may be very simple to see from the top but if you are using SQL Server 2008 and have millions of ad hoc query running every day you wil realize how important this feature is. This feature improves performance by relieving memory pressure by not storing the single time used compiled plans.

Reference : Pinal Dave (http://blog.sqlauthority.com)

SQL SERVER – Find Current Location of Data and Log File of All the Database

As I am doing lots of experiments on my SQL Server test box, I sometime gets too many files in SQL Server data installation folder – the place where I have all the .mdf and .ldf files are stored. I often go to that folder and clean up all unnecessary files I have left there taking up my hard drive space. I run following query to find out which .mdf and .ldf files are used and delete all other files. If your SQL Server is up and running OS will not let you delete .mdf and .ldf files any way giving you error that file already in use. This list also helps sometime to do documentation of which files are in being used by which database.

SELECT name, physical_name AS current_file_location
FROM sys.master_files

Following is the output of files used by my SQL Server instance.

Reference : Pinal Dave (http://blog.SQLAuthority.com)

SQL SERVER – List All Server Wide Configurations Values

Just a day ago, while working on one of the project, I needed to see what is the two digit year cutoff of my current SQL Server. I did not remember what was the exact syntax to search for the same so I ran following query to list all server wide configurations. While looking at quickly I found out value of two digit year cutoff on line 19th. A small but very important script to save for getting server information.

SELECT *
FROM sys.configurations;

I have ran this command on SQL Server 2008 and few of the information may be different than SQL Server 2005. When I ran this script I got 68 rows in result set.

I would like to know how many rows SQL Server 2005 returns.

Reference : Pinal Dave (http://blog.SQLAuthority.com)

SQL SERVER – 2008 – 2005 – Find Longest Running Query – TSQL – Part 2

Just another day I was playing with my query which I posted earlier SQL SERVER – 2008 – 2005 – Find Longest Running Query – TSQL and I found that I got error devide by zero. I have fixed this error in following query as well I have updated query to return time in millisecond instead of microsecond. Jerry Hung has also posted similar solution in comments of original article.

I strongly suggest to read original article to now more about introduction and learn about DBCC command which clears cache.

SELECT DISTINCT TOP 10
t.
TEXT QueryName,
s.execution_count AS ExecutionCount,
s.max_elapsed_time AS MaxElapsedTime,
ISNULL(s.total_elapsed_time / 1000 / NULLIF(s.execution_count, 0), 0) AS AvgElapsedTime,
s.creation_time AS LogCreatedOn,
ISNULL(s.execution_count / 1000 / NULLIF(DATEDIFF(s, s.creation_time, GETDATE()), 0), 0) AS FrequencyPerSec
FROM sys.dm_exec_query_stats s
CROSS APPLY sys.dm_exec_sql_text( s.sql_handle ) t
ORDER BY s.max_elapsed_time DESC, ExecutionCount DESC
GO

Reference : Pinal Dave (http://blog.SQLAuthority.com)