Tag goats

Building a new SQL 2008 box

I have a lucky, and rare, chance coming my way in about a week: I will be given the opportunity to design and install the production SQL servers at work.

Here’s the fun part – I’ve never done this before, at least not on a production machine.

What best practices, secret tricks, or hare-brained schemes do you, my fellow DBAs, follow when you put together a new SQL Server installation?

This could be anything from drive configuration, something about SANs, trace flags, whatever. You name it, I’ll evaluate it and confer with other smartypants types and once the install is done, I’ll let you know how everything goes.

Oh, the hardware is going to be a dual CPU quad Xeon machine from Dell with 16GB of RAM. And we do have a SAN of some nature, but that’s a mystery box.

Edit: So, what will these machines actually do? They will serve reports off of an OLTP schema that is updated every 15 minutes through replication from our master database server. There will be two instances on each machine – one that is live and one that just sits there, doing nothing. They mirror each other, in addition to the geographic fail over that somebody else is configuring. We do some heavy batch processing in the early morning hours, but during the day the machine is largely doing reads and whatever writes that the replication brings about.

The database that holds the majority of the reporting data is about 45GB and there is approximately 25GB of metadata and summarized reports (the batch processing, naturally) in a second database.

One quarter ago?

Today at work we discovered that DATEADD can do date math involving quarters. Which, if you ask me, is pretty cool.

In an effort to avoid work investigate this scenario, we started playing around with our calendar table and DATEADD.

SELECT [Date],
       DATEADD(q, -1, [Date]) AS OneQuarterAgo,
       DATEDIFF(d, [Date], DATEADD(q, -1, [Date])) AS diff_days
  FROM Calendar
 WHERE y = 2009

Using that query, we figured out that:

  1. We had a different idea of quarter than SQL Server
  2. We understand why SQL Server works like this
  3. God help us all if we have to figure out financial quarters correctly

Basically, SQL Server says “Give me a date that is three months ago and has the same, or closest, ordinal date value.” This is the most apparent when looking at the output of that previous query specifically for May (three months before May is February):

SELECT [Date],
       DATEADD(q, -1, [Date]) AS OneQuarterAgo,
       DATEDIFF(d, [Date], DATEADD(q, -1, [Date])) AS diff_days
  FROM Calendar
 WHERE y = 2009
   AND m = 5

Which produces:

Date OneQuarterAgo diff_days
2009-05-01 2009-02-01 -89
2009-05-02 2009-02-02 -89
2009-05-03 2009-02-03 -89
2009-05-04 2009-02-04 -89
2009-05-05 2009-02-05 -89
2009-05-06 2009-02-06 -89
2009-05-07 2009-02-07 -89
2009-05-08 2009-02-08 -89
2009-05-09 2009-02-09 -89
2009-05-10 2009-02-10 -89
2009-05-11 2009-02-11 -89
2009-05-12 2009-02-12 -89
2009-05-13 2009-02-13 -89
2009-05-14 2009-02-14 -89
2009-05-15 2009-02-15 -89
2009-05-16 2009-02-16 -89
2009-05-17 2009-02-17 -89
2009-05-18 2009-02-18 -89
2009-05-19 2009-02-19 -89
2009-05-20 2009-02-20 -89
2009-05-21 2009-02-21 -89
2009-05-22 2009-02-22 -89
2009-05-23 2009-02-23 -89
2009-05-24 2009-02-24 -89
2009-05-25 2009-02-25 -89
2009-05-26 2009-02-26 -89
2009-05-27 2009-02-27 -89
2009-05-28 2009-02-28 -89
2009-05-29 2009-02-28 -90
2009-05-30 2009-02-28 -91
2009-05-31 2009-02-28 -92

It’s pretty apparent that the last four days in May have the same date produced by the calculation in the OneQuarterAgo column.

There’s not really anything else left to do here, so I’m going to go back to listening to punk covers of Lady Ga Ga songs.

Links for the Week 2009.05.22

Big pile o’ link love this week. Honestly, I didn’t include a ton of GREAT links from Brent Ozar because people would start to think that Brent Ozar pays me to link to his site and say Brent Ozar a lot. He doesn’t, but if you click on the links to Brent Ozar maybe he’ll see where the traffic came from and pay me to provide links to Brent Ozar

SQL Server

SQL Server 2008 Developer Training Kit Available for Download Denis Gobo provides a link and a quick summary of Microsoft’s most recent training offering for developers that will help get people up to speed with SQL Server 2008.

PASS Virtualization Virtual Chapter That’s right, we have a new thing at PASS. Well, the same old thing has a new name. SIGs are now Virtual Chapters. And Brent Ozar is now in charge of the PASS Virtualization Chapter. Check it out!

Download – SQL Server 2008 Developer Training Kit Free training. Free training. Freetraining. freetraining.

Excel Functions for SQL Server Sometimes I’ll find myself using SQL Server and longing for something from Excel that one of my more management-type friends has shown me. Now I can, in theory, have some of that Excel love right in SQL Server.

What’s a ‘DBA’? I’ve known for a long time that, while I love data, I’m not a DBA… not 100%, at least. Sam Bendayan answers the question and talks about what job title options there are for database professionals

Development

MvcFluentHtml – Fluent HTML Interface For MS MVC ASP.NET MVC doesn’t us a bad method to generate HTML, but there are definitely smoother ways, depending on how preference. Fluent HTML uses one paradigm to make it a bit easier to generate HTML in your views. It’s closer to how Ruby on Rails does things, and I like Rails. A lot. Almost as much as I like SQL Server.

Dear Art Director…

Stuff & Things

The Information Architecture of Personal Music Collections Dan Brown, famed Information Architect not famed author, spent a lot of time thinking about how people interact with music libraries. The poster is from 2005 but, shockingly, not a lot has changed since then.

11 Striking Findings From an Eye Tracking Study Eye tracking is some great stuff, it’s right up there with click tracking. It helps us, as bloggers, figure out what you, the readers, are paying attention to.

How to Maintain a Healthy Lifestyle When You’re Too Busy To Care Title says it all. Lazy? Want to get in better shape? Do this.

Evil Lair: On the Architecture of the Enemy in Videogame Worlds I don’t know what to say about this, really. This is a fascinating article about how architecture current works its way into video games and also how it could be used.

10 for $10 hardcore summer tour This is the coolest idea for a summer tour – 10 bands for $10. If you’re at all into hardcore punk, it’ll be a great show. If you aren’t (which is more than likely since you’re reading this blog), take note because it’s an interesting idea that you might see more of in the future.

How to Build Your Own PC WARNING: NOT SAFE FOR WORK SomethingAwful.com is often flagged as adult content. Don’t visit it if you like keeping your job. That being said, this is a hilarious look at building your own computer. It’s based on Brent Ozar‘s experiences building his hackintosh.

Copying Data Should Be Easy

Typically, moving data isn’t that big of a deal. You can either fire up SSMS and write a quick script to copy data from one server to another. Or, if you need to move data from production into development, you can just do a back up and restore.

“Typically” is the key word in the previous paragraph. In my situation, we have a production master that replicates to two separate servers. The data on each subscriber is different and the determination process is driven by business criteria (actually, it’s driven by a number in a TINYINT column). The publisher is mainly a central target for our ETL processes. As such, it doesn’t have a lot of indexing on it. The subscribers, however, do. Refreshing the development environment is a bit trickier than just restoring over the dev database.

Yeah, sure, destroy. Sounds good.

Yeah, sure, destroy. Sounds good.

Initially, I tried using the Import Data task to copy data across from the production server to the dev server. The trick here is that there were still foreign keys on the table. In case you’re unfamiliar with this feature of the Import and Export Wizard, it gives you the option to “Delete” rows in the destination table. In this case, the word “Delete” actually means “Use TRUNCATE TABLE instead and don’t tell anyone about it”. Well, the fun part is that TRUNCATE TABLE will fail noisily if you have foreign keys in place.

Being an enterprising young man, I thought to myself, I know, I’ll just write a script to write a script that will drop and re-create all of my foreign keys. So, instead of writing the script myself, I twittered and Ted Krueger send back a tweet that led me to this little gem. Don’t mind the sloppy syntax, that script works great. So, after modifying it to give me both the drop and creates, I was ready to go, right?

Not so fast! As we know, every row written to a table also has to be written to all of the non-clustered indexes as well: one table plus four indexes = five writes. This is a large database (just large, not a VLDB). As such, there are a lot of indexes. They are also large. Inserting a large number of rows into a large number of indexes will take, as they say, some time.

Being impatient, and enterprising, I decided to write a script to drop and re-create all of the indexes as well. But, rather than write a script, I just went ahead and found one and modified it to suit my purposes. Actually, I tweeted and Adam Machanic and Mladen Prajdic ended up pointing me toward Tibor Karaszi’s sp_indexinfo – enhanced index information procedure which I was able to easily modify to give me the index drop and create info I needed.

Protip: SQL Server Google hint: Add “vyas” or “tibor” to your searches for DDL scripts and you’ll almost always get a good hit… (Thanks, Adam!)

At this point, everything should be done and our story should be over. You, dear reader, would have falsely assumed that this story has a happy ending.

When I fired up the data import task it would eventually and inevitably fail catastrophically with an error along the lines of “TCP Provider: An existing connection was forcibly closed by the remote host.” We started looking into the actual networking issued before we realized that I was running the export data wizard from my local computer, which shares a hub with several other networked devices. Once I remoted into the development server and attempted the process, I got the following error: “TCP Provider: An operation on a socket could not be performed because the system lacked sufficient buffer space or because a queue was full.”

This error comes from an issue when you are using the /3GB switch on a 32-bit server that might be copying large quantities of data from one place to another. The solution is do make sure that you still have AWE and PAE enabled, remove the /3GB switch, and then reboot!

I’m still waiting for my reboot. I think I should have just done a backup and restore and copied the indexes back in from production. So much for trying to be clever and automate the process, eh?

Oh, here’s the script that drops and re-creates all of the indexes in the current database. It should be, at the very least, a curiosity to someone.

DECLARE @newline AS NVARCHAR(2);

SET @newline = NCHAR(13) + NCHAR(10);

IF OBJECT_ID(N'tempdb..#indexes') IS NOT NULL
  DROP TABLE #indexes;

WITH key_columns AS
(
  SELECT c.[object_id],
         c.name AS column_name,
         ic.key_ordinal,
         ic.is_included_column,
         ic.index_id,
         ic.is_descending_key
    FROM sys.columns AS c
         INNER JOIN sys.index_columns AS ic
            ON c.[object_id] = ic.[object_id]
           AND ic.column_id = c.column_id
),
physical_info AS
(
  SELECT p.[object_id],
         p.index_id,
         ds.name AS location,
         SUM(p.rows) AS rows,
         SUM(a.total_pages) AS pages
    FROM sys.partitions AS p
         INNER JOIN sys.allocation_units AS a
            ON p.hobt_id = a.container_id
         INNER JOIN sys.data_spaces AS ds
            ON a.data_space_id = ds.data_space_id
   GROUP BY [object_id], index_id, ds.name
)
SELECT OBJECT_SCHEMA_NAME(i.[object_id]) AS schema_name,
       OBJECT_NAME(i.[object_id]) AS table_name,
       i.name AS index_name,
       CASE i.type WHEN 0 THEN N'heap'
                   WHEN 1 THEN N'CLUSTERED'
                   WHEN 2 THEN N'nc'
                   WHEN 3 THEN N'xml'
                   ELSE CAST(i.type AS VARCHAR(2)) END AS [type],
       i.is_unique,
       CASE WHEN is_primary_key = 0 AND is_unique_constraint = 0 THEN N'IX'
            WHEN is_primary_key = 1 AND is_unique_constraint = 0 THEN N'PK'
            WHEN is_primary_key = 0 AND is_unique_constraint = 1 THEN N'UX'
       END AS cnstr,
       STUFF((SELECT CAST(', ' + kc.column_name
                          + CASE kc.is_descending_key WHEN 0 THEN ''
                                 ELSE ' DESC' END AS VARCHAR(MAX)
                     ) AS [text()]
                FROM key_columns AS kc
               WHERE i.[object_id] = kc.[object_id]
                 AND i.index_id = kc.index_id
                 AND kc.is_included_column = 0
               ORDER BY key_ordinal FOR XML PATH ( '' )), 1, 2, '') AS key_columns,
       STUFF((SELECT CAST(', ' + column_name AS VARCHAR(MAX)) AS [text()]
                FROM key_columns AS kc
               WHERE i.[object_id] = kc.[object_id]
                 AND i.index_id = kc.index_id
                 AND kc.is_included_column = 1
               ORDER BY key_ordinal FOR XML PATH ( '' )), 1, 2, '') AS included_columns,
       p.location,
       p.rows,
       p.pages,
       CAST((p.pages * 8.00) / 1024 AS DECIMAL(9, 2)) AS MB,
       s.user_seeks,
       s.user_scans,
       s.user_lookups,
       s.user_updates
  INTO #indexes
  FROM sys.indexes AS i
        LEFT OUTER JOIN physical_info AS p
          ON i.[object_id] = p.[object_id]
         AND i.index_id = p.index_id
        LEFT OUTER JOIN sys.dm_db_index_usage_stats AS s
          ON s.[object_id] = i.[object_id]
         AND s.index_id = i.index_id
         AND s.database_id = DB_ID()
 WHERE OBJECTPROPERTY(i.[object_id], N'IsMsShipped') = 0
   AND OBJECTPROPERTY(i.[object_id], N'IsTableFunction') = 0
   AND OBJECT_NAME(i.[object_id]) LIKE N'%'
   AND i.[type] >< 0
 ORDER BY table_name, i.[type], index_name;

SELECT N' DROP INDEX '
       + QUOTENAME(i.index_name)
       + N' ON '
       + QUOTENAME(i.[schema_name])
       + N'.'
       + QUOTENAME(i.table_name)
  FROM #indexes AS i
 WHERE i.cnstr >< 'PK'; 

SELECT N'ALTER TABLE '
       + QUOTENAME(i.[schema_name])
       + N'.'
       + QUOTENAME(i.table_name)
       + N' ADD CONSTRAINT '
       + QUOTENAME(i.index_name)
       + N' PRIMARY KEY CLUSTERED ('
       + i.key_columns
       + N') ON '
       + QUOTENAME(location)
  FROM #indexes AS i
 WHERE i.cnstr = 'PK';

SELECT N'CREATE '
       + CASE WHEN is_unique = 1 THEN N' UNIQUE ' ELSE '' END
       + CASE WHEN type = 'CLUSTERED' THEN N' CLUSTERED INDEX '
              ELSE N' NONCLUSTERED INDEX ' END
       + QUOTENAME(i.index_name)
       + N' ON '
       + QUOTENAME(i.[schema_name])
       + N'.'
       + QUOTENAME(i.table_name)
       + N' ('
       + key_columns
       + N')'
       + CASE WHEN included_columns IS NOT NULL THEN N' INCLUDE (' + included_columns + N')'
              ELSE N'' END
       + N' ON '
       + QUOTENAME(i.location)
  FROM #indexes AS i
 WHERE i.cnstr >< 'PK'
   AND i.location IS NOT NULL;

Links for the Week of 2009.05.15

SQL Server

Find Last Date Time Updated for Any Table Ever want to know when a table was last updated? Now you can find out. Thanks to Pinal Dave for this slick little piece of code, I was totally astounded to know that you could do that.

Why use stored procedures? A very well reasoned argument for the use of stored procedures from Paul Nielsen.

Development

More ASP.NET MVC Best Practices Working with ASP.NET MVC? I know I haven’t had a chance to do much so I’ve got plenty of room to mess things up. That’s why best practices from others in the field are important to pay attention to.

What’s in your svn:ignore? Anyone who has ever used subversion is well aware of the pains that come when you get preference files and DLLs in your source control repository. How do you prevent that? By mucking around with svn:ignore, of course! (This also applies to anyone using VSTSDD, by the way.)

Unit tests vs Integration tests Ayende Rahien sums it up pretty well in just a sentence or two. I’ve had problems making the distinction clear to people in a succint way in the past. No longer shall I be at a loss for words!

Stuff & Things

6 Small Things You Can Do When You Lack Discipline So being disciplined is the key to success, right? And you’re having problems staying disciplined, so that clearly means you’re a failure, right? Wrong. None of us are 100% disciplined 100% of the time. Check out this post from Leo Babauta over at zenhabits.net for some great tips to keep yourself going.

How to Learn a Little Every Day I cannot stress this enough: learning is the most important thing you can ever do. I say it all the time. When people ask me what motivates me, I always respond that my primary motivation in everything is learning. Here are some great hints from Dumb Little Man on incorporating getting your learn on into your daily schedule.

burning fight Awesome live concert photos from Matt Miller. You can hire him for your less noisy events. After looking at his portfolio I would say that you probably should hire him.

On Non-Disclosure Agreements Seriously, this is what you sound like. Stop it. Unless it’s for humorous purposes. In that case you can go NDA yourself.

Rated G for Nerdy Content

My fellow DBAs and SQL Server Developers, have you ever worried about being associated with other, perverted, developers who might use profanity or nudity in their presentations? Are you concerned that people might not know what kind of content to expect in your presentations?

Worry no more!

Even C++ developers can understand this!

Even C++ developers can understand this!

Now you can declare to the world that your presentation is free of filth and only contains worthwhile knowledge and information. No more will people confuse you with some kind of filth monger. No more will people cringe in fear when you mention your up time. Rejoice my fellow developers!

Links for the Week of 2009.05.01

SQL Server

Where isn’t there automatic <insert feature> in SQL Server? What’s great is that a co-worker and I were arguing about this very thing last night. He wanted to know why there wasn’t a ‘better language’ than SQL to use that would make it easier/more optimal to use functions while querying a database. I tried to explain that it wasn’t SQL that was the issue but dealing with a variety of optimizations and what not. I didn’t do a good job. Paul does a good job of explaining. Go read Paul’s take on things.

Microsoft Project Gemini links Occasionally I’ll get asked about Project Gemini links, usually right after I talk about the demos we were shown way back in November at PASS. Now I have a resource, thanks to Donald Farmer.

Analyze This – Analyze Your Indexes Part 6 Jason Strate concludes his series of articles on analyzing index with this amazing finale of a query.

Development

ELMAH: Error Logging Modules and Handlers for ASP.NET (and MVC too!) A great over view of an error logging/handling module. I hate writing this stuff, I really do. Why bother re-implementing it with minor variations? Why not just configure something? Now you can.

Is it time to move beyond 960? Cameron Moll dares to ask the important question: Can we finally make web pages for people with normal size monitors?

Stuff & Things

The #1 Secret to Building Your Skill Set is… I’ll the secret out: it’s discipline. Read on for some great tips from KBK.

… I have no words for how cool this is

Delicious Library scanning Have Delicious Library? Want to get a USB barcode scanner to work on your mac but don’t know how? Now you do.

This site is protected with Urban Giraffe's plugin 'HTML Purified' and Edward Z. Yang's Powered by HTML Purifier. 226 items have been purified.