Why Do I NEED A Kindle?

Kindle

This comic was inspired by a blog post I read by Geek Gamer Girl.

Seriously, Amazon, I would be more than happy to accept a Kindle DX in exchange for this blantant advertisement for your product. Nah, I didn’t think so.

Visual Studio Tip: Add Existing Directory

How many times have you wanted to add a directory that already exists to your project only to have to create the directory (and any subdirectories) and then Add Existing Files (one directory at a time)?

Annoying isn’t it? (Almost as annoying as someone who uses too many parentheses.)

Why, oh why, isn’t there an Add Existing Directory function?

Because it isn’t needed.

What? You’re crazy!

If you copy the directory and all its subdirectories into the project (into the directory you want them) with File Explorer (or xcopy from the command line), then go into VS and click the little Show All Files icon at the top of the Solution Explorer pane (second icon from the right for me), voila! There are the directories that you want to add.

Now just highlight the grey little directory and right click. Next pick the menu item that says “Include In Project”.

Bam! You just kicked it up a notch! (Man that’s a tired catch-phrase, isn’t it?)

Does that ever save some time.

Today I needed to include Tiny MCE in my scripts folder in jeffaBlogger (MVC blog engine I’m working on). It finally was annoying enough to go Google up a solution.

Thanks to NitriqBlog for that little life-saver.

 

Atlanta Job Market Update

I’ve pulled this one since it was from 2008 and the job market in Atlanta at that time is now just a historical curiosity…

Silverlight Game Programming for Total N00bs

SILVERLIGHT?

Silverlight is Microsoft’s answer to Adobe’s Flash, which has become wildly popular for casual game creation (Flash, not yet Silverlight).

If you are a .Net programmer who would like to try your hand at making a casual game, then you are in luck! Silverlight is your ticket to ride.

CASUAL GAMES?

OK, what is a “casual game”? Are there “formal games” where you have to wear a tux? Maybe on Linux, but not on Windows! You see, Linux has this mascot… and he’s called… oh never mind.

Casual games are a category of games that are geared towards an audience other than “hardcore” gamers. In other words, games made for the mainstream player who has a few minutes to kill rather than hours/days/weeks/months (or in the case of something like World Of Warcraft, years).

Games like Halo, World Of Warcraft, etc. are considered Triple A games. These are games that push the boundaries of technology and are made by huge teams of programmers, artists, designers, caterers, marketers, haberdashers, etc., etc. Literally hundreds of people are involved and the budgets are enormous. If you are reading this blog, I’m guessing you aren’t going to be making those games…

ONE HAND CLAPPING

To jumpstart your learning process, I have written what has to be one of the simplest games ever. My goal was to make code you could get your head around in just a few minutes and then grow from there.

Introducing: PracticePong.


PracticePong is Pong… SIMPLIFIED. But, wait! Isn’t Pong already pretty darned simple? Yes, for an actual game. What I’m making is a Practice Game, that doesn’t try to be fun, but rather show you the parts needed to make a game without ANY extra stuff to confuse you.

So in PracticePong you only get one paddle. The Evil Computer gets none.

If the ball hits the left wall, you get a point. If it hits the right wall, the Evil Computer gets a point.

When you move the mouse up and down, the paddle follows.




When you click the mouse button, the ball launches. Even if it is already in play. Remember, this isn’t really a game… just a tutorial.

There are horrible, horrible sound effects and graphics. But, the point is, there aren’t many of them.

USE THE SOURCE

Here is a link to a ZIP file that contains the Visual Studio 2008 project. You will have to install the Silverlight tools before you can load it, however.

There are basically 3 xaml files (page, ball, and paddle) that represent very simple objects that will be on screen.

All the code is in page.xaml.cs and is pretty much a tutorial in and of itself.

There is also a website to host the page where the Silverlight lives.

THANKS


Thanks to several people who helped get me rolling on the right path.

First is Keith Rome. He spoke at our GGMUG meeting back in June and did a very good tutorial on getting started with Silverlight game programming.

Next is Bill Reiss over at Silverlight Games 101 for his tutorial series.

[NOTE: The link that was above is now a dead link.]

Then there is Andy Beaulieu who made the outstanding Destroy All Invadersgame. I learned a lot from his source.

Hope you enjoy PracticePong and go out there and make some fun games!

 

SQL Server 2005 Partitioning

One way to speed access to a large table is to partition the data. Oracle has partitioning and now so does SQL Server. I’ve worked with Oracle’s version for a while, but this is my first foray into the SQL Server variation.

I’m going to try to keep this as brief as possible, so I’m going to leave out much theory and background and leave that as an exercise for the reader and his friend Google.

In a nutshell partitioning means subdividing your table so that a query only has to spin through the subset of records, not the entire table.




In practice both Oracle and SQL Server allow you to divide your table up into more than one physical file, with certain ranges of data assigned to each file. This has speed advantages when querying a subset, but it also has management advantages since you can perform tasks like backups and archives on individual files instead of having to test every record in the table to see if it meets your criteria. Being included in the file it is in means that it meets the criteria.

I’d say most people who look to partitioning are doing so because they want to speed up their queries. Fair enough. Will it work? If so, how much speed will be gained? There’s really only one way to find out, right? Marketing materials! No, wait, I mean, Experimentation!

For my experiment I start with a real table to which I need to speed access. The table has about 32 million records and 33 fields.

The table has historical data that is broken into six month ranges. In other words, you will typically only need to access six months worth of the data at a time, but it could be any six month period in the last two years. Without partitioning, the dbms has to spin through all two years for every query. With partitioning it only has to spin through the relevant six month period.

The create script (with names changed to protect the innocent) is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
CREATE TABLE [testTable](
    [a] [bigint] NOT NULL,
    [b] [int] NULL,
    [c] [int] NULL,
    [d] [varchar](30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [e] [int] NULL,
    [f] [int] NULL,
    [g] [datetime] NULL,
    [h] [int] NULL,
    [i] [varchar](20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [j] [varchar](22) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [k] [varchar](10) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [l] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [m] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [n] [varchar](1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [o] [int] NULL,
    [p] [int] NULL,
    [q] [varchar](2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [r] [varchar](1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [s] [varchar](8) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [t] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [u] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [v] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [w] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [x] [varchar](50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [y] [varchar](5) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [z] [datetime] NULL,
    [aa] [int] NULL,
    [bb] [int] NULL,
    [cc] [int] NULL,
    [dd] [int] NULL,
    [ee] [varchar](2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [ff] [varchar](1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [gg] [varchar](25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
CONSTRAINT [PK_testTable] PRIMARY KEY CLUSTERED
(
    [a] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
The partitioned table is identical except for the last few lines. From the CONSTRAINT keyword on down it is as follows:
CONSTRAINT [PK_testTable] PRIMARY KEY NONCLUSTERED
(
    [a] ASC
)WITH (IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [testTablePS]([g])

The key is the very last line. testTablePS is the Partition Scheme to use. It takes the column name [g] as a parameter. It feeds this into the Partition Function to determine which partition a given record is in based on its value in the g column (in this case a datetime).

Each partition is in its own file in its own filegroup.

Now for the speed tests.

To begin with we’ll try WITHOUT indexing. Indexing will most likely improve the results, but I’d like a baseline first. This pretty much narrows things down to just the difference between partitioning and not partitioning.

The query I’ll use is this:

1
2
3
select *
from testTable
where g > '5/15/08'

This means we are looking at all the fields each time.

Here are the results (~2.4 million rows returned):
























Not PartitionedPartitioned
Query Run Time 1st run3:451:22
Query Run Time 2nd run2:421:16
Query Run Time 3rd run2:401:02

Predictably the first run is the slowest. Subsequent runs are a bit more consistent.

As you can see the partitioned table returns about twice as fast as the non-partitioned table.

Now lets try returning a specific date.

The query will be:

1
2
3
select *
from testTable
where g = '5/22/08'

Those results are here (~470,000 rows returned):
























Not PartitionedPartitioned
Query Run Time 1st run1:540:14
Query Run Time 2nd run1:520:12
Query Run Time 3rd run1:540:12

Much faster.

Now let’s look at what happens if we take the return and display of the data out of the equation.

1
2
3
select count(1)
from testTable
where g = '5/22/08'

The results are here:
























Not PartitionedPartitioned
Query Run Time 1st run1:410:06
Query Run Time 2nd run1:430:00
Query Run Time 3rd run1:430:00

It’s hard to find fault with less than a second…

Now a HUGE caveat… You knew there had to be one, right?




What if you write a query that doesn’t limit by the column on which the partition is based? Poor you. You will have the same OR WORSE results from the partitioned table that you have from the non-partitioned table. Why? Well now the DBMS has to look through several files to gather up the data instead of just one. This is especially noticable on big joins between tables.

Partitioning can be a big help, but it is definitely not a silver bullet.

That wraps it up for this post.

Next post I’ll add some indexing and rerun the queries.