Category Archives: Imported from BeyondRelational

These posts are imported from my old blog page: http://beyondrelational.com/modules/2/blogs/77/nakuls-blog.aspx

#0212-SQL Server-Productivity tip-Open Object Explorer from the Query Editor


Most of us (especially those working in close contact with development teams) are generally tasked with multiple roles and responsibilities – the most common combination being that of a database developer and a database administrator. In order to fulfill both responsibilities, I generally have both the query editor and the object explorer open for any server that I am connected to.

In some cases though, I connect to a server to execute a query or two and then find my self in need to access the object explorer.  In such cases, I use a neat functionality hidden in the pop-up menu of the query editor, which I thought would benefit all this week. So, here are the steps.

image
Assume that you are working in the SSMS query editor window.
1. Right-click anywhere in the white space
2. Click on “Open Server in Object Explorer”
image
You can see that the Object Explorer is now up.

There is no need to explicitly go to the Object Explorer and use the “Connect” buttons. Alternatively, you can also use the keyboard shortcut Alt + F8.

Why would you want to use the Object Explorer only when required?

There’s a reason why I don’t prefer to launch object explorer by default for servers I don’t work with regularly – for every feature of the SSMS that one uses, an additional connection is opened with the SQL Server (Read more about this here: http://bit.ly/XE6fZh).

Until we meet next time,

Be courteous. Drive responsibly.

#0211-SQL Server-Restart Recovery-Database Startup Sequence for User databases


In my earlier post (Restart Recovery-Database Startup Sequence), I studied the overall database startup sequence as part of the restart recovery process for databases on a SQL Server instance. The conclusion that I came to was that the restart recovery is a multi-threaded activity and multiple spids are utilized to bring the SQL Server instance online in the shortest possible time frame. The first database to come online is (obviously) the master database followed by the rest of the system databases in sequence (resource, model, tempdb, msdb and Reporting Server related DBs). Finally the user databases are brought online.

The question that now came to my mind was that it is possible for an instance to have multiple user databases. What would be the startup sequence for these user databases under normal conditions?

On my test instance, I have 6 user databases according to this script to identify system v/s user databases:

--Provides a list of user databases
select sdb.database_id,
       sdb.name
from sys.databases sdb 
WHERE CAST((CASE WHEN SUBSTRING(sdb.name,0,14) IN ('master','msdb','model','tempdb','ReportServer$') 
                      THEN 1 
                 ELSE sdb.is_distributor 
            END) AS BIT) = 0

The user databases on my test instance are listed below:

Database Id Database Name
7 AdventureWorks
8 AdventureWorksDW
9 AdventureWorksLT
10 AdventureWorks2008
11 AdventureWorksDW2008
12 AdventureWorksLT2008

To know the sequence in which these databases were brought online as part of the restart recovery sequence, I used the query from my pervious post with a minor modification in that I am filtering the log text:

--Check the sequence logged into the SQL Server Error Log
DECLARE @DatabaseStartupSequence TABLE (LogDate DATETIME, ProcessInfo VARCHAR(10), LogText VARCHAR(50))

INSERT INTO @DatabaseStartupSequence (LogDate, ProcessInfo, LogText)
EXEC sys.sp_readerrorlog 0, 1, 'Starting up database'

SELECT CAST(dss.LogDate AS TIME) AS LogTime, dss.ProcessInfo, dss.LogText
FROM @DatabaseStartupSequence AS dss
WHERE dss.LogText LIKE '%AdventureWorks%'
ORDER BY dss.LogDate ASC
GO

The results are as shown below:

LogTime ProcessInfo LogText
17:41:21 spid24s Starting up database ‘AdventureWorks’.
17:41:21 spid25s Starting up database ‘AdventureWorksDW’.
17:41:21 spid26s Starting up database ‘AdventureWorksLT’.
17:41:21 spid27s Starting up database ‘AdventureWorks2008’.
17:41:21 spid28s Starting up database ‘AdventureWorksDW2008’.
17:41:23 spid24s Starting up database ‘AdventureWorksLT2008’.

Result

Multiple spids are assigned to recover the user databases in order of their database_id. SQL Server started 5 separate processes to recover 5 out of the 6 user database. The 6th database was handled by the first spid that completed it’s work based on whether the scheduler had capacity available.

Database Id Database Name Assigned SPID Remarks
7 AdventureWorks 24  
8 AdventureWorksDW 25  
9 AdventureWorksLT 26  
10 AdventureWorks2008 27  
11 AdventureWorksDW2008 28  
12 AdventureWorksLT2008 24 Rollover, since spid24s would have completed recovery on ‘AdventureWorks’, it was assigned the next database in-line

In conclusion, restart recovery of system databases has a specific sequence that is followed by SQL Server, but when it comes to user databases, the order is governed by the database_id of the database.

This topic is by no means complete. There is a lot more to explore, so, if you have any related observations/questions, please do share them via the blog comments, or send them on my Twitter handle (@nakulv_sql).

Until we meet next time,

Be courteous. Drive responsibly.

#0210-SQL Server-Restart Recovery-Database Startup Sequence


The startup process of any system is a very interesting stage. Ever since I was exposed to the world of computers, I was fascinated with the POST (Power On Self Test) sequence, about which I learnt and explored in detail when I studied Electronics & Communications engineering. SQL Server is a server system on it’s own and therefore, I recently had a yearning for learning about the SQL Server startup sequence.


Now, I know that the SQL Server startup process involves an Undo-Redo phase for rolling forward/backward open transactions in each database, but the questions that kept cropping up in my mind were:



  1. When the SQL Server starts, what is the first database that is made online?
  2. When are user databases made available in the startup sequence?
  3. When is the tempdb available?

In order to answer these questions, I postulated a theory and then tried to collaborate it with practice. The entire experience is documented in this post.


The Theory


When I started learning about SQL Server, I thought that the database_id determines when a database comes online. This would mean that the following DMV would be the only thing tat one needs to be query:

USE master
GO
–Get the database Ids
SELECT sd.database_id, sd.name
FROM sys.databases AS sd
ORDER BY sd.database_id
GO

My test server is a SQL Server 2012 instance with reporting services installed and the AdventureWorks2012 sample database deployed. The result for this test instance is shown below:



































Database Id Database Name Is User Database?
1 master N
2 tempdb N
3 model N
4 msdb N
5 ReportServer$SQL2K12 N
6 ReportServer$SQL2K12TempDB N
7 AdventureWorks2012 Y

The one database that is not listed in the results of this DMV is the resource database.


Going by original hypothesis, the master should be started up first, followed by the resource, tempdb, model, msdb and so on.


The contradiction


Contradicting my thought process mentioned above were some of my pervious observations around tempdb. It is a confirmed point thing that the model database has to be online before the tempdb is made available.



The above contradiction led me to hypothesize that the startup sequence would be similar to master –> resource->msdb –> model –> tempdb –> ReportServer –> ReportServerTempDB –> user databases. It was now time to confirm this line of thought.


The Test


To identify the real order in which databases are brought online, I looked at the SQL Server error log where all startup activity is logged by Microsoft SQL Server. I had referenced this in one of my pervious post related to identification of the startup time of the SQL server. To read the SQL Server error log through T-SQL, we use a system stored procedure sys.sp_readerrorlog (undocumented, to the best of my knowledge).  This system stored procedure takes up to 4 parameters:



  • Error log file to read (0 = Current, 1 = Archive #1, and so on)
  • Log File Type (NULL/1 = SQL Server Error log, 2 = SQL Agent Log)
  • String 1 (first search string)
  • String 2 (string to further refine the search)

We need to read the current file in the SQL Server Error Log, and only need to search for one string – “Starting up”. The call would therefore be similar to the one shown below, where I have captured the results into a table variable which allows us to sort by the log time.

–Check the sequence logged into the SQL Server Error Log
DECLARE @DatabaseStartupSequence TABLE (LogDate DATETIME, ProcessInfo VARCHAR(10), LogText VARCHAR(50))

INSERT INTO @DatabaseStartupSequence (LogDate, ProcessInfo, LogText)
EXEC sys.sp_readerrorlog 0, 1, ‘Starting up database’

SELECT CAST(dss.LogDate AS TIME) AS LogTime, dss.ProcessInfo, dss.LogText
FROM @DatabaseStartupSequence AS dss
ORDER BY dss.LogDate ASC
GO


The results of the query execution are as shown below:







































LogTime ProcessId LogText
15:33:34 spid8s Starting up database ‘master’.
15:34:15 spid9s Starting up database ‘mssqlsystemresource’.
15:34:15 spid17s Starting up database ‘msdb’.
15:34:15 spid18s Starting up database ‘ReportServer$SQL2K12’.
15:34:15 spid20s Starting up database ‘AdventureWorks2012’.
15:34:15 spid19s Starting up database ‘ReportServer$SQL2K12TempDB’.
15:34:19 spid9s Starting up database ‘model’.
15:34:49 spid9s Starting up database ‘tempdb’.

The Result


The above is a very interesting result and tells me that I was not very wrong in my hypothesis. Here’s the interpretation of the log content.



  • We know that recovery is a parallel process – this is confirmed by the fact that we have multiple ProcessIds in the results above
  • The first database is recovered by process Id – 8 and is the master database – without the master database, the entire SQL Server fails to start
  • The next database recovered is by process Id – 9 and is the resource database (“mssqlsystemresource”)

    • This very process goes on to recover, in sequence, the model and then the tempdb database

  • The next process that SQL Server initiated was Id – 17 for recovers the msdb database
  • Process Id – 18 then recovers the ReportServer database followed by Process Id – 19 which recovers the ReportServerTempDB
  • Finally, process Id – 20 recovers the user database – AdventureWorks

The recovery interval (i.e. when the recovery for any database completes) depends on a number of factors and can be studied at: Understanding Recovery Performance in SQL Server.


Conclusion


In conclusion, I could now answer all my questions:



  1. When the SQL Server starts, what is the first database that is made online? Answer: Master
  2. When are user databases made available in the startup sequence? Answer: After all system databases have been recovered
  3. When is the tempdb available? Answer: After the master, resource and model databases are recovered (in that sequence)

I learnt something new today, which is always fun. This topic is by no means complete. There is a lot more to explore, so, if you have any related observations/questions, please do share them via the blog comments, or send them on my Twitter handle (@nakulv_sql).


Until we meet next time,


Be courteous. Drive responsibly.

#0209 – SQL Server-SSMS – Include column headers when copying query results


As part of my work, I often need to copy-paste the results of a query into an Excel sheet for multiple reasons. The purpose of such a requirement could be as simple as having a record of what the data looked like before and after a change I made (as in when doing data cleanup or custom data modification work) to as complex as running an ad-hoc data analysis. Almost all of my production-grade queries use aliases and it would be the same aliases that I would prefer to have as column headers on the Excel sheets for sake of consistency. The easiest way to achieve this is to copy the headers along-with the data from the results tab of the SSMS window.

Traditionally, I would choose the option “Copy with Headers” popup-menu option (or use the equivalent Ctrl+Alt+C keyboard shortcut):

image

However, our memories do fail us sometimes and remembering to use “Copy with Headers” and not the plain “Copy” is error-prone. Hence, I have the following setting turned on in my SSMS options:

image
Go to the Options window using Tools –> Options.
Under Options, navigate to Query Results section.
image
Go to the “Results to Grid” option and check the check-box labeled “Include column headers when copying or saving the results”.

Repeat the process, if required for “Results to Text” output format.

Re-launching the SSMS and attempting to copy (just plain copy) the result set also copies over the column headers to the applications of my choice, including Excel.

So, here are my questions – Do you use this built-in feature of the SSMS? Do you have any others to share with the group?

Until we meet next time,

Be courteous. Drive responsibly.

#0208-SQL Server-SET options-NOEXEC v/s FMTONLY-Does FMTONLY really execute the query/workload?


It’s a great feeling when you, the kind reader, share your feedback on my posts because generally, these provide a lot of learning opportunities for both. In the last couple of weeks, I explored the following SET options:

  1. PARSEONLY
  2. NOEXEC 
  3. FMTONLY (SQL Server 2008 R2 and below)
  4. sp_describe_first_result_set – replacement to FMTONLY (SQL Server 2012 and above)

SET options allow us to change the behaviour of SQL Server for the current session with respect to handling of specific information like date and time values, locking, Query execution, transaction, ISO settings and Statistics. While the SET option for PARSEONLY is quite straight-forward, a confusion may arise between NOEXEC and FMTONLY. Here’s why:

  • NOEXEC – parses a query, produces and adds to the plan cache the execution plan of the query/workload in hand, without executing the query
  • FMTONLY – parses the query, produces the execution plan and executes the query/workload to return the meta-data associated to the query without processing any records

When the FMTONLY option is exercised, the query is actually executed to return the meta-data, but no records are processed. However, this behaviour is not intuitive. Here’s a follow-up question that I received in my post related to FMTONLY.

When you try to execute a query that have side effects (like an INSERT) with FMTONLY ON, you can easily check that the row is NOT inserted. I just tried this on SQL 2008 (not R2). Can you confirm this? If this is true, how is FMTONLY different from NOEXEC?

Demo

In order to answer this question, I have come up with the following demo. The demo simply involves using the NOEXEC and FMTONLY options on a query around a non-existent table – MyTable. Since the table is non-existent, I should encounter a run-time error the moment the query is executed. The script below does the following:

  • Sets the system to a base state where both NOEXEC and FMTONLY are set to OFF
  • A query around the non-existent table – MyTable is executed with the NOEXEC option turned ON
  • The same query is re-executed with the FMTONLY option turned ON
USE tempdb
GO

--Base State
SET NOEXEC OFF
GO
SET FMTONLY OFF
GO
PRINT '00. Setting base state - both NOEXEC and FMTONLY are now OFF.'
GO

PRINT '01. Now checking whether MyTest already exists or not.'
PRINT '    If the ObjectId is not printed after this line, object is non-existent.'
PRINT OBJECT_ID('MyTest')


PRINT '02. Running with NOEXEC ON now...'
--Set the NOEXEC option to ON, telling the database engine
--to Parse and Compile the query, but not execute it
SET NOEXEC ON
GO

--Test workload.
--NOTE: The MyTest table does not exist!
SELECT Id,
       MyValue
FROM MyTest

SET NOEXEC OFF
GO

PRINT '03. NOEXEC is now OFF.'
PRINT '04. Running with FMTONLY ON now...'

--Set the FMTONLY option to ON, telling the database engine
--to Parse, Compile, Execute the query, 
--and return meta-data, but not return any records
SET FMTONLY ON
GO

--Test workload.
--NOTE: The MyTest table does not exist!
SELECT Id,
       MyValue
FROM MyTest

SET FMTONLY OFF
GO

PRINT '05. FMTONLY is now OFF.'
GO

Running the entire script against my test SQL Server instance (tested on SQL 2008, SQL 2008 R2 and SQL 2012) yields the following results.

00. Setting base state – both NOEXEC and FMTONLY are now OFF.

01. Now checking whether MyTest already exists or not.

    If the ObjectId is not printed after this line, object is non-existent.

 
02. Running with NOEXEC ON now…

03. NOEXEC is now OFF.

04. Running with FMTONLY ON now…

Msg 208, Level 16, State 1, Line 4

Invalid object name ‘MyTest’.

Conclusion

The above was a very simple demo, with a very clear output which helped me arrive at the following conclusion:

  • Although the table is non-existent (as confirmed by the OBJECT_ID() call in step #01), NOEXEC did not return any errors
    • This indicates that NOEXEC did not actually “submit” the query to the query engine for execution
  • The  attempt with the FMTONLY option set to ON however, did return a runtime error and that resulted in batch termination (no statements after that point were executed)
    • This indicates that FMTONLY did execute the query and as a result, encountered the error

Now, because the attempt with FMTONLY resulted in a batch termination, allow me to return my server back to the base state.

(To know more about SQL Server error states, please visit Pinal Dave, a.k.a. SQLAuthority’s [B|T] post: Introduction to SQL Error Actions – A Primer)

--Base State
SET NOEXEC OFF
GO
SET FMTONLY OFF
GO
PRINT '00. Setting base state - both NOEXEC and FMTONLY are now OFF.'
GO

I trust that the above demo answers all questions that one may have regarding the differences between NOEXEC and FMTONLY. If you have any other questions, please feel free to send them over to me. I will be glad to help!

Until we meet next time,

Be courteous. Drive responsibly.