There are times when you are writing a query while referencing another piece of information: the results of another query, a variable value, a webpage, etc…
If using two monitors you can have a query window on each as a reference, or you can resize two query window tabs so they both fit on the screen. But did you know there’s a better option?
Vertical Tab Groups
Vertical tab groups are great because they stay contained within the parent SSMS window. This is nice for when I’m working on a small laptop screen or don’t want to receive whiplash from moving my head back and forth between two monitors.
In order to create a vertical tab group, you need to have at least two query tabs open. Right-click on the tab you want to be on the right-side of of the screen and choose “New Vertical Tab Group”
You can easily change the size of each open tab group by dragging the divider between them:
If you are working with really wide data, you can also try a horizontal tab group instead:
My favorite feature of tab groups is that I can move my entire SSMS window from one monitor to another (or minimize it) and all of my tabs follow suit. This comes in real handy if working on multiple different projects at the same time.
Notice the heavily skewed value distribution. Also notice how we have a clustered index and a very skimpy nonclustered index:
DROP DATABASE IF EXISTS ORUnionAll
CREATE DATABASE ORUnionAll
CREATE TABLE ORUnionAll.dbo.TestData
INSERT INTO ORUnionAll.dbo.TestData VALUES (1,'',1)
INSERT INTO ORUnionAll.dbo.TestData VALUES (2,'',2)
INSERT INTO ORUnionAll.dbo.TestData VALUES (3,'',3)
CREATE CLUSTERED INDEX CL_Col1 ON ORUnionAll.dbo.TestData ( Col1 )
CREATE NONCLUSTERED INDEX IX_Col3 ON ORUnionAll.dbo.TestData (Col3)
If we write a query that filters on one of the low-occurrence values in Col3, SQL Server will perform an index seek with a key lookup (since our skimpy nonclustered index doesn’t cover all of the columns in our SELECT):
Col3 = 2
If we then add an OR to our WHERE clause and filter on another low-occurrence value in Col3, SQL Server changes how it wants to retrieve results:
Col3 = 2 OR Col3 = 3
Suddenly those key-lookups become too expensive for SQL Server and the query optimizer thinks it’ll be faster to just scan the entire clustered index.
In general this makes sense; SQL Server tries to pick plans that are good enough in most scenarios, and in general I think it chooses wisely.
However, sometimes SQL Server doesn’t pick great plans. Sometimes the plans it picks are downright terrible.
If we encountered a similar scenario in the real-world where our tables had more columns, more rows, and larger datatypes, having SQL Server switch from a seek to a scan could kill performance.
So what can we do?
The first thing that comes to mind is to modify or add some indexes.
But maybe our (real-world) table already has too many indexes. Or maybe we are working with a data source where we can’t modify our indexes.
We could also use the FORCESEEK hint, but I don’t like using hints as permanent solutions because they feel dirty (and are likely to do unexpected things as your data changes).
One solution to UNION ALL
One solution that a lot of people overlook is rewriting the query so that it uses UNION ALLs instead of ORs.
A lot of the time it’s pretty easy to refactor the query to multiple SELECT statements with UNION ALLs while remaining logically the same and returning the same results:
Col3 = 2
Col3 = 3
Sure, the query is uglier and will be a bigger pain to maintain if you need to make changes in the future, but sometimes we have to suffer for fashion query performance.
So let’s compare the reads of the OR query versus the UNION ALL query using SET STATISTICS IO ON:
So in this case, tricking SQL Server to pick a a different plan by using UNION ALLs gave us a performance boost. The difference in reads isn’t that large in the above scenario, but I’ve had this trick take my queries from minutes to seconds in the real world.
So the next time you are experiencing poor performance from a query with OR operators in it, try rewriting it using UNION ALLs.
It’s not always going to fix your performance problem but you won’t know until you give it a try.
Camping is a mental reset where I can focus on activities that are completely opposite of what I do every day. It involves different challenges and skill sets, and provides a literal breath of fresh air when compared to working in a typical office environment.
How did I come to enjoy sleeping on the ground and learning to survive with only 20lbs of gear? Let me describe three distinct eras in my camping evolution.
I didn’t grow up camping
My family never went on camping trips. I always enjoyed the outdoors, but I never learned any basic outdoors skills like you might learn in scouts.
My friends during high school came from similar upbringings. We didn’t know anything about building campfires or sleeping in tents, but we wanted to learn.
So, during the summer before college we decided we’d drive up to Vermont, rent a campsite at a state park, and learn to live outdoors.
While an immensely fun trip, our skills were lacking since we basically ended up eating ramen and sleeping in our cars (because our incorrectly set up tent gushed with rainwater during the middle of the night).
We kept at it though, going back every summer, until we managed to figure out how things should work. After a few trips we were no longer eating just ramen and not needing to sleep in our cars anymore.
Have tent, will travel
My outdoor skills improved as I continued to camp through my college years; I learned to cook food over coals, stay dry during the harshest rain storms, and light fires with a single match instead of half a can of camping stove fuel.
During this time I also realized that could travel almost anywhere and have my accommodations cost less than $20 per night PER CAMPSITE.
This meant my friends (and future wife Renee) spent college spring break camping through the Everglades and the Florida Keys. We spent our days kayaking, zip lining, and eating key lime pies before returning to our ocean front campsite for the evening. I think in all that trip cost us less than $400 per person for 9 days of fun, including gas for the minivan.
Ultra cheap vacations continued and I now graduated to cooking single pot meals and foil packet dinners. My car was still parked nearby but I wasn’t having to sleep in it at night.
I even ventured back to Vermont and proposed to Renee there while camping (she said yes even after three days of no showers. That’s when I knew she was a keeper).
Backpacking and gourmet food
Camping eventually evolved into backpacking – instead of having a car a few feet away with a cooking stove and cooler of cold food, now I was learning about how to go into the wilderness for days with everything I would need carried in on my back.
Backpacking is truly exciting. You get to go and see places only accessible by a long hike on foot. The trips require more planning, both in terms of hiking routes, food preparation, water scouting, wildlife management, etc…. all things that invigorate my researching, detail oriented personality.
Living out of a backpack also means that you can easily fly to locations and still have a cheap vacation. I got to see beautiful National Parks like Yellowstone, the Grand Tetons, and Shenandoah all because I knew how to fit everything I need to survive into a carry-on and personal item (except for stove fuel, bear spray, and pocket knife …some things you just have to buy on location).
Not only is visiting these places cool to begin with, but camping overnight in them means you get to see the park early before any car driving tourists arrive and you get to stay out way longer after they all leave the park to go grab dinner.
By this point my car is parked miles away from where I am sleeping and my food game has stepped up. Although I am limited to carrying everything I need in a pack, we frequently dine on pad thai, pizza, and cinnamon rolls.
Who says you need to be roughing it while camping?