Showing posts with label SQL Server. Show all posts
Showing posts with label SQL Server. Show all posts

Thursday, February 3, 2011

Time’s Makin’ Changes

Some History

Almost exactly 7 years I ago my wife and I decided to apply to be missionaries with New Tribes Mission.  We decided at that time to pursue what NTM calls Associate missionaries which allowed us to serve with NTM for 1-4 years.  In May of 2004 our applications were accepted and we began the road to service with NTM at the US Headquarters in Sanford, FL.  Because NTM is a faith-based, non-profit organization our journey began by contacting and visiting churches in New England to raise the prayer and financial support that we would need to serve with NTM.  We finally made it to the point where we could move to Sanford in June 2007 and I started my ministry with NTM July 2nd.  All that to say that our commitment with NTM is ending this summer.  We did have the option of continuing on, but we have chosen not to pursue that option.

So What’s that Mean?

I’m looking for work starting in July of this year.  My preference is to work in northern New England (New Hampshire or southern/central Maine) or central Florida (Orlando area).  So, if you hear of anything feel free to contact me.

What Else Has Changed?

I’ve learned that I’m quite a different person than when I moved to Florida.  I’ve grown spiritually, personally, and professionally.  I’ll keep this post about some professional growth.  When I moved to Florida and began serving with NTM, I thought I knew a lot about SQL Server, but then I met Andy Warren (Blog|Twitter) and became involved in the SQL Server community.  My community involvement hasn’t just led to more knowledge about SQL Server, but also about community, communication, and leadership.  I hope and pray that this next change leads to even more growth. 

Monday, January 10, 2011

Speaking at SQLSaturday #62–Tampa

I’ll be speaking at SQLSaturday #62 – Tampa this Saturday, January 15th.  I’ll be presenting:

Why I Use Stored Procedures

With the proliferation of ORM tools like Entity Framework, nHibernate, and Linq to SQL, many projects have decided that stored procedures are not needed and slow down development. While these tools have their place and have improved greatly, stored procedures still have their place, and, in this speaker's opinion, are the best way to do data access. In this session I'll discuss my reasons for using stored procedures and hopefully stimulate some discussion of other access methods.

Session Level: Intermediate

Every SQLSaturday is a great time and great opportunity to upgrade your skills and network!  Pam Shaw and crew have done a few of these so they know what they are  doing.

I’ll also be attending Denny Cherry’s (Blog|Twitter) Day of Data seminar on Storage and Virtualization for the DBA on Friday, January 14, 2011.  You can still register and get by 2 get one free deal.

Hope to see you this weekend!

Thursday, January 6, 2011

Fun with a String

I recently had a friend contact me recently to ask for some help with TSQL.  The basic issue is that he had 2 tables.  Table 1 has numeric key values which are contained within a character column in Table 2 which is also in another database on the same server.  His job was to parse the character column in Table 2 so he could join to the numeric key in Table 1.  He originally said that the numeric data in the character column would start at position 7 and be 12 characters long so his original query was something like this:

SELECT
*
FROM
db.schemaname.table1 AS T1
JOIN db.schemaname.table2 AS T2
ON T1.id = SUBSTRING(T2.character_col, 7, 12)



I replied that the query would work, but was he guaranteed that the data would ALWAYS start at position 7 and be 12 characters?  Also that using the SUBSTRING function meant that the optimizer could not use an index.  As I thought about the situation I came up with this as probably the most flexible solution.



Here’s some test data:



/* Don't like to work in a user database */
USE tempdb ;
GO

CREATE TABLE
#test1 (id INT)

/* create a test table */
CREATE TABLE #test
(
string VARCHAR(50) NOT NULL
) ;

/* put in some data */
INSERT INTO #test1
(
id
)
SELECT
123456789012
UNION ALL
SELECT
234567890121
UNION ALL
SELECT
345678901212
UNION ALL
SELECT
456789012123
UNION ALL
SELECT
12345678901
UNION ALL
SELECT
23456789011
UNION ALL
SELECT
1234567890123
UNION ALL
SELECT
12345678901234 ;

INSERT INTO #test
(
string
)
SELECT
'Jack 123456789012'
UNION ALL
SELECT
'234567890121'
UNION ALL
SELECT
'Jack 345678901212'
UNION ALL
SELECT
'Jack abcdefg'
UNION ALL
SELECT
'Jack 456789012123x'
UNION ALL
SELECT
'Jack 12345678901'
UNION ALL
SELECT
'Jack 23456789011a'
UNION ALL
SELECT
'Jack 1234567890123'
UNION ALL
SELECT
'Jack 12345678901234a' ;


/* Use PATINDEX inside SUBSTRING to find the first instance of a numeric character 
to set the starting index. Use PATINDEX on the string REVERSE to find the
last instance of a numeric character. */
SELECT
*
FROM
#test1 AS T1 JOIN
#test AS T2 ON T1.id = SUBSTRING(T2.string, PATINDEX('%[0-9]%', T2.string),
LEN(T2.string) - PATINDEX('%[0-9]%', REVERSE(T2.string)) -
PATINDEX('%[0-9]%', T2.string) + 2);

DROP TABLE #test1;
DROP TABLE #test ;


This code works for this situation.  Will it work in every situation?  Probably not.  Will it scale?  Probably not, but it was an interesting exercise.



Do you have a better solution?  If you do post it in the comments or post a link to a blog post where you put your solution.

Tuesday, October 19, 2010

Chapter 38 – Successfully Implementing Kerberos Delegation

Cross posted from the SQLPespectives blog put together Richard Rodriguez, Chris Shaw, and Jeremy Lowell for a chapter by chapter walk-through of the SQL Server MVP Deep Dives book. 

MVP Scott Stauffer does a fantastic job of explaining what Kerberos delegation is, the issues it solves, and provides an extensive list of resources to close out the chapter.

This is the best resource I have found for understanding Kerberos and how to implement it.  K. Brian Kelley has an excellent article on SQLServerCentral that is good, but not quite as in depth as this chapter.  Scott lays out the process logically beginning with how and why he came to understand the process, taking you through what Kerberos is, what issues Kerberos delegation solves, and providing a business scenario that Kerberos will solve.

Kerberos is a complex topic which Scott makes simple in his section Understanding Kerberos Delegation.  He explains SPN’s (Service Principal Names), permissions needed to work with SPN’s, and the tools you will need.

Scott very clearly takes you through implementing Kerberos from beginning to end.  He includes great screen shots and code snippets along with explaining WHY you need to go through each of the steps.

Scott also included a section on validating your delegation setup using a tool called DelegConfig.  This tool is run on the client and web tiers and will validate that Kerberos delegation is configured correctly and working.

Finally Scott provides 3 pages of resources to use to learn about and implement Kerberos delegation which includes: tools, blog posts, TechNet articles, MS Help & Support articles, white papers, and webcasts.

This chapter is really a one-stop shop for people who need to understand and implement Kerberos delegation.

Monday, October 11, 2010

SSMS Tip – Tab Groups

A few months ago as I came across tab groups in SSMS and once I found them I was very happy to have found this feature, so I thought I’d pass it along.

The way I access a tab group is to right-click on the tab header (for lack of a better term) and the bottom 2 choices in the context menu are:

  • New Horizontal Tab Group – great for comparing execution plans
  • New Vertical Tab Group – great for comparing scripts side-by-side.

I mostly use the horizontal tab groups when I want to compare execution plans because I can usually use a tool like RedGate SQL Compare to compare scripts, but I don’t have or know of a tool that does execution plan comparison.  Here are some screen shots that show what I mean.

Here’s how thing look normally in SSMS:

SSMS Normal You can see I have 2 tabs open and in order to compare execution plans I’d have to switch between tabs, but if I right-click on one of the Query tabs like this:

RightClick

When I select “New Horizontal Tab Group” this is the result in SSMS, which is MUCH better for comparing Execution Plans:

Horizontal Tab Group

I’m sure other people knew about this long before I did, but it is a feature I have found VERY useful so I thought I’d pass it along.

Tuesday, September 14, 2010

September OPASS Meeting Tonight!



Mini-Session


Topic: Using PIVOT – Going from Static to Dynamic


Sometimes data normalization results in a data structure that is not convenient for displaying the data. Take the common example of a sales database in which each record represents a single sale.  However, what the customer really wants is a summary of sales for each product by quarter in which the quarters are columns, not vertical groupings.  SQL 2005 introduced PIVOT  to solve that type of problem.  The only drawback is that you must know when you write the SQL statement, how many columns you will need along with their name/values.  In some situations you may not know how many columns you need ahead of time.  Suppose you wanted to pivot on products that your company sells, but the number of products changes frequently.  How can you make the PIVOT statement dynamic?  We will explore one solution to that problem in this month’s SQL Tech Shot.


Speaker: Michael Antonovich


Mike Antonovich is the Assistant Director of Web Services for Orange County Public Schools in Orlando, FL where he manages the SharePoint portal team implementing the Internet, intranet, collaboration, project, team, and school sites. They are also responsible for multiple .Net custom applications around the district. In June of 2010, he published his 7th book: Office and SharePoint 2010 User's Guide. Mike has been using SQL Server since 1998 and SharePoint since 2007.


Main Session


Topic:  Cool Stuff with SQL Azure


This session will provide a quick introduction into SQL Azure, including account creation and security, and discuss why a move to SQL Azure might be important to your organization. We will discuss supported functionality in SQL Azure and then look at different deployment scenarios and data access techniques such as sharding and why that is important in SQL Azure. We will then take a look at how to develop applications for SQL Azure using many of the topics discussed


Speaker: Scott Klein


Scott Klein is President of Blue Syntax, a consulting and services firm specializing in SQL Azure. Scott is a Microsoft SQL Server MVP and author of several books including Professional SQL Server 2005 XML, Professional LINQ, Professional Entity Framework 4.0, and Pro SQL Azure. Scott runs the South Florida SQL Server Users Group.


RSVP to webmaster@opass.org


Agenda


6:00-6:10 Welcome and Announcements


6:10-6:25 SQLSaturday


6:25-6:40 Michael Antonovich - Using PIVOT – Going from Static to Dynamic


6:40-7:00 Pizza/Networking


7:00-8:00 Scott Klein - Cool Stuff with SQL Azure


8:00-8:15 Wrap-up/Raffle


Hope to see you there



 Don't Forget to register for SQLSaturday #49 - Orlando!

Monday, September 13, 2010

Space Coast User Group Recap

I had the pleasure of making my second annual September visit to the Space Coast SQL Server User Group in Melbourne, FL, last Thursday, September 9, 2010, to present, Introduction to Triggers.  This is small user group, but they are a lot of fun and ask good questions.  Because of the small size it is a very informal group so I took some time to talk about SQLSaturday #49 – Orlando, the pre-con on Database Design with Louis Davidson, and SQLRally before getting on with my presentation. 

The presentation went well and they caught me on one of my demos.  The demo in question demonstrates a common mistake I see in triggers and mention before doing the demos.  So, when I get to it I ask, “Can anyone see the problem with this trigger?”, and in this  case someone noticed I had left out the code, “SET NOCOUNT ON;”, at the start of the trigger body.  This was right after I had mentioned that you should always include this statement, unfortunately, this was not the problem I was trying to point out.  And, no, I’m not going to tell you what the answer I was looking for was.  If you want to get that, you’ll need to come see me present at SQLSaturday #52 – Colorado on September 25th.  Other than that, all the demos went well and the attendees learned a few new things.

Afterwards we went out to socialize at the restaurant at the local Holiday Inn where we talked SQLSaturday, football, and paper mills.  Why paper mills?  Well, it turns out that one attendee worked for the paper company that used own the mill I used to work at, and we had mutual friends in the company, and another attendee used to work for the company that wrote the truck scale software that we used at the paper mill I worked at.  It’s amazing how small the world is!

I’m tentatively scheduled to return next September, as we might as well make this an annual event!  Topic to be announced.

Tuesday, September 7, 2010

Upcoming Engagements

I haven’t been speaking a lot lately as I’ve been busy working, planning SQLSaturday #49 – Orlando, and planning PASS SQLRally, but I do have some upcoming engagements that I hope to see some of you at.

Introduction to Triggers on Thursday, September 9th 6:30pm, Space Coast SQL Users Group.

This session will give a brief overview of the different types of triggers available in SQL Server (DDL & DML) and then go into more detail on how and when to use DML triggers. This session will cover misconceptions about how triggers work, when triggers shoul d and shouldn't be used (we will discuss options), common mistakes, and how to fix the most common mistakes. After attending this session a person will: 1. Identify different types of triggers and when to use them. 2. Be able to identify when a trigger is the right solution 3. Be able to write triggers that perform well

SQLSaturday #52 – Colorado on Saturday September 25th

I’m scheduled for 2 sessions at this event.  I’m attending this event for 2 reasons:

  1. My wife has connected with Steve Jones’ wife, Tia, online and they both love horses.  Tia has horses, so my wife, Alice, will be spending the Saturday at the ranch with Tia and the horses.
  2. An opportunity to go to a part of the country I haven’t been to and to connect with some new people.  There are several people I know from SQLServerCentral and Twitter that I have not meet in person yet, and this will be a great opportunity to do that.
Why I Use Stored Procedures

With the proliferation of ORM tools like Entity Framework, nHibernate, and Linq to SQL, many projects have decided that stored procedures are not needed and slow down development. While these tools have their place and have improved greatly, stored procedures still have their place, and, in this speaker's opinion, are the best way to do data access. In this session I'll discuss my reasons for using stored procedures and hopefully stimulate some discussion of other access methods.

Introduction to Triggers

This session will give a brief overview of the different types of triggers available in SQL Server (DDL & DML) and then go into more detail on how and when to use DML triggers. This session will cover misconceptions about how triggers work, when triggers shoul d and shouldn't be used (we will discuss options), common mistakes, and how to fix the most common mistakes. After attending this session a person will: 1. Identify different types of triggers and when to use them. 2. Be able to identify when a trigger is the right solution 3. Be able to write triggers that perform well

SQLSaturday #49 – Orlando on Saturday, October 16th

In addition to planning and and running this event I’ll be presenting one session.

Profiling: It's Okay in SQL Server

Learn how to use SQL Server Profiler/Trace to troubleshoot SQL Server performance and errors. This session will cover how to use Profiler to capture SQL Server events, creating server-side traces, creating custom templates, saving trace data, and interpreting trace data.

I hope to see you at one of these events.  Please come up and talk to me, share your business card, and ask questions.  My favorite part of these events is meeting new people and re-connecting with people I haven’t seen recently.

Monday, May 17, 2010

5 Features SQL Server Doesn’t Need

Paul Randal (@PaulRandal) started this chain of blog posts with his post, What 5 Things Should SQL Server Get Rid Of? and I was tagged by Michelle Ufford (@SQLFool) in her post, Delete 5_Useless_Things FROM [SQL Server].  Many will be repeats, but that’s partly because SQL Server is such a good product and mostly because some features cause more problems than they solve.

  1. Autoclose – I don’t know of anyone who uses it and I can’t think of any reason why you would want to use it.  Even most base laptops running SQL Server Express have enough resources to keep databases open.
  2. Autoshrink – another one mentioned by almost everyone.  It causes more problems than it solves.  As a matter of fact I can’t think of any problems it actually solves in this day of terabyte drives, raid arrays, and SANS.
  3. Encryption of Stored Procedures, Functions, and Views – Odds are whatever you are doing in T-SQL has been done before.  Not only has it been done before, but it has probably been published on a blog.  Jeremiah Peschka (@peschkaj) covers this in his recent post, Encrypted Stored Procedures and Their Effect on my Rug.
  4. Master as the default database – changing and adding objects to the master database is not a recommended practice, so why would you make that the default database context when a user connects to SQL Server without specifying a database or having a default specified?
  5. Primary Key Defaulting to the Clustered Index – Sure, often times the primary key is a surrogate key which is narrow, unchanging, and monotonically increasing so it may be a good choice for a clustered index, but this isn’t always the case.  A Primary Key is a constraint so I should have to choose if it is a clustered index or not.

You can check out Paul’s blog to see many of the other posts in this meme.  I’m a bit late to the party and I think most people I know I have already been tagged so I won’t be tagging anyone this time around.

Thursday, May 13, 2010

Let’s Play, “Why did it do that?”

On my current project I decided to be flexible and allow the use of Linq to SQL to try to speed up development.  This will not be a large, heavily used database, so squeezing every drop of performance out of the database is not a big issue.  One of the reasons I agreed to it was so that I could see Linq to SQL in a real-world project and the queries generated.  Well, I saw my first “Why did it do that?” query.

Here’s a similar, simplified schema:

CREATE TABLE dbo.students
(
student_id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
last_name VARCHAR(20),
first_name VARCHAR(30),
birth_date smalldatetime
)
CREATE INDEX IX_last_name_first_name ON dbo.Students(last_name, first_name);

CREATE TABLE dbo.classes
(
class_id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
class_name VARCHAR(25)
)
CREATE INDEX IX_class_name ON dbo.classes(class_name);

CREATE TABLE dbo.student_classes
(
student_class_id INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
student_id INT REFERENCES dbo.students(student_id),
class_id INT REFERENCES dbo.classes(class_id)
)
CREATE UNIQUE INDEX UX_student_id_class_id ON dbo.student_classes(student_id, class_id)



Here’s what Linq generated (modified to fit the new schema):



exec sp_executesql 
N'SELECT
[t0].[student_ID] AS [Id],
[t0].[First_Name] AS [FirstName],
[t0].[Last_Name] AS [LastName],
[t1].[student_class_ID] AS [Id2],
[t1].[class_id] AS [ClassId],
[t1].[class_name] as [ClassName]
(
SELECT
COUNT(*)
FROM
[dbo].[student_classes] AS [t3] INNER JOIN
[dbo].[classes] AS [t4] ON
[t3].[class_id] = [t4].[class_id]
WHERE
[t3].[Student_ID] = [t0].[Student_ID]
) AS [value]
FROM
[dbo].[students] AS [t0] LEFT OUTER JOIN
(
[dbo].[student_classes] AS [t1] INNER JOIN
[dbo].[classes] AS [t2] ON
[t1].[class_id] = [t2].[class_id]
) ON
[t1].[student_ID] = [t0].[student_ID]
WHERE
([t0].[Last_Name] LIKE @p0) AND
([t0].[First_Name] LIKE @p1)
ORDER BY
[t0].[student_ID],
[t1].[student_class_ID],
[t2].[class_id]'
,
N'@p0 varchar(8000),@p1 varchar(8000)',
@p0 = 'Abb%', @p1 = 'Abb%'

Note the correlated sub-query to return the count of classes by student. This is not in the Linq query in .NET, but is added by the framework because of the one-to-many relationship between students and student_classes. Basically the student object contains an EntitySet of student_class objects and it looks like L2S needs to know the number of objects in the list. If this is needed you can return it by replacing the correlated sub-query with a CTE or derived table. Here’s an example of what I’d write:

SELECT
S.student_id,
S.last_name,
S.first_name,
SC.student_class_id,
SC.class_id,
C.class_id,
C.class_name,
CC.class_count
FROM
dbo.students AS S LEFT JOIN
(
dbo.student_classes AS SC JOIN
dbo.classes AS C
ON SC.class_id = C.class_id
)
ON S.student_id = SC.student_id LEFT JOIN
(
SELECT
SC2.student_id,
COUNT(SC2.student_class_id) AS class_count
FROM
dbo.student_classes AS SC2
GROUP BY
SC2.student_id) CC
ON S.student_id = CC.student_id
WHERE
S.last_name LIKE 'Abb%' AND
S.first_name LIKE '%'
ORDER BY
S.student_id,
SC.student_class_id,
C.class_id

This eliminates the correlated sub-query and eliminates a second scan of the classes table.  I’m still trying to understand why Linq needs the count.  Any other suggestions?

Wednesday, April 21, 2010

Presenting at SQLSaturday #41 – Atlanta

I have the privilege of being able to attend and present at SQLSaturday #41 – Atlanta this weekend.  This will be my first SQLSaturday outside of Florida and the first time I will have presented outside of Florida.  I’m looking forward to seeing many “old” friends and making even more new ones.  My presentation is:

Why I Use Stored Procedures and You Should Too!

With the proliferation of ORM Tools like Linq To SQL, NHibernate, there has been a move to no longer use stored procedures for Data Access, I personally disagree. This will be a professional and polite open discussion starting with why I believe stored procedures are the best way to access data in SQL Server. Alternate view points welcome.

With the recent release of Visual Studio 2010 and .NET 4.0 there have been changes in the Microsoft ORM tools that alleviate some of the issues I have with ORM tools, but I don’t think all the issues I see have been addressed.  It’s interesting that at my office we just brought in a consulting company to work on a project with us and they are proponents of Linq to SQL, so I get to try my arguments with them and hear the other side of the argument. 

I’ll be flying into Atlanta Friday afternoon and should be at the speaker party of Friday night, but will miss the after-party on Saturday to be able to catch my flight back to Orlando. 

If you are attending please be sure to find me on Saturday.  I’ll have my contact cards, I hope you will, too!

If you have registered, but will not be able to attend please cancel your registration so someone on the waiting list can attend.  Thanks!

Tuesday, April 13, 2010

T-SQL Tuesday #005 – Don’t Send a Blank Report from a Report Subscription

Aaron Nelson (@SqlVariant) is hosting this month’s T-SQL Tuesday (#tsql2sday) and his topic is reporting.

One of the frustrations I have had and seen with Reporting Services subscriptions, especially when using non-enterprise edition, is that there is no built-in way to specify that a report should not be emailed if there is no data.  I came up with a work around, albeit not a perfect solution.

The first step is to note what jobs you have already created on your reporting SQL Server so you will know what job applies to the new subscription.  This is because SSRS subscriptions are driven by SQL Agent Jobs.  I’m sure there are other ways to find out which job ties to your new report subscription (querying sysjobs for most recently created or directly querying the ReportServer database), but in my case knowing what you already have and visually finding the new job was the easiest.

Next, create your scheduled subscription and under “Select Schedule” set the dates to begin and end the subscription to the past.  This is an important step as you don’t want the job to run on it’s own, but when you determine it should run.  Then click “OK” to save the subscription.

Now, you should have new job in SQL Agent with a GUID as a job name.  Now you need to create a new SQL Agent job with one step.  In that step you will, unfortunately, need to duplicate the logic in the report.  For example, Previous Day’s Sales, you would do something like this:

IF EXISTS ( SELECT
1
FROM
Sales.SalesOrderHeader AS SOH
WHERE
-- Start of Yesterday
SOH.OrderDate >= DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()) - 1, 0) AND
-- beginning of today
SOH.OrderDate < DATEADD(DAY, DATEDIFF(DAY, 9, GETDATE()), GETDATE()) )
BEGIN
EXEC
msdb.dbo.sp_start_job @job_name = N'B05BEC48-721A-4BE4-B2E8-9B13F6143025'
END


As you can see, this code checks to see if any Orders were placed the previous day, and, if there were any orders, the job created by our SSRS Subscription is run, if no orders were placed then the SSRS subscription does not run.  You would then schedule this job to run on a daily basis so the subscribers to the report will get an email whenever there have been orders made the previous day.



The problem with this work around is obvious, when you have data you run similar queries twice, thus increasing the load on your SQL Server.  If you have many subscriptions, you may not want to use this work around for them all.  I came up with this because we had an exception report and the business users only wanted to receive an email when there was an exception.

Tuesday, March 30, 2010

Didn't I Just Post about Slipstream making Installs Easier?

So the other day I posted, Slipstream - Makes installs simple, and this afternoon I needed to do a SQL Server 2008 Standard install to get an evaluation environment of Team Foundation Server 2010 installed.

Well, I didn't follow my own advice.  I figured I had some good reasons:

  1. My slipstream setup is on my laptop at home and is SQL Server 2008 Developer.
  2. I'm doing a one-time install so setting up the slipstream environment would take just as long as installing the RTM and then SP1.

Just call me stupid.  First, I got a Restart Required error that wouldn't go away on the RTM install.  You can find the fix to that here (thanks to Aaron Bertrand (@AaronBertrand)).  So I go the RTM installed, then I started to install SP1.  Wait! The same error!  No big deal I have the fix.  No, you can't use the /Action=Install with a service pack install.  Okay, I'll try /Action=Upgrade, nope that doesn't work either.  Finally, after 2 hours I tried /SKIPRULES=RebootRequiredCheck without the /ACTION parameter and it worked!

Lesson learned.  In less than half the time I could have built my SQL Server 2008 Standard + SP1 slipstream install and had everything up and running.  I basically lost an afternoon because I refused to do something I knew I should do.

Monday, March 29, 2010

Slipstream - Makes installs simple

I was recently working on building a test environment for myself while I was studying for the MCITP-Database Administration exams.  SQL Server 2008 supports creating a slipstream install for service packs and cumulative updates so you can install to the latest SP or cumulative update in one step.

The problem with a slipstream install is that you need to set it up first, so for a single install I'm not sure how much time you actually save, but for multiple installs or for creating media it is great.  I followed the instructions Peter Saddow's blog on msdn.  I'm not going to duplicate those instructions here, as they are easy to follow and worked. 

Once I finished setting up the slipstreamed install location, I downloaded ISO Recorder and used it to create an ISO image of the install directory.  ISO Recorder adds "Create ISO image file" to the right-click menu.  I did the ISO image as I was installing SQL Server on some virtual machines and didn't want to have to share the install location and I also wanted to be able to easily burn it to DVD.  The only issue I had was that Virtual PC would not successfully mount the created ISO image.  Fortunately I had already downloaded Virtual Clove Drive, which would allow me to mount the ISO image.  I'm not sure why Virtual PC would not allow me to mount it.  Once I got the ISO image mounted I was able to install SQL Server 2008 + SP1 without issue on a couple of VM's.  It was definitely worth the time to create the slipstream.

Anyone else have any experiences to share or issues they encountered?

Monday, March 15, 2010

Thoughts on SQL Server Certification

This is probably part 1 of a series, but no guarantees.

Why Certify?

I've been working with SQL Server for 10 years and for most of that time I've thought certification was unnecessary.  When I first started out my boss was not a fan of MS certifications, so I wasn't interested either.  Once I had some experience, I thought that my experience was enough.  So what changed my mind?  I moved and got to know people who, in my opinion, know a lot more about SQL Server than I do, so I was challenged to "up my game" and one way to do that is through certification.  The certification requires that I study about areas of SQL Server that I have not had the opportunity to work with or needed to know about, areas like clustering, log-shipping, online restores, to name just a few. 

Another reason is that I enjoy presenting (teaching) and I think I'd like to continue to do that and maybe make some money doing it.  So, I decided that one way to do that is to become and MCT (Microsoft Certified Trainer) and in order to do that you need to be an MCITP.

Finally, after having already decided to go down the certification path, I read this article in ComputerWorld, Opinion: Certifications are no longer Optional.  I don't know how accurate that might be, but I also think that certifications can't hurt me.

So What Have I Done?

I recently took (and passed) 70-432: TS: Microsoft SQL Server 2008 Implementation and Maintenance. 

Preparation

I prepared for the test by going through Buck Woody's (@BuckWoody) blog series on his preparation for this test.  I also purchased the MCTS Self-Pace Training Kit (Exam 70-432): Microsoft SQL Server 2008-Implementation and Maintenance.  I purchased the book because it comes with practice test software which I thought would be valuable. The training kit was helpful, but a little shallow, I really expected it to be delve deeper into the subjects.  The case study presented at the end of each chapter was the most helpful part of the book as it really caused me to think about what I thought was the best way to solve the problem(s) presented.  I actually had a harder time doing the practice test(s) than I did with the real test.  I don't think I passed the real test because of this book, but it did help augment my experience and the other resources.

The Test

Having never taken a certification test before and this being about 15 years after the last test I took that actually meant anything, I was a bit concerned about being able to pass.  This concern was based on the fact that I had NOT passed a practice test.  I'll share that I have always been a good test taker, especially when the test is multiple choice, which the certification test is.  I got to the test center about 30 minutes before the test was scheduled (as recommended) and was registered and at the test station about 20 minutes later.  Now, the recommendation is to allow 2 hours and 45 minutes for the test so I expected a long test.  Well, I was leaving the test center 40 minutes after I sat down at the test station.  During that time I did the practice test, as it was my first time, did the pre-test MS survey, took the test, reviewed every question on the test, took the post-test MS survey, and the post-test Prometric survey.   You can decide how hard the test was.

Test Value

The test definitely covered all the areas it said it would cover, but I thought it should have been twice as long as there was not enough depth to the questions.  I am pretty sure I could have passed without studying.  I definitely could have passed without studying as much as I did.  Would I expect someone who passed this test to be able to sit down and set up a cluster or replication?  No.  I would expect to be able to give them a scenario and have them give me an basic solution that would be meet business requirements around availability and recovery.  So it has some value, but could be better.

What's Next?

I've scheduled 70-450: PRO: Designing, Optimizing and Maintaining a Database Server Infrastructure using Microsoft SQL Server 2008.  I'll have another post about this test when I get there.

Thursday, March 4, 2010

Timing Matters

A few weeks ago I got an email from my backup administrator with a message like this:

Set type               : Backup
Set status             : Completed
Set description        : Weekday Backup

Resource name          : \\Server\Backups
Logon account          : System Logon Account
Encryption used        : None

Agent used                     : Yes
Advanced Open File Option used : No

Byte count             : n bytes
Rate                   : n MB/Min

Files                  : n
Directories            : n
Skipped files          : 1
Corrupt files          : 0
Files in use           : 0

Start time             : DOW, Month DD, YYYY 12:25:48 AM
End time               : DOW, Month DD, YYYY 12:29:26 AM

Media used             : media name
File is in use         : \\Server\Backups\BackupFolder\database_name_tlog_YYYYMMDDHHMM.BAK

So I checked the job schedule because when the transaction log backup job runs, it also deletes old backups.  The Log backup job was scheduled to run on the 1/2 hour and according to this report, the BackupExec job finished BEFORE 12:30 AM.  I sent this information to the backup administrator mentioning that it seemed like there must be a time difference between the BackupExec server and the SQL Server.  It turns out that the the SQL Server was 62 seconds ahead of the BackupExec server. 

Apparently BackupExec grabs a list of files to be backed up and then iterates over the list backing up each file, but when it got to this file the SQL Server Agent job had deleted the file.  Thus, BackupExec couldn’t backup the file.

I find this interesting because wouldn’t this also mean that BackupExec would miss any files created during the backup process?  I’m not a expert on backups, beyond knowing how to do SQL Server backups and the fact that I’ve changed tapes and started BackupExec jobs a couple of times, so maybe this is expected and accepted behavior.

Thursday, February 25, 2010

The Journey from Smart to Good

“It’s easier to be smart than good.”

I heard that quote in a recent sermon at church and it is one I can very much relate to in more than one area of my life.  In context the pastor was discussing the difference between knowing what the Bible says (being smart) and applying what the Bible says (being good) and all too often I am more smart than good in that area, that’s a topic for another blog, but really the quote can be applied to many areas, including being a SQL Server DBA and that’s what I want to talk about here.

All too often I’m smart, rather than good when it comes to being a DBA.  I allude to this in my 2010 Goals post in the Professional Development section goal #2.  I’m great at learning new things and always have been, but not as good at putting them into practice.  I KNOW a lot about SQL Server, but, for a variety of reasons (fear of failing, size of SQL Server implementations, etc…), I haven’t APPLIED that knowledge.  One other thing I think that comes into play for me, anyway, is the three levels of knowledge as discussed in this blog post (note:  while the ideas are good I don’t agree with some of the wording).  Basically it says there are three areas of knowledge:

  1. The things you know you know.
  2. The things you know you don’t know.
  3. The things you don’t know you don’t know.

The goal is to have area 3 be as small as possible and area 1 as large as possible.  My issue in regard to being a SQL Server DBA is that I have moved a big chunk of area 3 into area 2, which just makes me feel inadequate, but in reality that means I’m making progress.  The next step is to move some of area 2 into area 1.

So what’s the plan for going from smart to good?  I think the first step is to understand that there is a difference, then begin applying what you already know.  Then just continue to learn AND apply. 

Remember it’s a journey not a destination and the good DBA’s I know realize that you never really arrive. 

So where are you in the journey?

Monday, February 22, 2010

What’s up with the reads?

So the other day I read Andrew Kelly’s article, Do You Have Hidden Cache Problems, in the latest electronic edition of SQL Server Magazine, and decided to run the query he listed in the article to see if my server was suffering from this problem:

SELECT
SUM(single_pages_kb + multi_pages_kb) AS "CurrentSizeOfTokenCache(kb)"
FROM
sys.dm_os_memory_clerks
WHERE
name = 'TokenAndPermUserStore'


My result was 189344 kb.  In the article Andrew states that:




…if its under 10MB, you should be fine.  I’d start getting concerned between 10MB and 50MB.  If the amount of the consumed memory is over 50MB, you’re probably affected by this problem.




Well, my value converts to nearly 185MB!!!  I guess I must have this problem.  The article says this about the cause:




On a system with reuses query plans effectively, this cache would be as large as only a few megabytes,… But on a 64-bit system with lots of ad hoc or dynamic SQL queries, this cache can grow to hundreds of megabytes in size.




So apparently my lightly loaded server (1 main application on it right now) and a max of about 50 user connections has a lot of ad hoc or dynamic SQL hitting it.  Well, since the application is a third-party application I decided to run this query to see what I had in the procedure cache for ad hoc queries:



SELECT
DEQS.execution_count,
DEQS.total_worker_time,
DEQS.total_physical_reads,
DEQS.total_logical_reads,
DEQS.total_elapsed_time,
DECP.refcounts,
DECP.usecounts,
DECP.cacheobjtype,
DECP.objtype,
DEST.text
FROM
sys.dm_exec_query_stats AS DEQS JOIN
sys.dm_exec_cached_plans AS DECP
ON DEQS.plan_handle = DECP.plan_handle CROSS APPLY
sys.dm_exec_sql_text(DEQS.sql_handle) AS DEST
WHERE
DECP.objtype = 'ADHOC'
ORDER BY
DEQS.execution_count DESC


Hmmm, 4800+ rows returned.  As looked a little deeper I noticed that rows 10-12 based on execution count were the same query with different WHERE clauses.  The queries looked like this:



SELECT TOP 1
Column1
FROM
Table WITH
(NOLOCK)
WHERE
(Column2 = 'Column Default Value' Or
Column2 = 'Another Column Value') AND
(
Column3 = 'Column Default Value') AND
Column4 = 'Value' AND
Column5 = 'Value'
ORDER BY
Column2,
Column3


Interesting.  Then I looked a little further down the list and found some more of the same query.  So I reran my query adding WHERE text Like '’%KeyWord1%KeyWord2%KeyWord3%’ and found over 600 rows for this “single” query in the cache.  Now, those of you who read my blog know that I am a believer in stored procedures for data access and if you aren’t using stored procedures then use parameterized SQL.  This is a great example of a query that needs to be encapsulated into stored procedure or parameterized.



It gets even better.  I took one of the queries and ran it to see what it returned.  It returned nothing! So I ran SELECT * FROM Table to see what was in the table, nothing at least at that time!  The fun part is that running the application query does a Clustered Index Seek, but takes 2 scans to do it according to STATISTICS IO and the SELECT * takes does a Clustered Index Scan but only scans the index once according to STATISTICS IO.  So I looked at the clustered index on the table and it is (based on my query):



    Column2, Column3, Column4, Column5, Column6



So the only column in the table not included in the clustered index is Column1 (the value being returned).  As I looked at the query, it hit me.  There is an OR in the where clause, so in the Query Plan you have 2 SEEK predicates thus 2 scans of the index.  If you remove the OR you get one SEEK predicate and 1 scan.



So what does all this mean?  Well, for me it solidifies 2 things:




  1. Use stored procedures or at the least parameterized SQL.


  2. OR’s are bad and should be avoided as much as possible



So what am I going to do?  I honestly don’t know for sure.  Because there are no complaints about performance I don’t feel the need to address the TokenAndPermUserStore issue and I’m not sure what I’d do anyway besides possibly using Forced Parameterization.  I think I will contact the vendor (they’ve been good to work with so far) to find out what the query really does and to find out why it isn’t parameterized or in a stored procedure since most of their other stuff is.  I’m open to suggestions.

Wednesday, February 3, 2010

DBCC CHECKDB() on ResourceDB?

A few days ago I was answering a forum post about CHECKDB() and as part of the research I checked the Windows Application Log.  I was surprised to see this entry:

Event Type:    Information
Event Source:    MSSQLSERVER
Event Category:    (2)
Event ID:    8957
Date:        1/30/2010
Time:        5:45:02 PM
User:        domain\username
Computer:    ServerName
Description:
DBCC CHECKDB (mssqlsystemresource) WITH all_errormsgs, no_infomsgs, data_purity executed by domain\username found 0 errors and repaired 0 errors. Elapsed time: 0 hours 0 minutes 0 seconds.

I’m using Ola Hallengren’s backup and maintenance scripts to do my integrity checks, but you can’t run DBCC CHECKDB() against ResourceDB, can you?  Well, just to verify I tried it and got this message:

Msg 2520, Level 16, State 11, Line 1
Could not find database 'mssqlsystemresource'. The database either does not exist, or was dropped before a statement tried to use it. Verify if the database exists by querying the sys.databases catalog view.

So where did the application log come from?  As usual BOL has the answer in the DBCC CHECKDB() entry:

Because the Resource database is modifiable only in single-user mode, the DBCC CHECKDB command cannot be run on it directly. However, when DBCC CHECKDB is executed against the master database, a second CHECKDB is also run internally on the Resource database. This means that DBCC CHECKDB can return extra results.

So while you can’t directly run the command SQL Server is taking care of it for you when you run it against the master database.

The question is, are you doing anything to BACKUP the Resource Database? 

Thursday, January 28, 2010

What the Exec?

I’ve been working with SQL Server for 10 years and have worked in production with versions 6.5 – 2005 and used 2008 personally.  I know I haven’t seen everything, but a couple of weeks ago a friend of mine asked me to look at some stored procedures he was working on and I saw something I’d never seen before.  The code was something like this (I’m using the AdventureWorks database, 2005 version):
CREATE PROCEDURE dbo.exec_example
(
@parameter VARCHAR(10) = 'employee',
@ID INT = 10 
)
AS

SET NOCOUNT ON;

DECLARE @sp_name NVARCHAR(100);

IF @parameter = 'employee'
BEGIN
SET @sp_name = 'dbo.uspGetEmployeeManagers'
END
ELSE
BEGIN
SET @sp_name = 'dbo.uspGetManagerEmployees'
END;

EXEC @sp_name @id;

RETURN;
The interesting part is where the stored procedure name is put in a variable and then you just use Exec @sp_name with the parameters listed after.  I’d never seen this done before, and my first comment on the code was, “I don’t think that should work”, but it does.  I also looked it up in BOL and here’s a couple of snippets from the EXECUTE (Transact-SQL) entry:

From the Arguments section:



@ module_name_var








Is the name of a locally defined variable that represents a module name.

From the Examples section:
E. Using EXECUTE with a stored procedure variable
The following example creates a variable that represents a stored procedure name.

DECLARE @proc_name varchar(30);
SET @proc_name = 'sys.sp_who';
EXEC @proc_name;
I had been contacted to try to help clean up and improve the code my friend was writing and this was a time where I learned something.  This is one of the things I love about SQL Server, and technology in general, you can learn from anyone, even when you’ve been called in as the expert.