|
|
|
|
-
So I am back hotel (yeah, not I won’t be “back home” until the 4th most likely) after speaking in Columbus yesterday, and I feel like blogging about how things went, perhaps to get advice on how you might correct/approach things. I do two sessions usually, a design fundamentals session that went well, with scores averaging 4ish out of 5. No real “bad” reviews, and a few pretty good ones. Then I looked through the reviews for the Patterns session and a few were pretty great, but a few more were negative (2 or 3ish), with most averaging 3.5 or so for my second session. That session must be corrected.. I think a few things went wrong (listed from least to worst). 1. The crowd was a bit unresponsive. This certainly could have been my fault, though I did hear the same thing from a few other speakers. Perhaps Ohioans' aren’t morning people? Perhaps they don’t like badly told bad jokes? no clue. One guy tweeted about it (http://twitter.com/dmmaxwell/status/17097085613). Still, can’t blame the audience for being themselves. 2. I was coming down with a bit of a cold. I didn’t realize it, but by the end of the day I felt pretty crummy. Again, just one of those things. It was only a minor factor, and not my first off day. 3. A lot of people don’t grok why I am saying what I am saying. They understand the presentation, and claim to know all that I am saying. They say “not intermediate, not technical enough”. Look, I realize that part of my problem is that I am trying to take a subject that takes me 100 pages to express in a book and do it in a 50-60 minute time block. The problem is “technical”. How do you make “design” technical. I spend a bit too much time on enforcing and understanding uniqueness and need a bit more stiff example of nulls. The list of sections is: •Normalization •Uniqueness •Supertype/Subtype •Generalization •Data Driven Implementation •Self Documenting data •Data Domains •Optional Data •Pre-calculated data In each section I talk about some of the table designs that could serve to deal with each and make things easier to implement. (Hierarchies is missing from the list if I had more time, but it just doesn’t fit in 1 hour.) The “reason” I speak on the topic of design is simple. Get the design right, and all of the other sessions you go to will become “next steps” in the process and not regular emergency rescue procedures. On the forums (which I haven’t been to in a while to do some writing, speaking and vacationing. Hey something has to give :) 90% of the questions people ask could be alleviated by good design. Even 90% might be an understatement. The fact is, design is all about following a very simple (to express) pattern: 1. Understand the needs of your customer and produce requirements. 2. Design structures that meet those requirements, following proper patterns starting with normalization and other common patterns and standards 3. Implement the structures. 4. Help programmers use your structures correctly (or at least do some review) The most technical stuff is writing CREATE TABLE statements, CONSTRAINTS, and maybe a trigger now and again. The rest of the work is programming (and another session :) I could teach a monkey to do syntax of commands. Step 1 is where 60% of the problem is (and is rarely in the data architect/programmers hands). Step 2 is the next 25% of the problem, as you need to end up with tables that match how SQL Server works best. 1% is in implementing, and the final 14 is in how the code is written. The problem is (and this is why I believe that so many people give up a Saturday to go to these events) every mistake is magnified in an inversely proportional asymptotic curve. Screw up requirements, and the programmers will have a mess trying to meet the actual requirements of the user. Build bad structures, and coding is that much more difficult. And so forth. A well designed database running on a great RDBMS will leave the DBA team in more of a Maytag repairman role. Never busy fixing stupid problems, only spending time upgrading capacity to meet customer needs. Happy customers means happy you. I am working to produce a new version of the session for Devlink and possibly PASS, so if you have ideas (if you have seen it or not), comment here, or if you want to be super mean, you can email me at louis@drsql.org. Either way, I just want to make the session everything it ought to be (whether that makes everyone happy every time, that is the goal anyhow).
|
-
Your task, model a database that represents a suburban block. You survey the area, and see the following houses (pictures culled from Wikipedia here) and  So you look at the houses, start modeling roofs, windows, lawn, driveway, mail boxes, porches, etc etc. You get done, and with your 30+ tables you are feeling great, right? I know I would be. “I knocked this out of the park! We can capture everything about these houses. I…am…a…superhero database modeler,” I think, “I will get a big promotion or a raise for sure! Shoot, I will get both!” So you show this model to the client and they say, “you’re fired. Do you even know what business we are in?” Well, no, I suppose not. That is the lesson for the day. Perspective. Unless you realize the perspective of the client, understand the problems they want to solve, you are missing the point. One of my “mind exercises” I play when travelling in a car, or at a theme park, or at a doctor’s office, etc is to think about how I could make the place better with database technology. During my family’s excessive trips to Disney World, when I am the slightest bit mentally bored I think about how I could fix things. (RFID in every ticket tracking and predicting next moves, stored in a database for reevaluating how to herd people like the lunch crowd at Tech Ed, for example.) But driving through a neighborhood the other day, it really hit me. There are many different ways to look at a block of houses, apartments, flats, etc and model them for usage (in addition to basic locator information like address and perhaps longitude/latitude). - Fire Department – hydrant to home to occupant ratio
- Sales – Number of windows, roof style, lawn, age of home
- Law Enforcement – Name of occupants, previous law enforcement “contact”
- Sanitation Department – Number of trash cans (including serial number for tracking), average amount of trash
And so on, but then I thought, what about the Sanitation Department. Take a side loading trash truck (http://vehiclestoys.guidestobuy.com/mack-granite-side-loading-garbage-truck): ` What if they weighed the trash as the loaded it, then kept records of how they weight varied. They could predict how much trash they could pick up and change routes accordingly. How else might this information be used? The information might also be interesting to law enforcement. This single family dwelling makes 80% more trash that all of their neighbors. Is this suspicious? Does it hurt to check it out? Is this getting too big brother? Maybe, depending on how the information was used, but it certainly might be used as evidence in addition to an actual complaint. Privacy concerns aside (not that you have any privacy in your trash, right?) It will be centuries before two government organizations work together that smoothly. It can take 2 change of address forms per government agency to move from one house to another. In the end of this technically rather soft blog, the point is that requirements govern the design. Unless you know why the user wants you to model something, you cannot do a good job of building a database to meet their needs. Sure you can build a cool database that stores everything that you can possibly ever desire about a subject, but does it meet the needs of the user? The only way to know the needs of the user is to study them, understand them, and put yourself in their shoes. Figure out their job and build from there. Adding a few extra bells and whistles to delight the user isn’t horrible sometimes, but missing the point is.
|
-
Now, don’t get too excited and grab your pitchforks and torches. Clearly, it is extremely possible to overdo something in the design, but very often normalization takes the rap as being the culprit. In my “Database Design Fundamentals” presentation, one of my favorite things to do is ask “What is the most important normal form?” 9 out of 10 times, someone answers “Third”. When I ask what they have against fourth, the usually say that it makes the database work too slow. But when they find out that most Third Normal Form databases are already in Fifth Normal Form, well, this fact has never actually slowed down any database that I know of. Under-normalizing is a very common problem, which is pretty much self explanatory. Most people don’t really understand it, or even really care about it. The basics of it are very straightforward, but the finer points (and why they are so important) are lost on many people who happen to be cobbling together some form of storage for the state of their objects (what we typically like to think of as a relational database.) But I am not even sure that by definition you could over-normalize. I will submit to you that almost every so-called over normalized is more precisely “over designed” and is actually just an architect taking a set of requirements and expanding them to meet what they felt the requirements should be. As an architect, I have a very large bag of tricks that I like to pull from to create the “perfect” solution. The problem is, users rarely want or even need “perfect”. Yet we always get really excited to start adding to what the user asks for. Normalization can only be done in the context of the requirements. If you defined every relationship in your requirements as 1-1, you could implement a fully normalized database in one table.. Every customer makes one order for one product. Done. Clearly reality is rarely so clean, and if the requirements stated this, you would not be doing your job unless you said “Whoa, are you..sure?” A great example of how databases get out of hand came during Audrey Hammond’s (@datachix2) presentation at SQL Saturday in Atlanta. Her example was of a personal movie review system that her (hopefully theoretical, slightly sadistic and certainly inappropriate time using) boss had given her to do. She came to a final example design that seemed to match the requirements that she had presented in one of her early slides. Her question, how would you change the model. Several of the people in the room had suggestions to improve the model, but most of the people were expanding the model to include stuff that they wanted to see in the model (I will admit, I wanted to do the same thing :). If we had kept going, we would have ended up with a data model that could be used to replace the guts of the Internet Movie Database (imdb.com, one of my favorite sites.) The problem was, while the ideas that had been good ones if we were trying to brainstorm items for the requirements, they were beyond what had been agreed upon for the implementation. The goal to create a personal movie review system is not exactly the same as the needs of the boss who want to keep up with a list of movies he has watched and a list of the important people in the movie that he wants to keep up with. Under the name of normalization, this sort of thing happens often. We add more and more tables to our model to take the design to larger and larger proportions implementing more and more things that seem like a great idea, but aren’t what the client wants. This is when the cries of over normalization begin to go up and cursing the name of Codd as if he was the person who over-engineered your database. I clearly don’t want to make it sound like as an architect you shouldn’t push to provide a solution that gets it right when the requirements are, shall we say, weak. Requirements are very often not thought through, and it is your job to recognize this and be certain that the requirements are changed to to reflect this, so you can create systems that implement what the user needs. Taking the user’s requirements as the final word for what they want is another poor practice. Users know what they do, not how to create databases (presumably that would be your job.) My rule of thumb is that: 1. The requirements dictate the database design 2. The requirements and the relational engine dictate the implementation So unless you understand the requirements, you can’t design the optimal database, and if you don’t understand SQL Server, you are not going to end up with an optimal implementation. Over-normalize? No. Over-engineer? Definitely.
|
-
Or any support people for that matter. I constantly hear people having to support this, support that, wearing the “beeper”, etc etc. But these people do seemingly love what they do, because I hear this on “non-essential” communications channels, like Twitter, SQL Saturday conversations, etc. These are people who are doing what they do because they like it. I have to be honest with you though, about the second time I was awakened by a beeper with the same problem I would be outraged. In fact I was, a long time ago. Luckily though, I worked for a company where I was the dba, programmer, and support for the database stuff. So when I had to do any support, I learned from the experience and fixed it so I wouldn’t have to do it again. This topic is basically centered around why I had an extra 45 minute this morning to write a blog post when I actually should still be in bed. I built an database transform/copy SSIS package that runs at 2:00 am. It is (for the time being) reliant on a database that gets restored by 1:00 am… only last night it was done at 2:15. The steps to drop constraints and truncate the table worked marvelously. The ones to reload… not so much… This is a new process and is currently in working development state (it is more or less done, but the code that uses this data isn’t actually complete yet. But still, my phone that delivers my corporate email buzzed before 8:00 am, and I noticed that it was an email from another developer asking “where is my data”. So I hit the computer and realized the bug… thankful it wasn’t something else. Even this little disturbance to my lying in bed getting ready to get up pattern is enough to make me wonder how dbas do it. Buzz…process failed. Buzz…process failed. Email… why is my data not ready yet. And they aren’t usually the one who created the mess. Often it is the data programmer, or even just programmers that are good with C#, not so good with that easy to learn easy to work with, no brains necessary T-SQL (I am paraphrasing the thoughts of more than a few programmers). What is the key to all of this… programmer (data and otherwise) care for the other person. When I was coding and supporting the databases, I learned to be mindful of a very good friend of mine, Future-Me. Future-Me is the recipient of everything I do. What I eat, what I do, and what kind of solutions I produce. Future me also gets pretty perturb as Current me when he thinks back to all of the stupid things he has said. Some people don’t even think about the future because they have no plans to stay in their current jobs. Me, well, I might leave some day, but I plan to stay forever. And a future of well built, well managed systems that always work sounds wonderful (unlikely in many ways, but wonderful.) I have always said that every programmer should be forced to do the job of the persons they are writing software for, using the software they created. 40 clicks to do a task during development sounds marginally okay, but if you have to do that task 100 times a day, that is 4000 clicks! Sometimes this is referred to as dogfood testing, like having the people who develop dogfood taste their food (since dogs do like ‘em some table scraps!) Frankly I would rather be an actual dogfood tester than need to click the mouse 4000 times for one of my tasks (plus a few thousand for Solitaire and you are bound to start an epidemic at your company of Carpal Tunnel syndrome.) I honestly should have considered the fact that the data might be delayed and implement something to protect against this. Either by timing, or by basically making the SSIS package check for the status/existence of the database. You can bet that I will make sure that happens. And if I was a dba that kept getting errors that others created… well, I don’t want to say I would revolt, but I certainly wouldn’t just grin and bear it. Hence the reason I talk so much about design. Good design begats good support patterns. Bad design begats something altogether.
|
-
Well, I have to admit when I got the invite to speak during this event, I was honored (and still am for that matter). But I have to admit, I hope people don’t come in with any belief that I will be Celebrating SQL Server 2008 R2. Most of what I will present could have been celebrated with SQL Server 6.5, as I will be doing my bread and butter Database Design Fundamentals session that I have done multiple times over the past few years. Ironically, had the people that you and I work with/for been using proper design techniques back, lo those many years, more of us could celebrate SQL Server 2008 R2 here in 2010* because instead of fixing data, dealing with fragile structures, and fighting the SQL Server engine, we could be exploiting all of the new stuff that Microsoft has given us in all of the new versions with relative ease (hey, just the compression stuff in 2008 and even more in 2008 R2 would be super wonderful to have, regardless of any other feature!) I will be presenting on the 20th at 6 AM Eastern time, which is actually 10:00 UTC, and even better time zones in Europe and more, so frankly I am pretty excited to have this opportunity to speak to the people I would rarely have the chance to, since I can imagine very few of the people I usually speak to will have the energy to listen to this stuff at 6AM on the east coast which is even worse as you travel west in North and South America. But hey, what is a bit of sleep, and since I am going to be on vacation with my wife at Disney World that day, this is actually a very good time slot, since the resort Internet should be screamingly fast at that point of the day. Bummer is that I won’t have time to attend any other sessions that day, but I will be consoling myself with the fact that when it is done I will head over to the happiest place on earth, possibly wearing these that I had the last time I was speaking in Orlando, though that was to live, in the room people, not a webcam: The session is a very interactive one, so I hope to have polls, questions, and any kind of interaction that seems useful though the assistance of my wife (whom I will be dragging out of the comfy bed also at 5:30 am (hey, I served as photographer for a conference she put on for free!) or, if all else fails, I will have a small, but loyal audience that will be making the trip with me on their portable bleachers: Their only problem is that they pretty much do whatever I tell them (except the LGM, he can get a little excitable at times) and while it is convenient for me that they only answer questions the way I want them to, they may not ask the questions that you want answered. If you have ever been to one of my sessions I can only promise that every time is quite different, and I have really focused the session of late. Doing it 5 times this year at several events including 4 SQL Saturdays, the Rocky Mountain Tech Trifecta, and a user group has really helped. In previous years, when the session was over (usually at PASS), my only concern was that it was over. But knowing I was doing it again in a few weeks time, well, I want to take all feedback immediately from attendees and myself and keep progressing. So, I hope to see you in the attendee list! *(the big reason I hate using the year in the name of the product!)
|
-
A few weeks back (Feb 27) I spoke at the Rocky Mountain Tech Trifecta (http://rmtechtrifecta.pbworks.com/), where I gave the SQL Track keynote, and then did my Database Design session. Great time and I had a blast giving a keynote. It was especially fun just doing a lightweight session just encouraging folks to do design. Last week, I spoke virtually for the Minnesota PASS group, giving the same presentation, plus 10% and including my patent pending Lego audience (The Minifiggers) and audience members that provided me with feedback and answers to my questions that I commonly ask during the presentation. Doing a virtual presentation is interesting, because as exciting as my Minifiggers are, they have plastic faces and don’t let me know when I am confusing them, or when they find my jokes funny. That was the past.. Over the next 4 weeks, I will be speaking at 2 (and probably 3) SQL Saturday events in Birmingham, Richmond, and hopefully Atlanta. Each time I will be doing my database design session (which has changed 40% since last week), and my database design pattern session (which I haven’t started going over again, but it will likely change from the last time I gave it last year. The abstracts are: Database Design Fundamentals In this session I will give an overview of how to design a database, including the common normal forms and why they should matter to you if you are creating or modifying SQL Server databases. Data should be easy to work with in SQL Server if the database has been organized as close as possible to the standards of normalization that have proven for many years. Many common T-SQL programming "difficulties" are the result of struggling against the way data should be structured and can be avoided by applying the basic normalization techniques and are obvious things that you find yourself struggling with time and again (i.e. using the SUBSTRING function in a WHERE clause meaning you can't use an index efficiently). Database Design Patterns Beyond database design fundamentals (for example, Normalization) lies the area where you have to create "real" solutions. In this session, I will cover a good number of patterns that we commonly find useful to try to apply to the problem of building a database solution. Ideas like generalization, subclassing, single table domain tables, optional data, and more will be discussed, some of them good, some not so good (don't assume which will be which), but all that are common and/or useful for your database implementations. After these three stops, I don’t see myself doing much speaking until Devlink (if accepted, if not I will be attending!) and/or PASS (again, if accepted) as well as at least one other opportunity that has not been scheduled yet (all hush hush and whatnot). If you need a speaker for your user group that is within 6 hours drive from Nashville, I will be happy to come sometime, or anywhere if you provide me transportation or let me present virtually. So hope to you see you (not you, I was pointing at.. well, ok you too) at one of these stops for a fun talk about database design. Yes, I said fun. And the first step to good performance is Normalization, not Denormalization. Both true statements.
|
-
Is the world ready for a Louis Davidson keynote address? Luckily the entire world won’t have to find this out, but a hundred or two folks in Denver next weekend will serve as test cases for just that (http://rmtechtrifecta.pbworks.com/Schedule). Ideally, you will laugh a lot, cry a little, hear very little profanity (if this occurs, I am probably a bit out of my mind), and see at least 2 pictures of my grand child. Oh yeah, and there will be at minimum of one sing a long (no I am not kidding, though I rather don’t expect much participation.) I will insult everyone in the room at least a little, though mostly just their coworkers who are too lazy to get up at 9:00 on a Saturday when the Olympics are still on and listen to me pontificate on such subjects as: professional development, why database design is so important (and actually design of anything one might be trying to build!), proper filling of a Lego pick a brick cup, and how being a mile over sea level can make certain people delirious (the first two will be planned, the latter one just are “possible” topics.) And just be warned, when I pull out the very large mallet and a watermelon, the first few rows get wet, so bring a rain coat if you want. If nothing else, I hope to have a lot of fun pictures for you to look at, and a lot of quotes from my favorite philosopher types. Of course, as this is my first presentation of this sort, I might just freak out, start screaming and run away. Probably not, but be prepared for anything. I know I will be.
|
-
Haven’t posted anything useful in a while, so I figured I should. This was something I was building for a coworker the other day, and I find the best way to flesh out a solution is to think about how it will work for the thousands who might see this post, and the hundreds that might actually read it. My next post figures to be an updating of my calendar table queries here on my sqlblog.com blog (since I have pretty much abandoned my spaces blog for now. Another new feature I am going to start is to include a download of the pertinent source code for posts like this. So the create table and insert statement will be in a link at the end of the post. One of the posts that I am kind of proud of was my initial post on how to build a date table here. I use that script any time I want to create a date dimension for a warehouse, or for some other application. The last use was a time entry system, where I extended it to include work_week, which instead of being Saturday - Sunday, as a normal week is, is defined as Monday - Sunday (Yeah, that way extra time on the weekend is part of the same week.) But I digress. Recently, the need came up to do groupings of data on the hour of the day, for call center tracking. When I heard the person who would be doing the coding start to say something about using datepart and such, I said, "I know a better way". If you can calculate the number of minutes past midnight, then I could do the rest with relative ease, much like their current experience with the date dimension. In the end, the hardest part of using the date dimension is the calculating of seconds past midnight. Not hard so much that it is really difficult, but hard to explain. Basically you use the old stripping the time off of the datetime trick: DATEADD(DAY, 0, DATEDIFF(DAY, 0, <referencedColumnName>)) This is a neat trick, datediff(day,0 returns a number of days since the base date for the type, either smalldatetime or datetime, and dateadd(day,0 converts the integer to a date value. Quite fast, and you end up with a datetype without having to cast the value (I have to explain this to everyone I introduce it to, so if you already got it, I am sorry). Then use datediff to see how many seconds have passed since midnight: DATEDIFF(mi,DATEADD(DAY, 0, DATEDIFF(DAY, 0, <referencedColumnName>)), <referencedColumnName>) Simple enough, really, just a bit untidy to type. In reality, if this is a commonly used value for a table (particularly if you have a datetime value in one of your dimension tables), you can just add a computed column to your dimension (probably essential to use the PERSISTED keyword to ensure it is only calculated once). alter table <tableName> add <columnName> as (datediff(mi,DATEADD(DAY, 0, DATEDIFF(DAY, 0, <referencedColumnName>)), <referencedColumnName>)) persisted Now, the basics are a table that has a key of the number of seconds past midnight, with the types of attributes you might typically calculate, as usual, it is very likely that you will have some more you might want, or less, depending on your organization. Like if everyone had a fixed lunch time, you could add lunch_time, and include the minutes of the lunch time in it. Then you could compare, say internet bytes/second during lunch versus work hours. First create your table. I have called it time_of_day, using my typical naming convention of having reporting tables named with underscores. I have commented on each column as to its meaning. set nocount on go create table time_of_day ( time_of_day_key smallint primary key, hour_of_day_24 tinyint, --0-23, military/European time hour_of_day_12 tinyint, --1-12, repeating for AM/PM, for us American types am_pm char(2), --AM/PM minute_of_hour tinyint, --the minute of the hour, reset at the top of each hour. 0-59 half_hour tinyint, --1 or 2, if it is the first or second half of the hour half_hour_of_day tinyint, --1-24, incremented at the top of each half hour for the entire day quarter_hour tinyint, --1-4, for each quarter hour quarter_hour_of_day tinyint, --1-48, incremented at the tope of each half hour for the entire day string_representation_24 char(5), --military/European textual representation string_representation_12 char(5) --12 hour clock representation sans AM/PM ) go Then we load the table from --digits gives you a set of 10 numbers 0-9 with digits (i) as( select 1 as i union all select 2 as i union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9 union all select 0) --sequence produces a set of integers from 0 - 9999 ,sequence (i) as ( SELECT D1.i + (10*D2.i) + (100*D3.i) + (1000*D4.i) FROM digits AS D1 CROSS JOIN digits AS D2 CROSS JOIN digits AS D3 CROSS JOIN digits AS D4) insert into time_of_day(time_of_day_key, hour_of_day_24, hour_of_day_12, am_pm, minute_of_hour, half_hour, half_hour_of_day, quarter_hour, quarter_hour_of_day, string_representation_24, string_representation_12) --calculates the different values for the time table SELECT i as time_of_day_key ,datepart(hh, dateval) as hour_of_day_24 ,datepart(hh, dateval) % 12 + case when datepart(hh, dateval) % 12 = 0 then 12 else 0 end as hour_of_day_12 ,case when datepart(hh, dateval) between 0 and 11 then 'AM' else 'PM' end as am_pm ,datepart(mi, dateval) AS minute_of_hour ,((i/30) % 2) + 1 AS half_hour --note, I made these next 4 values 1 based, not 0. So the first half hour is 1, the second is 2 ,(i/30) + 1 AS half_hour_of_day --and for the whole day value, they go from ,((i/15) % 4) + 1 AS quarter_hour ,(i/15) + 1 AS quarter_hour_of_day ,right('0' + cast(datepart(hh, dateval) as varchar(2)),2)+ ':' + right('0' + cast(datepart(mi, dateval) as varchar(2)),2) as string_representation_24 ,right('0' + cast(datepart(hh, dateval) % 12 + case when datepart(hh, dateval) % 12 = 0 then 12 else 0 end as varchar(2)),2)+ ':' + right('0' + cast(datepart(mi, dateval) as varchar(2)),2) as string_representation_12 FROM ( SELECT dateadd(minute,i,'20000101') AS dateVal, i FROM sequence AS sequence WHERE i between 0 and 1439 --number of minutes in a day = 1440 ) as dailyMinutes Go You can see the values by using SELECT top 5* FROM time_of_day returns: time_of_day_key hour_of_day_24 hour_of_day_12 am_pm minute_of_hour half_hour half_hour_of_day quarter_hour quarter_hour_of_day string_representation_24 string_representation_12 --------------- -------------- -------------- ----- -------------- --------- ---------------- ------------ ------------------- ------------------------ ------------------------ 0 0 12 AM 0 1 1 1 1 00:00 12:00 1 0 12 AM 1 1 1 1 1 00:01 12:01 2 0 12 AM 2 1 1 1 1 00:02 12:02 3 0 12 AM 3 1 1 1 1 00:03 12:03 4 0 12 AM 4 1 1 1 1 00:04 12:04 To use the values, I will create a test table, in this case to simulate a phone call for a call center: create table testPhoneCall ( TestPhoneCallId int identity primary key, callType varchar(10), callTime datetime --the point in time of the call ) Obviously a real table would have more columns with more descriptive information, but this will do for our purposes. Using the following insert, I will load the table. Basically I am trying to set about 70 percent of calls to incoming, and then at some random time of day, within 2000 days of 20010101. The go 1000 will load the table with 1000 rows. insert into testPhoneCall(callType,callTime) select case when rand()> .7 then 'Incoming' else 'Outgoing' end ,dateadd(minute, rand() * 1439, dateadd(day,(rand() * 2000),('20010101'))) go 1000 Taking a look at the data select top 10 * from testPhoneCall You should see something along the lines of: TestPhoneCallId callType callTime --------------- ---------- ----------------------- 1 Outgoing 2002-10-23 06:46:00.000 2 Outgoing 2004-03-23 14:27:00.000 3 Outgoing 2001-01-13 11:45:00.000 4 Incoming 2002-04-29 03:41:00.000 5 Outgoing 2005-06-30 01:19:00.000 6 Outgoing 2002-06-30 13:15:00.000 7 Outgoing 2005-11-13 06:03:00.000 8 Outgoing 2003-01-01 04:56:00.000 9 Outgoing 2004-09-04 12:26:00.000 10 Outgoing 2005-09-28 08:47:00.000 To use this data with our time_of_day table, we need to get the number of seconds past mighnight the data is. Using the trick to get the date without time: DATEADD(DAY, 0, DATEDIFF(DAY, 0, <datevalue>)), I datediff by minutes the timeless date, and the date value with time. You can do this in a query, or a view, or in my case, I am choosing to add this to the table as a computed column (which is what I am doing with my data warehouse table that sparked this need: alter table testPhoneCall add callTimeOfDay as (datediff(mi,DATEADD(DAY, 0, DATEDIFF(DAY, 0, callTime)), callTime)) persisted --persisted means it calculates at save time, not run time Now, we can join to the time_of_day table with our new callTimeOfDay columm, and find out how many calls were in the AM, and which were in the PM select time_of_day.am_pm, COUNT(*) as numCalls from testPhoneCall join time_of_day on time_of_day.time_of_day_key = testPhoneCall.callTimeOfDay group by time_of_day.am_pm And since we used a random number, it should be about even, and it seems to be: am_pm numCalls ----- ----------- AM 494 PM 506 And you can mix in data from your table, like the call type, and then see what percentage of calls were in the which half of the hour and if they were incoming or outgoing calls: select testPhoneCall.callType, time_of_day.half_hour, COUNT(*) as numCalls from testPhoneCall join time_of_day on time_of_day.time_of_day_key = testPhoneCall.callTimeOfDay group by testPhoneCall.callType, time_of_day.half_hour This returns: callType half_hour numCalls ---------- --------- ----------- Incoming 1 157 Outgoing 1 352 Incoming 2 155 Outgoing 2 336 It is a simple as that. Keep in mind that using a table to do time calculations will not always be faster. Using the functions can be faster, though whenever you are doing groupings/joins a time/date table will often be faster but will always be more convienient. To download the code for creating and loading the time_of_day table, follow this link: timeTableCreateAndLoad.sql
|
-
I was tagged by Glenn Berry in the meme that Paul Randal started a few days ago, so I need to tell my story to keep it going. So here goes. A Girl, A Guy, and a Tennis Racket When I was a young fellow, I liked a girl. She liked me. Unfortunately (at the time) and fortunately (in clear hindsight, knowing what I know now), the definition of like was much much different. Eventually, she introduced me to her boyfriend, who became my best friend throughout college. I met my wife through a friend of his (whom she was dating at the time.) His friendship changed me from a super introverted geeky guy who would probably have been first on the list to be interviewed if some incendiary device was used on my high school to a simple introverted nerd. He got me my first job in IT working with databases, and really helped me see how computer science was the place to be (though he wouldn’t consider what I do “programming” as last I remember he was a hardcore C++ programmer). He wasn’t like a perfect influence of course, and we spent many school hours playing Gauntlet (the video game) and/or Tennis (the real sport), and later when I was finishing my degree, and he was finishing his Master’s, golf. And honestly I spent more time with him than I did with my own family at times, causing a lot of grief. We lost touch due to some “stuff” that happened, and I haven’t seen him in 17 years now, but honestly his influence on me continues today. A Move to a Beach The day I lost touch with him was the day we moved from Tennessee to Virginia Beach to work for CBN (whom I have worked for since then except for a short stint at a dot-com in Nashville. This was the day my family truly came together. We moved from our families, friends, etc, and started to only influence one another. The first years there were the best years in many ways, as it was before my wife or I got important/time consuming day or night jobs. So in part it was just a great thing for us as a family. The other half of the equation was that I was given an amazing chance to learn and grow. I started as a DB developer in Cleveland, TN, with a guy who was pretty good, so I was a solid newbie. But CBN let me go to several database design/programming classes, and was instrumental in encouraging us to speak at conferences. Another factor was that several people I worked with who really knew relational databases and I was able to really educate myself in ways that are often impossible for some people. Add to that spending a few nights and a few weekends doing this stuff over time, and my career was given a great push… Being Critical of Other People’s Work Led to Other People Being Critical of Mine About 11 years ago, I was attending one of those conferences where I was speaking (which was due to my bosses influencing me to speak) I met the guys at WROX press, who needed tech reviewers. I got involved and by doing a good job, in an email exchange with the editor, something was said like “would like to work with you again” and I said “Sure, and if you ever get a book on database design, I would be more than happy to review it”. The reply was “Good idea. Why don’t you write it.” The rest is painful, glorious, painful, painful, wonderful history. Looking back on the first version of my book, you can see that I didn’t know enough to write a book. Stuff like terminology was all over the place, and some of the stuff in the book was not super. But it wasn’t bad either. Granted it took me 9+ months working 30+ hours a week (plus quite a few weeks of vacation, though I didn’t miss any of my daughter’s school activities!) to finish the book, and the brutality of the comments from tech reviewers was very painful at times (some were pretty snotty, actually, but in retrospect most were spot on.) That book was that last turn in the road that delivered me to where I am today (which is good, because every time I think about how long it took, I realize that I could have went back and worked for Wendy’s and made a lot more money than I did on the book!) So am I suggesting you all go out and write a technical book? No way, and it has nothing to do with not needing the competition (well, not *everything* to do with it). The fact is, unless you are truly gung ho and ready to spend lots of time on a book, you will hate yourself. I forget where I first heard it, but some famous person was quoted to have said that it is a wonderful thing to have written a book. It is like being a parent in many ways. It is great to have a 20 year old daughter. And while the process up to that age was a labor of love, it was always a little painful, worrisome, scary, etc, etc. Worth it? Of course. But if I woke up tomorrow 20 years ago knowing what I know today, after I put a bed down on Superbowl 24, I would be pretty frightened. Back then it was an adventure, just like every camping trip you go on when it is sunny when you leave and raining actual no fooling cats and dogs by the time 10 minutes after you are in your tent, which promptly blows away. I can sum up my advice in two sentences: 1. “The only thing worse than writing that book you have in you, is not writing it.” 2. “If you can think of nothing you would rather do than write a book, then write it, otherwise run away” Runner’s up Mostly because I didn’t include my wife or child in the list as much as they deserved (if it was a top 100, 50+ would include some action from them), I need to include my list of runner’s up items. There have been so many other events that made me what I am, and I wouldn’t have survived without my wife and child, who are my best friends of the past 17 years. Barely a day goes by that I speak with the child (who isn’t a child anymore, as I previously mentioned) and certainly none goes by without talking to my wife unless one of us is REALLY busy. So that list includes, but is not limited to: Day I got Married; Day I became a Father; Day I became a Grandfather, Day I first ate hot chicken; Day I become an MVP; Flunking out of Engineering; Give up on becoming a Mathematician; Working with Paul Nielsen; Meeting Arnie Roland; Meeting Kevin Kline; Meeting Joe Webb; First PASS Conference; Day I ate my first McRib. Honestly, these are almost as important as those three, but in terms of being influential to my career not quite as much. I will tag Paul Nielsen, because working with him has really elevated my game and speaking abilities, and I wonder what got him here. Also Kevin Kline, because with a name like his, I should get a few more hits to my blog. Plus, I will bet his are pretty interesting
|
-
Darn it, when I get my reviews back from a conference, I want them to say “Perfect”, “Wonderful”,”The best conference I have ever gone to, bar none”, and no matter how many times I offer to fill in the evaluation forms from people, well, let’s just say that there are always a few people who don’t say these things. I saw Grant Fritchey’s post, and started mine, then saw Marco Russo and Andy Leonard’s while mine stewed overnight… So I am clearly not the pioneer here. In reality, this was probably my best set of evals ever. One year, I was the fifth lowest in the list. Fifth…lowest. I was very much on the verge of quitting at the time. But frankly my friend Wayne Snyder gave me the best advice ever. Who cares what they think, just speak about what you care about. (At least I think it was Wayne, we have had a few memorable conversations over time, and I think we were standing in the front of a bus at the time, but I digress). As a person of (ahem) alternate shape, I have a lot of self consciousness pent up left over from my high school years, and to be honest, I often get that fear of people laughing at me going around and around in my head. In the end I realized that I wanted to try to end the poor database craptacular explosion that (from the examples I have seen) has been spreading throughout the world. Imagining that the audience is all dressed in bright blue bunny eared parkas doesn’t hurt either. In the end I know I write better than I speak, and one comment was “'Work on the delivery; otherwise, good content.”. I am just glad this person wasn’t leaving comments five years ago :) The session was database design, and on a five scale, the ratings this time were (giving a 1 to “very poor” and a 5 to “excellent”: | How would you rate the usefulness of the session information in your day-to-day environment? | How would you rate the Speaker's presentation skills? | How would you rate the Speaker's knowledge of the subject? | How would you rate the accuracy of the session title, description, and experience level to the actual session? | How would you rate the amount of time allocated to cover the topic/session? | | 4.475 | 4.675 | 4.85 | 4.7 | 4.525 | Not shabby, and I am certainly happy that the highest score was for knowledge :). A few “poor” ratings, and one very poor (a 1) for the usefulness..Fair enough. Lots of excellent. I am never quite sure what people are expecting from a topic of Database Design, and I generally talk at a high level, briefly cover normalization, give some examples, and “bam!” an hour is gone. I tried to do more in the past, but we always got hung up and never made enough progress. At SQL Saturday events (which I have done two, and am doing the Richmond event Jan 30) I add a patterns session where I talk about the patterns I like to use to solve common problems. Still high level stuff, admittedly. I have commonly used a lot of jokes/lists to keep the mood light and keep people from leaving the room after they realize they had gone to sleep and were drooling on their conference materials. (That is really not cool!) And to be honest, the old adage of making be laugh as a deflection is quite a useful tool. But, a couple of the comments were: "'Funny but a lot of stop and go." and "I would get rid of our 'lists.'" So they are gone! Okay, not gone, but I have been thinking of de-emphasizing them for a while. I am possibly doing a keynote later this year and I want to replace some of the lists with a more sermon-esque half-rant about the value of database design. I certainly am not going to lose the humor, but lowering the content will be good. In any case, thank you to everyone who fills out your evals at conferences in a reasonable manner and leaves useful comments. We do read them, and we listen when they are not shouting/whining/insane. Like the person who commented “I hate to give all 5's, but Louis deserves them.”, that is the kind of constructive criticism a person likes to hear. In any case, hope to see you in November, or at least sometime soon at an event.
|
-
My family used to send out Christmas cards with a yearly report of "where we are from whenst we came from" report, but some years we depressed people, but too often it sounded like bragging. This year I could neither brag nor depress, for it has been a pretty even Steven kind of year. Some medical stuff, but had a really good year SQLwise. Kept the MVP, wrote some good blogs that will make up a chapter of my next design book, and finally hit a nice stride when speaking (big thanks to Paul Nielsen, as speaking with him has really helped me see what I did right (and wrong!) But here at the end of the year, it is definitely the custom to send out cards to people. As a guy, I am not really into the whole “physical” card thing, but I like writing SQL. So I figured I would combine the greeting thing with the SQL thing. The following script, when run, will, Mad Libs style, spit out a personalized holiday message from me to you. A little personal, a little SQL. If you are not so equipped to run the script, email me at louis@drsql.org and I will translate. Of course, I am more than happy to take any other types of messages there too (other than ones that pertain to my lottery winnings or any sort of personal products to enhance my life by emptying wallet. Those are right out.) For those who lack the desire to spend the effort, Merry Christmas, Happy New Year, etc. I love this community of SQL folks as a really interesting extended family (frankly I see a lot of you more than my family at various events :) But hey, if I was gonna say much more then the following SQL would be a waste of time, huh. I will note, if you say you don’t celebrate Christmas, but you do believe in Santa Claus, you won’t cause your computer to burn up with a paradox, but I did default it to a lack of belief in Santa, cause frankly, I figure the largest contingency of my readers are the ones who have to buy the gifts, not wonder where they came from :) See you in a week with my SQL New Year’s Resolutions! declare @name varchar(30) declare @celebrateChristmasFlag bit declare @presentYouWant varchar(100) declare @believeInSantaFlag bit set @name = 'Friend' --<Your name here set @celebrateChristmasFlag = 1 set @presentYouWant = 'Quad Core Netbook with eternal battery' set @believeInSantaFlag = 0 set nocount on select 'Hello ' + @name +',' union all select case when @celebrateChristmasFlag = 1 then CAST(0x4D65727279204368726973746D61732C204861707079204E6577205965617221 as varchar(40)) else CAST(0x536561736F6E73204772656574696E677321 as varchar(30)) end union all select '' union all select CAST(0x492077616E7420746F207769736820796F7520616E6420796F7572732061207665727920686170707920686F6C6964617920736561736F6E as varchar(60)) union all select CAST(0x66726F6D20616C6C206F6620757320617420647273716C2E6F7267202877656C6C206974206973206A757374206D652C207265616C6C7929 as varchar(60)) union all select '' union all select CAST(0x5468616E6B20796F7520666F722072656164696E67206D7920626C6F672C20616E64204920686F706520796F752077696C6C20636F6E74696E7565 as varchar(60)) union all select CAST(0x746F207265616420696E20746865206E657720796561722C20616E6420796561727320746F20636F6D652E204920686F70652074686174 as varchar(60)) union all select CAST(0x796F7520676574207468617420 as varchar(20)) + @presentYouWant union all select case when @believeInSantaFlag = 1 then CAST(0x66726F6D2074686520626967206A6F6C6C7920677579206E616D65642053616E746120436C61757321 as varchar(60)) else cast(0x66726F6D20736F6D656F6E6520796F7520646F6E27742073686172652061206372656469742063617264207769746821 as varchar(60)) end union all select '' union all select cast(0x53656520796F7520696E2074686520636F6D696E6720796561722120204C6F756973 as varchar(60))
|
-
Ever since the early days of laptops, I have looked for the “perfect” device. Something with excellent battery life, very portable, and useful for writing. I like to write, you might have noticed. I also like gadgets. The goal being that whenever I get an idea, I can get it down quick. My first try was to acquire some form of PDA device. I have tried almost ever version of Pocket PC, including the one the looked a lot like a PC, though much much smaller (It was made by Phillips, I think it was called a Handheld PC). None of these has ever exactly hit the mark, though they all have had good points. My current Samsung i760 phone does pretty well, but not great for writing long stuff though it does a very good job at quick note-taking/short writing device because it is with me 99% of the time. I can whip out a few paragraphs, and on rare occasion a full blog post, but no matter how good of a thumb typist I might be, it is generally overly tedious to do more than a page or so on the device. Include the fact that the form factor makes a little text seem much larger than it actually is, and it just isn’t even vaguely a good enough writing device. (I am hoping the next version of Windows Mobile 6.5 or 7 will give me more satisfaction, but who knows.) On the laptop side, I have always used one as my work computer. The problem there has always been weight to power to battery life ratios, I have a DELL M4400 with a 3 cell internal and a 12 cell slice battery, and I still only get about 4 hours, tops. All that battery makes it heavy. Really heavy, like Van Gogh with a side of Escher mixed with a bit of Dal.. oh wait, that is a different kind of heavy. I mean it weighs like 9+ pounds. The Dell is a very solid workhorse, dual core, 4GB, 1920X1080 video, but it is just a big old thing to lug around (and no, quad core was just too much when I got it a year ago). The only real feature that makes it a great mobile device is backlit keys. This is the feature I truly love, (and the awesome resolution) but it is just too much trouble to lug this thing around just to write a blog post…It is great when I travel for business, as the 1920X1080 video rivals even decent workstation video, and at home I have a writing tablet that it is attached to that make it a great workstation (plus I use it to remote control a quad core 8GB workstation a lot of the time.) So recently I resolved to get a machine that is small, powerful enough to run Word, Live Writer and an edition of SQL Server that I could use all day long. So I started looking towards the mini / netbook class machines. When I started this post, I had just purchased a HP MINI, 110-1125NR netbook as the answer. I was pretty impressed with it, but I struggled a bit with the resolution at 1024 x 600. Even the keyboard was quite nice and I got used to it in a few hours (I never thanked my dad nearly enough for making me take typing!) I installed Office 2010 pre-release, SQL Server 2008 Express Edition, Windows Live tools, and it all ran pretty nicely. I carried it around PASS for the most part, though I didn’t have everything completely set up on the new mini so I had to lug the monster around. I did do most of my Powerpoint editing on the device which worked pretty nicely. And this was with 1 GB and Windows 7 Starter edition, which had one limitation that irked me… the inability to change your desktop theme. That is going to annoy many netbook users, as their entire goal is a status symbol thing. I do like having vacation location pictures on my desktop, but I would have lived with that… When I got home, the wife coveted the new device, and as I was keen to up the resolution, I gave it to her and I got to search again. My theory is that way more than 50% of the delight in any task is the anticipation, and so it was fun. I narrowed it down to a 11.6’ Gateway machine with an Athlon processor, the same HP device, just upgraded to the HD video, and a Toshiba Satellite T115-S1105 (The Dell machines seemed pretty nice too, but still had to order it custom to get what I wanted.) Battery life on the Gateway was just 5 hours, and I wanted more battery. The HP had to be ordered, and to get it right made it more like 450 than the original 350, then tax and shipping made it too expensive. The Toshiba won out as it had ridiculous 9 hours + battery, DDR3 memory, 2 GB of ram (with an open slot available for another 2 GB), N wireless, and a 250 GB hard disk, 1366x768 video, HDMI output (excellent for hotels with LCD TVs) and Win 7 Home Premium instead of Starter. All for 479 from Amazon. The keyboard is very nice, and I didn’t have to get used to it much at all. It has a nice trackpad, a Pentium class processor (single core, low power… A Celeron Edition is available for ~30 less too), and runs quite nicely. I don’t have any really large databases on the machine, as I mostly test syntax and stuff for forum posts and blogs when I use SQL Server on the machine. The only con is size. The step up in video size makes the machine seem almost laptop sizes rather than a mini PC size. It only weighs 3.5 pounds with a 6 cell battery, and they make a 12 cell…18 hours between charges? Might have to get into that. I am even getting 6 hours with the addition of my USB device from Verizon. The lack of a DVD drive is an expectation of something with 9 hours of battery on 6 cells, and frankly with the excellent MagicCD tool and the fact that everything I need I generally get from the web either in Isos (from MSDN) or installers from the web. Since a device like this will often need to entertain you as well as let me write (sometimes simultaneously), I have tested a lot of the video sites. It does streaming video great from the Move family of players (ESPN360, ABC), as well as Silverlight (Netflix) in excellent HD quality. Hulu video is decent, but not at the highest quality (low quality is smooth, and looks good enough on the 11.6 screen). With VideoLAN and Zune both, video looks great. Like all computers, it of course comes with a bunch of weird bloatware apps that almost immediately get removed, but also a few useful ones.. The coolest that is worth sharing is the hard disk protection service. It includes a 3D viewer that lets you watch the heads of the drive move, and shake the PC a bit and the heads/platters move to a safe position: -
 -
Cool stuff, though frankly I haven’t even thought about the hard disk heads in quite a long time. I know the Dell I have also has something like this to protect against a drop harming your precious data. All in all it seems like it is going to be a good friend for a few years to serve as my writing notebook and travel companion. Since I can keep it lean and not install most of the stuff you need to program/do your job, it should be fast enough for most anything. I have already noticed that I carry this laptop far more places than any of my previous ones, due to portability, and battery life. So if you see a guy sitting in a restaurant with a computer with too many stickers on it like so: -
-
Stop and say “howdy”. -
|
-
Yeah, yeah, I know. PASS ended two weeks ago. Well, not for me. The effects of 5 days of standing and walking and standing and walking took their toll on my post operative hip and I went down for the count. Finally things have calmed down and it is time to do what I should have done before. Basically, this was quite a good conference, with lots of great connections made, and a chance to reconnect with what are becoming old friends after 10 years of attending. The effects of budget cuts were very apparent, with no volunteer gathering this year, far less snacks, etc. Luckily, one great thing about the Seattle location is that there are several places to get your own food including a Subway, and a pretty good Baja Mexican restaurant. Next year, if there isn’t a gathering paid for by PASS, we need to do it anyhow. Bowling the year before was a lot of fun, and I would have happily dropped a Jackson or two to hang out and bowl or play pool before the conference. I arrived on Sunday evening, still with plenty of stuff to do to get ready for the week. Ate some dinner at the Daily Grill, Paul Nielsen and I went back to the room we were sharing and continued prep for our Friday Post Con on database design. Biggest lesson learned that day, use your sinus meds when sharing a room. Apparently if not you snore a “bit”. Monday Monday was a busy day, with a snippet of an Insider session and a couple of PASS meetings. Really good stuff that I need to relay back to my Nashville SQL Server User group buddies. The we moved on to Quiz Bowl. After all of the years, different configurations, etc, we finally hit upon a method that worked best. New software to run the Quiz Bowl was purchased (here) and it worked really nicely. And add to that that we used “celebrities” instead of random people from the crowd, we had a much better set of contestants. In the past we had tried many different configurations and unfortunately had always ended up with one really good contestant, and some not so decent ones. Paul Randal and Kimberly Tripp proved they were up to the task, and beat the other teams of Kevin Kline and Brent Ozar, as well as Joe Webb and Grant Fritchey. Next year it will likely be more of the same, but who knows. Tuesday Slow day, with the biggest thing for me was the “Birds of a Feather” lunch, where I hosted a table for database design, along with Paul who tried to do a starting an ISV table, but abandoned it quickly to talk database design. The day was finished off with an Insiders party, but I left early to go back and get some work in prep for Wednesday. Wednesday This was a really long day for me, and started my downward slide mentioned in the opening italicized paragraph. It started off rough, with a Quest sponsored breakfast where four speakers tried to do way too much with little prep and even less bacon that we were promised (the sausages were good :). I especially tried too much, and left the crowd less than satisfied (I feel). Got plenty of good comments (and a few negative ones in the feedback,) and I immediately (during the keynote on my new mini-PC, which I will review in my next blog, and which I am typing right now) put together a blog entry on the Disk IO stuff I tried to cover. Will blog the performance monitor DMVs in the upcoming days. Next up was the most rockstar moment of my life. We had a book signing for the SQL Server MVP Deep Dives book. I signed (along with the other nerdiariti who wrote and/or edited the rest of the book) like 150+ copies. Very definitely a cool project and a cool feeling to sign so many books (even a few for the higher ups in Microsoft.) Then I had my database design session. I have finally become comfortable enough with the material (which you can download here) that it goes smoothly and even fits into the allotted time span…I just to run way short of time, but now the presentation seems short (hence the reason why did a post-con on Friday.) Didn’t make any sessions because I ended up standing around talking for the entire day. Wore me out, but one of the best things about PASS is the community, meeting new people and keeping up face to face relationships with everyone you have met throughout the years. From there I bailed on the party at Gameworks and got some rest. Thursday On Thursday, I hit a couple of Insider’s sessions, and then the second rockstar feeling moment of the summit. Did an interview with Joe Celko and Paul Nielsen for the Midnight DBA crew. Oh yeah, and Buck Woody happened in as well for a section of the interview. Will post more when (if?) it shows up on their site. It was pretty wild at times, and Sean and Jennifer McCown were a lot of fun to hang around with for a couple of hours. Frankly I still don’t feel like I am worthy of being interviewed with the likes of Joe Celko. Why? Because like most technical people, I am not a pioneer of anything. Joe Celko was a part of getting SQL to where it is, and even Paul has some nifty new stuff with his Nordic Object Relational framework. Rather, I take the work of others and attempt to make it accessible to the masses. When I was in college, the academic stuff went over my head, until I finally tried it and got it. Won’t say more because I have said it all before. I actually went to a couple of sessions this day, including a few on virtualization (something we are getting ready to do in a major way at my employer.), but again mostly a lot of socialization, then headed in early since we had an early day on Friday for the post conference session. The downside of the day was that I was in considerable pain by the end of the day and had to bail on the Red-Gate dinner. I really hated to miss it, as I am very appreciative to them for what they do for the SQL community, not to mention I ended up eating a 44 dollar hamburger in my room for dinner…really good, but nothing compared to what they had planned. Friday The post con session was a great deal of fun. Paul and I have made a habit of presenting together at several conferences over the past few years, and one thing is always the case. Not enough time. So this year Paul suggested we put in for a post conference session and while I thought we had a snowball’s chance in Bermuda of getting it, and well, I was wrong. We had a good crowd of 47 with a lot of good conversation and in the end, 6.5 hours was a decent amount of time to do an advanced session on database design, though still with no active involvement doing design. It did give us time to use the white board and show some designs when people wanted more, or the places where we didn’t write good enough slides (you can get the slides here: PASS2009_AdvRelDBDesign_PostCon.pptx). Hopefuly we get to do the session again next year, as it was a tremendous amount of fun. Finally, many of the MVPs headed out to a fantastic meal that Arnie Roland has arranged for the past two years. This year, he managed to get Quest to sponsor the proceedings, and they not only fed us, but gave us a bag of t-shirts as well. Good food and nice people are always appreciated. Afterwards, back to the room to finish packing. Then it was a matter of making it home, which was a pretty interesting experience. Southwest Airlines has some definite software problems that cause troubles every time I fly. And they always point to the “new” system. That was a reasonable excuse during last PASS, but a year later? Mercy. At the very least I was able to get my luggage in at exactly 50 pounds after swapping a book for an umbrella. I am home now, and now somewhat getting over the physical experience of it all. The mental experience is something I will never get over, at least until next November.
|
-
For any of you who attended the Quest breakfast at PASS (and anyone else really) I wanted to go ahead and post the code and give a little wrap up/explanation. (I will post the stuff on perf counters later. They are cool, but this is really what I wanted to make sure people saw.) I had a plan for my presentation, but time was less than I expected, and the good stuff kinda fell off. So here is the stuff around the Disk IO DMV section that I really messed up and didn’t show enough. I read a few of the comments that my presentation wasn’t that useful to you, and that is clearly on me. If the index ones are useful, these are too, and can be used to help spread load around your disks. So, here is the slide I presented: By knowing the amount of data written to a database file, you can see how busy the file is, the filegroup is, the database, the disk drive, etc, by aggregating the data in the following query in various way. The query is pretty simple and will return all files in all databases (there are parms on the function to change that, but check BOL for more info): --since reboot SELECT db_name(mf.database_id) as databaseName, mf.physical_name, divfs.num_of_reads, divfs.num_of_bytes_read, divfs.io_stall_read_ms, divfs.num_of_writes, divfs.num_of_bytes_written, divfs.io_stall_write_ms, divfs.io_stall,size_on_disk_bytes FROM sys.dm_io_virtual_file_stats(null,null) as divfs JOIN sys.master_files as mf ON mf.database_id = divfs.database_id and mf.file_id = divfs.file_id The “stall” columns give you how long any processes have waited on your disk drives to serve up data for this file. This information plus the information in _bytes_written and _bytes_read columns can give you how much data was moved, and how long your CPU had to wait for the data before it could get working on it. Very powerful stuff, and can really give you a look at opportunities for performance tuning. That query gives you data from the last reboot of the server, but usually you want to see up to date values. So you have to get a baseline of values, then compare them at a later point. You can build tools that do this, and you can use the performance data warehouse in 2008, and I will demonstrate the former. Using a temp table and a WAITFOR DELAY command, I build a quick tool to see waits and stats over 20 seconds. Note that I use a #temp table to allow you to run the last query over and over to see the comparison to the baseline until you want to drop the #temp table. --over the following delay declare @delay varchar(10) = '00:00:20' SELECT db_name(mf.database_id) as databaseName, mf.physical_name, divfs.num_of_reads, divfs.num_of_bytes_read, divfs.io_stall_read_ms, divfs.num_of_writes, divfs.num_of_bytes_written, divfs.io_stall_write_ms, divfs.io_stall,size_on_disk_bytes, getdate() as baselineDate INTO #baseline FROM sys.dm_io_virtual_file_stats(null,null) as divfs JOIN sys.master_files as mf ON mf.database_id = divfs.database_id and mf.file_id = divfs.file_id WAITFOR DELAY @delay ;WITH currentLine as ( SELECT db_name(mf.database_id) as databaseName, mf.physical_name,num_of_reads, num_of_bytes_read, io_stall_read_ms, num_of_writes, num_of_bytes_written, io_stall_write_ms, io_stall,size_on_disk_bytes, getdate() as currentlineDate FROM sys.dm_io_virtual_file_stats(null,null) as divfs JOIN sys.master_files as mf ON mf.database_id = divfs.database_id and mf.file_id = divfs.file_id) SELECT DATEDIFF(s,#baseline.baselineDate,currentlineDate), currentLine.databaseName, left(currentLine.physical_name,1) as drive, currentLine.physical_name ,currentLine.io_stall - #baseline.io_stall as io_stall_ms ,currentLine.io_stall_read_ms - #baseline.io_stall_read_ms as io_stall_read_ms ,currentLine.io_stall_write_ms - #baseline.io_stall_write_ms as io_stall_write_ms ,currentLine.num_of_reads - #baseline.num_of_reads as num_of_reads ,currentLine.num_of_writes - #baseline.num_of_writes as num_of_writes ,currentLine.num_of_bytes_written - #baseline.num_of_bytes_written as num_of_bytes_written FROM currentLine join #baseline on #baseLine.databaseName = currentLine.databaseName and #baseLine.physical_name = currentLine.physical_name go --drop table #baseline The most interesting part of this query is often the stall columns. When I see really bad IO, the number of seconds waited can end up being way more than the actual number of seconds. Disk IO is more or less serial (particularly on my mini HP with Win7 Starter Edition), so if you have many queries running concurrently, every one of them needs data from the same IO source, and if one query used the disk for 1 second, the other processes might wait for 1 second each. When wait stats are really low, that means the disk were ready, willing, and able to serve all processes. On your test server, you can use a query like: --create database DMV --go use DMV go create table testDMV ( testDMVid int identity, bigun char(8000) ) go set nocount on insert into testDMV(bigun) select REPLICATE('a',8000) go 5000 --drop table testDmv select * from testDMV To create some data. Note that data will be written to the disk in various counts. I set all of the rows to take a full data page, and each of the rows is an individual transaction. But it won’t be a 1-1 match with the number of rows written or read. SQL Server flushes data to the disk in the manner it wants to, and some manner of caching will change the number over time. Run the select * from testDMV query over and over and you will not see any change in the disk IO, because it is in cache now. I hope this is better. Sometimes as a presenter I am a good writer, and frankly the lack of bacon really threw me off this morning. Feel free to email me at louis@drsql.org or tweet me at drsql and I will be happy to share more. All of this will be in our RedGate book that will be coming out before the end of the millennium, at the very minimum.
|
-
Mercy, PASS is going to be a busy week for me. My basic schedule is: Sunday: Arrive just after 4 PM. Bus to the Sheraton. Monday: Some Insiders stuff, some meetings, etc 6:30 or so, the Quiz Bowl 2009 (Celebrity Edition). We have 3 star studded teams this year, and instead of winning prizes for themselves, they are going to win prizes for you…So come on out for some good food, friends, and fellowship with your fellow nerds. Tuesday: 11:30 – 1:30 Birds of a Feather Lunch. I have a table where I hope to meet with people and help them with design (so they can help me with examples for my next book) and just discussing normalization or whatever. This will be in the Expo Hall 4B Wednesday: 7:00 – 8:30 Quest PASS Breakfast “Dine and DMV’s” . I am on the panel and will be showing a couple of the DMVs for the Performance Counters and Disk IO. More info: http://www.brentozar.com/archive/2009/10/quest-pass-breakfast-event-dine-dmvs/. This event will be in Room 608 11:30 – 12:00 Book signing with 53 of my coauthors on the MVP Deep Dives Book. Don’t have a copy? They will be on sale there. More info, check here: www.sqlservermvpdeepdives.com. This will be in the Spotlight Theater. With 30 minutes and 30-50 people signing books, this should be a hoot and a holler. 1:30 – 2:45 Database Design Session. With room for 360, there should be some elbow room if you find your session is packed. It is that kind of self-deprecating humor, coupled with light doses of database theory and practical advice that will make this session the can’t miss session of PASS! We will be room 615-617, but unlike breakfast, there will be no bacon involved, and please don’t bring eggs either. 7-9, The party at Gameworks. Not sure if I will be there, cause frankly I will have been up at 6:30 in the morning and am not a big fan of being awake in the first place. Friday: All day – Post Con with Paul Nielsen on Relational Database Design. Finally, a session length that is long enough to get through an overview of Relational Design. We have lots of good stuff to talk about, and lots of interaction planned. Not sure if there is a ton of space left, so hurry up and sign up if you wanna! Saturday: 11:00, get back on a plane and head to Nashville, giving up the two bonus hours I received in route. I will blog some and tweet some more during PASS, so if you want to meet up, follow me/direct message me at www.twitter.com/drsql and let me know. Frankly the whole thing seems exhausting to me, so you might find me slumped in a corner asleep…luckily, I am not a bingo square, but it should be fun anyhow: http://codegumbo.com/index.php/2009/10/21/sql-pass-twitter-bingo-the-rules-so-far/
|
|
|
|
|
|