Archive

Archive for the ‘Sql Server’ Category

Wither ‘Go’

September 28, 2009 Leave a comment

Wow, it’s been another time and a bit since my last post. Still here, still banging my head against the proverbial wall…

Came across this Oddness today.

I had the following script segment:

Code Snippet
If Exists (
    Select    1
    From    sys.tables
    Where    Object_Id = Object_Id('Security.Dictionary')
  )
  
  Drop Table [Security].Dictionary;

Create Table [Security].Dictionary
(
         Id                        Int Identity(1, 1) Not Null
        ,HashValue                 Int Not Null
        ,ItemType                  TinyInt Null
        ,TextData                  NVarChar(MAX)
);
    
Alter Table [Security].Dictionary With NoCheck
    Add Constraint PK_Dictionary Primary Key NonClustered
        (
             HashValue
        )
      With (
         FillFactor = 50
        ,Online = On
        ,Pad_Index = On
        ,Allow_Row_Locks = On
        ,Allow_Page_Locks = Off
        );

I needed to Add ItemType to the clustered key, so I dutifully made it a Not Null and tried again.

Code Snippet
If Exists (
    Select    1
    From    sys.tables
    Where    Object_Id = Object_Id('Security.Dictionary')
  )
  
  Drop Table [Security].Dictionary;

Create Table [Security].Dictionary
(
         Id                        Int Identity(1, 1) Not Null
        ,HashValue                 Int Not Null
        ,ItemType                  TinyInt Not Null
        ,TextData                  NVarChar(MAX)
);
    
Alter Table [Security].Dictionary With NoCheck
    Add Constraint PK_Dictionary Primary Key NonClustered
        (
             HashValue
            ,ItemType
        )
      With (
         FillFactor = 50
        ,Online = On
        ,Pad_Index = On
        ,Allow_Row_Locks = On
        ,Allow_Page_Locks = Off
        );

Imagine my puzzlement when I received the following error:

Msg 8111, Level 16, State 1, Line 12
Cannot define PRIMARY KEY constraint on nullable column in table ‘Dictionary’.
Msg 1750, Level 16, State 0, Line 12
Could not create constraint. See previous errors.

This threw me for a loop since ItemType was quite clearly Not Null (Line 9). So I ran each segment in turn using Select and F5 and was even more non-plussed when each segment ran fine. I then ran the script again and once more, it ran without failure. With my trusty imaginary ‘WTF?’ Red Fez hat firmly planted on my noggin, I attempted to recreate the situation and low and behold I found that adding a Go batch separator thus separating the Create Table And the Alter Table made all the difference for the first run through:

Code Snippet
If Exists (
    Select    1
    From    sys.tables
    Where    Object_Id = Object_Id('Security.Dictionary')
  )
  
  Drop Table [Security].Dictionary;

Create Table [Security].Dictionary
(
         Id                        Int Identity(1, 1) Not Null
        ,HashValue                 Int Not Null
        ,ItemType                  TinyInt Not Null
        ,TextData                  NVarChar(MAX)
);

Go

Alter Table [Security].Dictionary With NoCheck
    Add Constraint PK_Dictionary Primary Key NonClustered
        (
             HashValue
            ,ItemType
        )
      With (
         FillFactor = 50
        ,Online = On
        ,Pad_Index = On
        ,Allow_Row_Locks = On
        ,Allow_Page_Locks = Off
        );

If I were to guess what just happend here I’d say that I think the Alter Table sans the Go seperator was parsed based off the previous table specification, however embedding the Go seperator forced the parser to re-evaluate the new layout. Or something…

Sql Server 2008, SP1

Categories: Odd, Sql Server

There can be only 1

Our resident architect came over today and posed me this little puzzler – he wanted a query that would return if 1 row or nothing based of a certain criteria. In other words if two rows met the criteria he wanted nothing pulled back.

A strange request I’ll grant ye, and one that took me some time to bang my head against, however the answer was pretty neat:

Code Snippet
Create Schema Test;
Go
Create Table Test.Only1RowTest
    (
             Key1                Int
            ,Key2                Int
    )
Go
Insert Into Test.Only1RowTest
    Values   (1,1)
            ,(2,2)
            ,(3,3)
            ,(1,2);

– Demonstrate pulling back no rows because 2 rows meet the criteria

With Cte As (
    Select     Top(2) *
      From     Test.Only1RowTest
      Where  Key1 = 1
      )
      
      Select Cte.*
        From Cte
            Inner Join
                (
                    Select    Count(*) As c
                      From    Cte
                ) As CteC
                    On CteC.c = 1;

– Expand the criteria to further limit the row count and we get 1

With Cte As (
    Select    Top(2) *
      From    Test.Only1RowTest
      Where Key1 = 1
        And Key2 = 1
      )
      
      Select Cte.*
      From     Cte
        Inner Join
            (
                Select    Count(*) As c
                  From Cte
            ) As CteC
                On CteC.c = 1;

To break it down further, we create a common table expression and start off on the basis that returning 2 rows is just as bad as returning 2 million, so we limit the rows pulled back with a Top(2), we then bring back the results of the CTE as long as the # of rows returned =1 (no-one ever said an Inner Join had to join two columns together).

Sql Server 2008 Build 10.0.1798.0 (RTM-CU4)

Categories: Sql Server

Fritzin’ with the Guv’nor

It’s a feature I for one have been screaming desperate for – the Sql Server 2008 Resource Governor – the means to finally provide a T-SQL based process to throttle how much CPU and Memory certain activities can utilize.

For me I need to it because I hate bringing the server down every time I need to run a fragmentation scan; with a 1.5TB DB on an undersized server, I need most of the resources dedicated to keeping the application happy. However I don’t want anything I do to kill the performance – and likewise I don’t want some schmuck running a badly written adhoc query in Management Studio preventing me from doing my job.

And this is where the Resource Governor comes in to play by offering Resource Pools and Work Groups. Each Pool can be though of almost as an individual Sql Server instance operating on shared data.And to a certain extent this is true, however the pools do share some meta-data which I’ll explain later.

image

Out of the box there are 2 Pools and 2 Groups pre-defined – One called Internal which is static and immutable and where Sql Server processes its internal processes, the other called Default which contains a undeletable but otherwise configurable group, also called Default.

In this configuration and user processing is performed in the Default Pool and all internal processing is carried on in the Internal pool – even to the detriment of any other pool out there. This allows Sql Server to continue processing without other pools pressurizing it and as a result, no user processes are allowed in the Internal pool.

Pools are the first level of control and are used to define the minimum and maximum CPU and memory workloads running inside them are ever allowed to use. Work Groups take it to the next level and allow not only a finer level of control but also the ability to move them between pools. Groups, for example can be defined to specify how much of a % they take out of the pool, the priority level and also the MAXDOP setting. Finally, users are associated with pools via use of a Classification Function.

However, it is important to understand that the Resource Governor really only limits resources when there is a pinch point in total resource availability. Running identical queries on an otherwise silent server, one in a High priority pool and the other in a low one will have no obvious effect. However once the server is being pushed the resource governor provides a nice guarantee of resource availability to those sessions that require it and a good throttle to those that don’t.

image In the examples that follows I use two new pools and one associated work group in each pool. One pool will be used to process high priority tasks and the other low priority. Two users will be created, one will be assigned to the High Work Group, the other the Low Work Group.

(NB: for brevities sake the users I’m creating here do not have any passwords; it goes without saying that this is exceptionally bad form and should not be practiced on any server that you value data, schema or any other objects on!)

Create Resource Pool Low With ( Min_CPU_Percent = 0, Max_CPU_Percent = 30 ) ;Create Resource Pool High With ( Min_CPU_Percent = 60, Max_CPU_Percent = 100 ) ;

Create Workload Group Low With ( Importance = Low ) Using Low;Create Workload Group High With ( Importance = High, Request_Max_Memory_Grant_Percent = 100 ) Using High;

Alter Resource Governor Reconfigure;

Use AdventureWorks2008;Create Login LowUser With Password=N'', Default_Database=AdventureWorks2008, Check_Expiration=Off, Check_Policy=Off;Create User LowUser For Login LowUser;Exec sp_AddRoleMember N'db_owner', N'LowUser'Create Login HighUser With Password=N'', Default_Database=AdventureWorks2008, Check_Expiration=Off, Check_Policy=Off;Create User HighUser For Login HighUser;Exec sp_AddRoleMember N'db_owner', N'HighUser'

As can be seen, the Low pool is only given 30% of CPU to play with – however this is not a true maximum but for these examples it’s good enough. I’ll explain these figures and how they interact later. Notice also the statement reconfiguring the governor; no changes are ever made until this Reconfiguration has taken place.

Next we need to be ability associate users with workgroups – something that’s facilitated with a Scalar-based classification function. This function can make its decision based on numerous factors, including (but not limited to) session user name, host name and application name. For now we’ll keep it very simple and base it off the user name.

Use master;Go

Create Function    dbo.ResourceGovernorWorkgroupClassifier()   Returns    sysname   With SchemaBindingAs   Begin

       Declare         @WorkgroupName                SysName            = 'default'       ;

       If SUser_Name() = 'LowUser'           Set @WorkgroupName = 'Low';

       If SUser_Name() = 'HighUser'           Set @WorkgroupName = 'High';

       Return @WorkGroupName;

   EndGo

Alter Resource Governor With ( Classifier_Function = dbo.ResourceGovernorWorkgroupClassifier);


This really simple classifier function simply assumes user will be allocated to the “default” work group unless either LowUser or HighUser logs in, at which point they’ll be allocated to the relevant Work Groups. This function will now be executed for every subsequent user login – so as a result you’ll always want to keep this function as short and sweet as possible (a reconfiguration is not required for this to take a effect).

So, now we’re ready to demonstrate the Resource Governor in action. Now, remember earlier I mentioned the governor only kicks in when there’s a pressure point? This being the case we need a method of creating an artificial resource hog – something that will thrash the DB nicely. The AdventureWorks2008.Sales.SalesOrderDetail table is a nice enough size for us to run some hairy and not so hairy queries against. Caveat emptor – the queries themselves are totally nonsensical – they are written to provide example load usage only.

Run the following in a session as a ‘normal’ user (sa, your Windows account or anything else):

Select COUNT(*)From Sales.SalesOrderDetail As Sod1Inner Join Sales.SalesOrderDetail As Sod2 On Sod1.SalesOrderDetailID != Sod2.SalesOrderDetailID;

Even on a relatively beefy PC this should begin to the thrash the living bejezus out of Sql Server and take the CPU close to 100%. Now connect a session as LowUser and run:

Set Statistics Time On;Select COUNT(*)From Sales.SalesOrderDetail As Sod1Inner Join Sales.SalesOrderDetail As Sod2 On Sod1.SalesOrderDetailID != Sod2.SalesOrderDetailID;And Sod1.SalesOrderID < 43800;

Finally, connect a third session as HighUser and run the same query. If all goes well, this last query should finish relatively quickly (for me it takes between 10 and 15 seconds), however the second query (running as LowUser) should take considerably longer (for me it was a shade over 2 minutes). If all is well the first control query should still be running (and still consuming the very soul out of your CPUs). If I were you I’d kill this initial query off now if it’s still going. It’ll do nothing for the performance of your PC!

image

To see the true affect of the Governor, one simply has to compare the results produced by the time statistics. Whilst the actual CPU used by both queries is broadly the same, the elapsed time for low user is almost exponentially higher. This is directly the effect of running under the pool where the maximum CPU is capped at 30%. The figures here also show running the same queries under no stress to show that without putting the server under load, the governor makes very little difference.

Finally for this post (and don’t worry – there will be a follow-up posting detailing some of the more intricate aspects of the Resource Governor) we’ll demonstrate another nice feature – moving Work Groups to different pools.

image

Moving a work group can be performed a any time, however the effect will only be felt with a Reconfiguration. Executing the following will result in an error:

Alter Workload Group Low Using High;Alter Resource Governor Reconfigure;

Msg 10904, Level 16, State 2, Line 2

Resource governor configuration failed. There are active sessions in workload groups being dropped or moved to different resource pools. Disconnect all active sessions in the affected workload groups and try again.


What is needed here is to disconnect any sessions currently utilizing the Low Work Group. We can utilize the following query to find out which sessions are affected and kill them off by hand (and don’t forget to run the reconfiguration!)

Select    Session_Id, Status From    sys.dm_exec_sessions As S       Inner Join sys.dm_resource_governor_workload_groups As G           On S.group_id = G.group_id Where     G.name = 'Low';

Now repeat the experiment by starting the Stress query first followed by the Low and finally the High.

image

As you can see the elapsed time is significantly less when the Work Group is moved into the High Resource Pool. The reason for the discrepancy between the two is down to the configuration of the two groups; the High Group is set at a High Priority and allowed to utilize all of the RAM the pool has been allocated, whereas the Low Work Group is limited to being able to grab a maximum of 25% of memory from the pool (the default) and a relative importance setting of Low.

That’s all for now – keep tuned for part two where we delve deeper into the mind of the guv’nor.

Sql Server 2008 Build 10.0.1600.22 (RTM)

Sql Server 2008 Management Studio ‘pings’

Not had a chance to do a full investigation on this, however I did have a situation the other day where, despite me killing off all query connections and all connected Object Explorer windows, I still found that the 2008 Management Studio would ping one of my servers every three minutes or so. This only transpired because it was using an old cached Sql Server DB Principal password (I’d just changed it) and ChangeDirector was constantly wibbling about it.

Killing off MS altogether stopped the issue dead in its tracks. If I get a chance to I might go back to finding out what the real story was, but a little puzzler it was at the time.

Sql Server 2008 Build 10.0.1600.22 (RTM)

Clustering Quest ChangeDirector

February 23, 2009 Leave a comment

Whilst Quest declare that ChangeDirector 2.1 supports Clustering I’m not convinced it goes the whole hog. However your intrepid Random-Thunker has gone through the small number of extra steps required to make it so.

First off if you’ve not already done so, install ChangeDirector onto both nodes using the normal methods and validate that it works just fine by moving the Sql Cluster service through each node. Validate with ChangeDirector that the agent is running correctly.

Now shut the Service down and modify the configuration file ON EACH NODE. For me the configuration file was on C:\Program Files\Quest Software\Quest Change Director for SQL Server\[SqlClusterName]\QuestChangeTrackerAgent.exe.config. Update this to point the Trace and Log folders on one of the shared drives used by the cluster. I used the drive dedicated to normally storing dumps and backups onto which kept it away from affecting the other drives in the SAN whilst still making it always available to the cluster.

Fire up the service again on the active node to verify all is well still then shut it down again and this time change it’s startup type from Automatic to Manual.

Create a new Generic Service Cluster Resource in the Cluster Administrator. The Service name to use is Quest Change Tracker Agent. I added a couple of dependencies for both the drive I was using to store the logs and traces on and also Sql Server itself. In addition I elected to change the settings to not affect the group; this way if it should so something daft it wasn’t going to take the whole cluster with it. For me the continuous availability of the cluster trumps ChangeDirector – your individual mileage may, as they oft say, vary. And oh, there are no registry keys to replicate so you don’t need to worry on that front.

Now you should be able to fire up the resource in the Cluster Administrator and off you go. For a final test move the Sql Cluster through each node verifying that it’s seen by ChangeDirector at all times.

Windows 2003, ChangeDirector 2.1.0.87

Unverifiable Passwords with Sql Configuration Manager

February 23, 2009 Leave a comment

This was an odd one and much akin to a previous recent incident I’d had with the configuration manager (albeit this time on a totally different server); this last weekend we had one of our regular ‘let’s all work through the night’ maintenance windows. Such events are never fun to do but made even worse when the strangest of things happen.

This weekend it was the turn of the Sql Configuration Manager and it’s stubborn refusal to validate a new account password. No matter how many times I tried it would not take the new password, regardless if I pasted it in or typed it in. Each time I’d see an entry in the Security log telling me the attempt to logon with the credentials had failed.

Given that it was now getting close to 3AM I decided another approach based off the prior experience; I fired up the Services applet and pasted the password directly in there.

Well, would you Adam and Eve it – it only bloody worked.

Don’t have a good reason or explanation for this one other than – WTF?

Still, whatever it takes.

Sql Server 2005 SP2 No CR’s.

Categories: Sql Server, Workarounds

2005 Configuration manager oddness

January 20, 2009 Leave a comment

I was doing a round of mass service account password changes today on one of our development servers and came across this bit of strangeness; despite making several attempts to update the account and password in the Configuration manager the SSIS service refused not only to start up, but also failed to give any indication as to why (the application logs were horribly silent on anything from either SSIS or even the service manager).

So I went into the back door and fired up the Services applet and refreshed the password in there. One message informing me the account had been granted the ‘Logon as a service’ privilege and the service was up.

What beats me is why the configuration manager refused on multiple times to accept the change. Not saying we should all ignore the config manager from now on but I myself will bear this in mind for future weirdness.

And hot on the heels of 2005 SP3 comes…

December 23, 2008 Leave a comment

Cumulative Rollup 1 which essentially comprises CUs’ 10 and 11 for SP2.

In the good old days would MS just release something akin to a SP3a? Ah well..

Service pack 3 is here, CU1 is here.

Categories: Service Packs, Sql Server

Sql Server 2005 SP3 released!

December 18, 2008 Leave a comment

Microsoft have finally released Sql Server 2005 SP3 – how long was that chaps? 1.2 eternities or 1.3? (I lost track after a few lifetimes).

Well, better late than never, least now I don’t need to grab the less supported CRs to get the latest round of fixes.

Categories: Service Packs, Sql Server

Management Studio folders

December 16, 2008 Leave a comment

What MS giveth with one hand they unceremoniously forget to supply with the other; here I’m referring to being able to update the path of the folders used by Management Studio for storing projects etc.

Fortunately it’s an easy fix that, as usual, relies on the registry.

Fire up regedit (or your favorite registry hacker) and move yourself to

HKEY_CURRENT_USER\Software\Microsoft\Microsoft SQL Server\100\Tools\Shell

and update the folder paths there.

Categories: Sql Server
Follow

Get every new post delivered to your Inbox.