jump to navigation

Looking into the SQL Server Log October 17, 2012

Posted by fofo in Sql Server, Sql Server 2005, SQL Server 2008, SQL Server 2012.
Tags:
add a comment

In this post I will be looking into the SQL Server Log and how we can use it so we can identify and troubleshoot potential problems.

Recently I asked someone that gave me a call regarding an SQL Server issue, to have a look at the SQL Server Log and he just could not locate it. That is why I decided to write a post for this great tool.

I will show you how to access the SQL Server Log using various ways.

I will be using SQL Server 2012 Developer Edition but the Express edition will suffice .

I connect to the SQL Server instance using SSMS. I log in as sysadmin.In order to access the SQL Server Log I expand the Management node and then the SQL Server Logs node. One can see all the available logs.We have 7 logs in total. The Current and 6 Archived ones.These logs are for the SQL Service Service and not for (e.g) the Agent Service.The Current Log is the log that SQL Server is currently using.

Please have a look at the picture below.

We can use the Log File Viewer to view the contents of the current Log or any archived log.We can filter,search  the log.

Please have a look at the picture below

When you stop and start the SQL Server Service it archives all of the logs.Archive #6 means 6 times ago SQL Server was stopped.

I am going to stop and restart SQL Server Service.What happens now is that the oldest log is deleted and a new one is added. Archive #5 becomes Archive #6.

Please have a look at the picture below.

We can configure the number of archives that SQL Server will have.Select the SQL Server Logs node, right-click on it and select “Configure“. There you can set the maximum number of error log files.

Have a look at the picture below.

We can use the xp_ReadErrorLog stored procedure to read the contents of the SQL Server Log.

In a new query window I type

USE master
GO

EXEC xp_ReadErrorLog

Have a look at the picture below

We can access the SQL Server Log by going to the installation directory of SQL Server. Then I locate the Log folder. Then I open with some sort of  application (Notepad ++) the log I want.

Have a look at the picture below

 

We can use the Event Viewer to have a look at the contents of SQL Server Log.

Have a look at the picture below.

I am sure that you realise that the best way to view the SQL Server Log is the SQL Server Log File Viewer.

 

Hope it helps!!!

Optimising SQL Server for ad hoc workloads August 10, 2012

Posted by fofo in Sql Server, SQL Server 2008, SQL Server 2012.
Tags: , ,
1 comment so far

In this post I will be demonstrating with hands-on examples how to optimise your SQL Server for “ad hoc workloads“. I will be using the view LookIntoPlanCache that I created in this post .Make sure to read this post if you are not familiar with terms like Query Optimiser,execution plans and Plan Cache.

I will be using SQL Server 2012 Developer edition in this post but feel free to use SQL Server 2008/R2 versions.I will be using the AdventureWorks2012 database.You can download it from the Codeplex website.

There are times when the application code (high level code) includes ad-hoc queries/statements and there are no stored procedures in the code when it should.There are many cases when developers do not even use parameters. By that I mean that the developer code is written in a way that does not make use of execution plan reuse. Some people will say “Hey man, I do not care I have enough memory in my SQL Server box”.Well, SQL Server just loves memory and it is the one hardware resource that we must keep an eye on.

It is never a good argument to claim that there is “enough hard disk or memory in my system” so I do not care about fixing things…

Imagine that you have a reused plan in the plan cache and because of ad-hoc queries/workloads that plan is pushed out of the plan cache.That does not help the performance of the system.When you have many plans in the cache that are not reused at all that can lead to procedure cache bloat.In this case you have many entries (execution plans) in the plan cache that are used only one and if this happens far too often good plans (heavily reused plans) are forced out of the plan cache.

There is a setting that can be configured in SQL Server to approach such issues when we have lots of adhoc queries.It is called Optimize for Ad Hoc Workloads and you can enable it by using the system stored procedure sp_configure. By default this setting is off.When enabling this feature you must keep in mind that it will affect newly created plans and not the ones that are already placed in the plan cache.

Let me move on with my hands-on examples.

Connect to an instance of SQL Server. Type (copy paste) the code below.Do not execute anything yet.


USE AdventureWorks2012;
GO

IF OBJECT_ID ( 'Person.uspGetPersons', 'P' ) IS NOT NULL
DROP PROCEDURE Person.uspGetPersons;
GO

CREATE PROCEDURE Person.uspGetPersons
@LastName nvarchar(50),
@FirstName nvarchar(50)
AS

SET NOCOUNT ON;
SELECT FirstName, LastName, Title
FROM Person.Person
WHERE FirstName = @FirstName AND LastName = @LastName;
GO

DBCC FREEPROCCACHE

SELECT * FROM dbo.LookIntoPlanCache

EXEC Person.uspGetPersons N'Miller', N'Dylan'
GO
EXEC Person.uspGetPersons N'Duffy', N'Terry';
GO
EXEC person.uspgetpersons N'Brown', N'Kevin'
GO

SELECT * FROM dbo.LookIntoPlanCache

I execute line 1-2 to make AdventureWorks2012 the current database. Then I will create a simple stored procedure in lines 8-17.In lines 4-6 I just check to see if the stored procedure already exists on the system. Then in line 19 I clear the plan cache and use the LookIntoPlanCache view to see the contents of the plan cache.There will be no contents at this stage.

Then I execute the lines 23-28 .There are 3 calls to the stored procedure.Please note that I have typed the name of the procedure with 3 different ways.

Finally I execute the LookIntoPlanCache view to check the contents of plan cache once more.Have a look at the picture below to see the results I got.

The plan for the stored procedure is compiled, cached and reused.Having typed the stored procedure’s name in a different way does not matter .

In a new query window type (copy paste) the following t-sql code.Do not execute anything yet.


USE AdventureWorks2012
GO

DBCC FREEPROCCACHE

SELECT  *
FROM    [AdventureWorks2012].[Sales].[Currency]
GO
SELECT  *
FROM    [AdventureWorks2012].[Sales].[Currency];
GO

SELECT  *
FROM    [dbo].[LookIntoPlanCache]
GO

DBCC FREEPROCCACHE

SELECT  *
FROM    [AdventureWorks2012].[Sales].[Currency]
SELECT  *
FROM    [AdventureWorks2012].[Sales].[Currency];

SELECT  *
FROM    [dbo].[LookIntoPlanCache]
GO

Execute line 4.Once more I clear the contents of plan cache.Then I execute 2 simple SELECT statements.Please note that I in the second SELECT statement I have added a ‘;’.

Ηave a look at the picture below to see the results returned with the execution of the statements.

You can see that I get 2 execution plans for an identical query.The first thing to note here is that we should try and write T-SQL ad hoc queries in the same way. The second thing is that ad-hoc statements get different treatment compared to stored procedures.

Then in line 17 I clear the cache once more.Then I execute (line 19-22) the two SELECT statements in the same batch.Then I look into the contents of the plan cache using the LookIntoPlanCache view.

Have  a look in the picture below to see what my results are.

It is one entry this time in the plan cache but the plan size is twice the size.

Let’s see now how we can optimise SQL Server for ad-hoc workloads

In a new query window type (copy – paste the following).Do not execute anything yet.


USE AdventureWorks2012
GO

DBCC FREEPROCCACHE

SELECT  *
FROM    [AdventureWorks2012].[Production].[ProductModel]
GO

SELECT  *
FROM    [AdventureWorks2012].[Purchasing].[ShipMethod]
GO

SELECT  *
FROM    [AdventureWorks2012].[Sales].[Currency]
GO

SELECT  *
FROM    [dbo].[LookIntoPlanCache]
GO

sp_configure 'show advanced options', 1;
GO
RECONFIGURE
GO
sp_configure 'optimize for ad hoc workloads', 1;
GO
RECONFIGURE

SELECT  *
FROM    [AdventureWorks2012].[Production].[ProductModel]
GO

SELECT  *
FROM    [AdventureWorks2012].[Purchasing].[ShipMethod]
GO

SELECT  *
FROM    [AdventureWorks2012].[Sales].[Currency]
GO

SELECT  *
FROM    [dbo].[LookIntoPlanCache]
GO

I execute line 1-2 to make AdventureWorks2012 the current database.Then I clear the cache once more and execute three SELECT statements (lines 6-16) (ad-hoc queries).

Then in lines 18-20 I look into the plan cache once more.

Have a look at the picture below to see the results I have got.

Those results were the ones I expected. If most of your workload or even 25-40% percent of your workload is ad-hoc queries you should optimise SQL Server differently.

Execute lines 23-29. That will enable SQL Server to optimise execution plans for ad-hoc queries.Then execute the same 3 SELECT statements (lines 31-41) as before.Finally execute the view (lines 43-45) to look into the contents of plan cache once more.

Have a look at the picture below to see the results I have got.

Instead of a compiled plan I have a Compiled Plan Stub.The size that each of these stubs is 272 bytes. That size  is significantly less (150 times) than the size that the original compiled plans occupied. What will happen if I run again the 3 SELECT statements in lines 31-41? When I execute these lines again along with the view that looks the contents of the plan cache, I get the following results

As you can see now there are no more Compiled Plan Stubs for the 3 SELECT statements but compiled plans that take “full” size in the plan cache.So, when the same query is executed for a second time the full execution plan is generated.

To recap, make sure you write your code using stored procedures and parameterised queries. If you do not have access to the high level code and that code has been written by an “ad-hoc query” enthusiast make sure you optimise SQL Server accordingly,thus to optimise SQL Server for ad-hoc workloads.

Hope it helps!!!!

Looking into the contents of Plan Cache in SQL Server August 9, 2012

Posted by fofo in Sql Server, Sql Server 2005, SQL Server 2008, SQL Server 2012.
Tags: , ,
3 comments

In this post I will be demonstrating with hands-on examples how to look into the contents of Plan Cache.  I will be explaining what the Plan Cache (Procedure Cache) is, the process of query optimization and the generation of execution plans in detail. Then I will use some DMVs to create a custom view that will return the contents of the plan cache.

I will be using SQL Server 2012 Developer edition in this post but feel free to use SQL Server 2005,2008 versions.I will be using the AdventureWorks2012 database.You can download it from the Codeplex website.

Let me talk a bit about query optimisation and T-SQL. T-SQL is declarative by nature. When we write T-SQL statements in a query window in SSMS and execute them,we just say to SQL Server “I want these results back”. We do not provide any details on how the results will be returned.If there was nothing else between our T-SQL code and the SQL Server Database engine, we simply would not get any results back.Luckily for us there is a very important component, the Query Optimizer that generates an imperative plan. By saying imperative I mean detailed. This plan that is called execution plan is what is actually executed by the relational engine.The query optimiser will not look for a perfect plan.It is a cost-based optimiser that must find an efficient plan.The optimiser when deciding upon the execution plan will take in to consideration the type of operations,statistics (must always be up to date),indexes,hardware resources (number of CPUs ,available memory),SQL Server edition,number of active concurrent connections and query hints.

The following steps  take place upon query receival from SQL Server:

  • Parser
  • Algebriser
  • Optimiser
  • Execution plan generation – caching
  • Query execution = execution plan execution

The Parser checks the an incoming query validating it for correct syntax.The query is terminated if a syntax error is detected.On validating a query the parser generates the parse tree.

The Algebriser takes the parse tree and resolves all the names of the different objects and data types.The output of all these verifications and resolutions is a binary set of data called a query processor tree.

Based on the query tree the Optimiser finds the optimal solution to execute the query.

Plans are then cached and reused so you do not have to create a new plan every time a query is executed.That will improve the performance significantly since execution plans are costly in both time and resources.So, the first time a query is executed the plan is created,compiled and placed in the procedure-plan cache. When there are subsequent requests for that query,the query plan will be used.

Connect to an instance of SQL Server. Type (copy paste) the code below and execute it. Make sure you include the execution plan ( CTRL+M )


USE [AdventureWorks2012]

GO

SELECT  Sales.SalesOrderDetail.OrderQty ,
Sales.SalesOrderDetail.SpecialOfferID ,
Sales.SalesOrderDetail.UnitPrice ,
Sales.SalesOrderDetail.UnitPriceDiscount ,
Sales.SalesOrderHeader.Status ,
Sales.SalesOrderHeader.AccountNumber
FROM    Sales.SalesOrderDetail
INNER JOIN Sales.SalesOrderHeader ON Sales.SalesOrderDetail.SalesOrderID = Sales.SalesOrderHeader.SalesOrderID
ORDER BY Sales.SalesOrderDetail.UnitPrice DESC

Ηave a look at the picture below to see the results returned with the execution of the statement above along with the execution plan.

I will not be looking into the various components of this execution plan and what they mean. You can hover over each of these components and get information like IO cost and CPU cost.

Most SQL Server developers and administrators I know, strongly believe that DMVs are the best feature that has been added to SQL Server since 2005.I feel exactly the same way.Please have a look at this post of mine that I talk about new DMVs and DMFs in SQL Server 2008 SP1 and SQL Server 2012.

Wouldn’t it be nice to be able to look into the contents of the cache?We can do that by using various DMVs.

In a new query window type the following.Do not execute anything yet.


USE AdventureWorks2012
GO
--DO NOT USE THIS COMMAND IN A PRODUCTION SYSTEM

DBCC FREEPROCCACHE

SELECT * FROM sys.dm_exec_cached_plans

SELECT * FROM Person.Person

SELECT * FROM sys.dm_exec_cached_plans

select * from sys.dm_exec_query_plan(0x060005003A0E56049009B9FF0100000001000000000000000000000000000000000000000000000000000000);

select * from sys.dm_exec_sql_text(0x060005003A0E56049009B9FF0100000001000000000000000000000000000000000000000000000000000000)

Execute line 1-5 first. I clear the contents of plan cache with the DBCC FREEPROCCACHE command.

Then (in line 7) I use the sys.dm_exec_cached_plans dynamic view that returns a row for each query plan that is cached by SQL Server.

Please have a look in this link for more information about the sys.dm_exec_cached_plans view.

At this time I do not expect to see anything in the plan cache.Then in line 9 I execute a simple SELECT statement..

An execution plan is generated. I run again the sys.dm_exec_cached_plans (line 11) view and I get back a row for this cached plan. I find out the relevant handle.

In my case is “0x060005003A0E56049029B9FF0100000001000000000000000000000000000000000000000000000000000000″

In your case it will be different so make sure you use yours instead.

Now I want to find the actual execution plan.We can use the sys.dm_exec_query_plan dynamic view.This view returns the plan in XML format for the batch specified by the plan handle.

Please have a look at this link for more information about the sys.dm_exec_query_plan view.I need to provide the handle as an input parameter.

I execute line 13 and I get the query plan in XML format for the sql query “Select * from Person.Person”

Then I want to find the SQL statement that created that plan.I will use the sys.dm_exec_sql_text dynamic view.

Please have a look at this link for more information about the sys.dm_exec_sql_text dynamic view.I need to provide the handle as an input parameter.

I execute the statement in line 15.The results I get is something like this

dbid    objectid    number    encrypted    text
5              NULL          NULL                0              SELECT * FROM Person.Person

So I managed to get the handle of the SQL query and then get the execution plan for this query and finally the text for the query itself.

Well that seems like a lot of work and I will demonstrate how to combine all these views into a custom-helper view.

In the same query window type (copy paste) and execute the following.


CREATE FUNCTION ExecPlanAndSqlText2 (@planhandle varbinary (MAX))
RETURNS TABLE
AS
RETURN SELECT EST.text,ECP.objtype,ECP.cacheobjtype,ECP.usecounts,ECP.size_in_bytes,EQP.query_plan FROM sys.dm_exec_sql_text(@planhandle) AS EST CROSS JOIN
sys.dm_exec_query_plan(@planhandle) AS EQP
JOIN sys.dm_exec_cached_plans AS ECP
ON ECP.plan_handle = @planhandle;
GO

SELECT * FROM ExecPlanAndSqlText(0x060005003A0E56049029B9FF0100000001000000000000000000000000000000000000000000000000000000);

I create a helper function first using all the dynamic management views and their relevant columns and then I pass as an input parameter the handle.

When I run the last SELECT statement I get the following results.

As you can see now I have all the information I need in one function.

In the same query window type (copy and paste) the code below.Execute the code


CREATE VIEW LookIntoPlanCache
AS
SELECT  EPAST.*
FROM    sys.dm_exec_cached_plans AS ECP
CROSS APPLY ExecPlanAndSqlText(ECP.plan_handle) AS EPAST

SELECT * FROM LookIntoPlanCache

I create a view (LookIntoPlanCache) that collects all the plan handles and passes them to our user defined function. Finally I execute a simple SELECT to see the contents of the view.

When I do that  I get the following results.

Finally I have the SQL query text,the execution plan and the times this plan was used in one view.

Make sure you use this view to look into the contents of your Plan Cache.It works for every system.

Hope it helps!!!!

Using SQL Server Best Practices Analyzer in SQL Server August 7, 2012

Posted by fofo in Sql Server, Sql Server 2005, SQL Server 2008, SQL Server 2012.
Tags:
1 comment so far

In this rather short post, I would like to talk about a very handy and easy to use tool (SQL Server 2012 Best Practices Analyzer-SBPA) that provides a lot of information about all the SQL Server 2012 components installed on the system and checks if the configurations are setup according to the recommended best practices.This tool is available for previous versions of SQL Server and SQL Server 2012.You can download the SQL Server 2012 version of the tool from this link.

The supported operating systems are Windows 7, Windows Server 2008, Windows Server 2008 R2.

There is a chance that the SBPA will fail during installation. You probably will have to download and install Microsoft Baseline Configuration Analyzer V2.0 first.

After I install the SBPA tool, I launch it (Admin Priveleges).

Have a look at the picture below

Then I click Start Scan.A new window appears.In this window I can specify the instance name of the SQL Server I want to scan and then choose what SQL Server components I want also to analyse. In my case I specified the SQL Server Engine & Setup of my SQL Server Developer 2012 version.

Have a look at the picture below

Then I click Start Scan once more.Then the scanning begins.Upon completion of the scanning by the SBPA 2.0, a report is generated and is categorized into Errors, Warnings and Compliants. Have a look at the picture below

You will be able to see different errors that exist on the SQL Server instance in relation with the rules configured in the Best Practices Analyzer.We can also click the detailed explanation for each error. In my case the error I decided to look into tempdb-wrong configuration error.There is a also a resolution for the error.

Have a look at the picture below

You can expand the Warning section of the report.In my case one of the warnings is that the AdventureWorks2012 database is configured with the Simple Recovery Model.I will have to decide depending on my disaster/recovery requirements if I need to change that setting or not.

Have a look at the picture below

To recap, this tool validates an SQL Server instance against a fixed set of built-in rules that can help us identify common installation and configuration issues.

Hope it helps!!!

Looking into logical query processing in SQL Server August 7, 2012

Posted by fofo in Sql Server, Sql Server 2005, SQL Server 2008, SQL Server 2012.
Tags:
4 comments

A few weeks back, I received an email from a good colleague of mine that was really puzzled with the execution of a rather simple query.Finally he gave up and draw the conclusion that there was some sort of a bug in SQL Server.I tried this query myself and it did not work.The query was pretty simple and I could not see why it was not working,in the first place.The answer to this “strange” behavior of  SQL Server is not strange at all. We write SQL queries using the T-SQL syntax.The way we form a SQL query is not the same way SQL Server logically (internally) executes the query.

Let’s see that with a hands-on example.

I am using the AdventureWorks2012 database.Make sure you visit the CodePlex website and download it.Then attach it (restore it) to your local SQL Server instance.

I will be using SQL Server 2012 Developer Edition but the Express edition will suffice .

I connect to the SQL Server instance.

Type (copy and paste the code below) the code below in a new query window in SSMS. Make sure you review it. At first glance there is nothing wrong.Try to execute the query.


USE AdventureWorks2012
GO

SELECT  [JobTitle] ,
[BirthDate] ,
[MaritalStatus] ,
[Gender] ,
[HireDate] ,
[VacationHours] ,
[SickLeaveHours] ,
( [VacationHours] + [SickLeaveHours] ) AS [TotalLeaveHours]
FROM    [AdventureWorks2012].[HumanResources].[Employee]
WHERE   [TotalLeaveHours] >=70

You will receive an error.

Invalid column name ‘TotalLeaveHours’.

SQL Server executes internally the SQL query with a different logic. It does not follow the order of the statements as they are depicted in the SQL Query.The order of execution is the following

  • FROM
  • ON
  • JOIN
  • WHERE
  • GROUP BY
  • HAVING
  • SELECT
  • DISTINCT
  • ORDER BY
  • TOP

You can see now why my query failed. SELECT is evaluated after the WHERE clause.

One way to visualize what I am explaining, please have  a look (download) this poster.

Let’s rewrite the previous statement.

Execute the code below


USE AdventureWorks2012
GO

SELECT  [JobTitle] ,
[BirthDate] ,
[MaritalStatus] ,
[Gender] ,
[HireDate] ,
[VacationHours] ,
[SickLeaveHours] ,
( [VacationHours] + [SickLeaveHours] ) AS [TotalLeaveHours]
FROM    [AdventureWorks2012].[HumanResources].[Employee]
ORDER BY [TotalLeaveHours] DESC

You can see now why my query succeeds. ORDER BY is evaluated after the SELECT clause.

Another excellent article on the subject is this one (greek audience only :P).

I am big fan of LINQ to SQL and Entity Framework. I am sure you have written at least one query using the LINQ syntax.Have a look at the ( snippet )code below

var companies = from comp in ctx.Companies
                                   where comp.CompanyName.StartsWith(“Ad”)
                                   orderby comp.CompanyName
                                   select new { comp.CompanyID, comp.CompanyName };

I am sure you can see the similarities between LINQ query syntax and how SQL Server processes a query internally. So if you think that LINQ syntax is “strange” you know now why we write the LINQ queries the way we do.
Hope it helps!!!

Follow

Get every new post delivered to your Inbox.

Join 1,165 other followers