SQL Server Storage Engine under the hood: How SQL Server performs I/O
Aug 11th
Found prove that SQL Server is the Devils Engine - ERROR 666
Aug 5th
Filtered Index with WHERE col IN (...) clause
Jul 14th
Just deployed my first SQL Azure database.
Jan 28th
Quiet an adventure as with all IT related things: SQL Azure is almost like SQL Server. Emphasis on the almost. But after a little fighting I got it running. Time will tell us how well it is going to run.
My tip to all is to have a deployment script that only contains what you realy need and not a generated ones that specifies each and every default option. Why: SQL Azure does not know many of the default options and therefore the script fails in that case.
How to assign a text containing a single quote to a char, varchar, nchar or nvarchar valiable or colum
Jan 27th
Sometimes the need to assign a text like "She's the boss" to a text column or variable arises.
DECLARE @MyText AS NVARCHAR(100) = 'She's the boss';
You can already see on the syntax coloring that something is wrong. To put a single quote inside a string literal you must precede it with another single quote
DECLARE @MyText AS NVARCHAR(100) = 'She''s the boss';
If you run the whole batch below
DECLARE @MyText AS NVARCHAR(100) = 'She''s the boss';
SELECT @MyText;
You will see it produces the desired result: She's the boss
To give you another example the text ‘I am between single quotes’ would look like this
DECLARE @MyText AS NVARCHAR(100) = '''I am between single quotes''';
SELECT @MyText;
increasing the performance of count(*)
Jan 26th
I got a very strange request: We have to constantly count the rows in a table can we increase the performance of count(*)
So lets analyze the problem step by step.
The table is a typical table the actual columns have no effect so I replaced them with just one column in the example to make things easier; Let's start by creating a heap
CREATE TABLE MyTable
(
ID intNOTNULLIDENTITY(1,1),
Payload varchar(300)NOTNULL
)
and fill it with random data
DECLARE @i ASint= 1;
WHILE (@i < 1000)
BEGIN
INSERTINTO MyTable(Payload) VALUES (REPLICATE('ABC', 20 + @i % 80));
SET @i += 1;
END
Now lets see where we are on a heap
STATISTICSIOON
SELECT COUNT(*)FROM MyTable
Table 'MyTable'. Scan count 1, logical reads 25, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
To count the rows SQL Server must do a full table scan and reads each page exactly once.
Let's see if an index will help us…
CREATE CLUSTEREDINDEX CI_MyTable ON MyTable(ID); SELECT COUNT(*)FROM MyTable;
Table 'MyTable'. Scan count 1, logical reads 27, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
SQL Server now performs a clustered index scan which is in fact a table scan plus the overhead to find the first page. Actually a little bit more work than the table scan.
The trick to get it faster is to create an index that uses less space that the table (SQL Server will always select the smalest index to execute a COUNT(*))
The Smallest INDEX you can create on a table that has a clustered index is a secondary index that is composed just out of the clustered key:
CREATE INDEX IX_ID ON MyTable(ID);
SELECT COUNT(*)FROM MyTable;
Table 'MyTable'. Scan count 1, logical reads 3, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Now it just has to Scan the leaf nodes of the secondary index
Careful this kind of index has very limited use besides the example above.
Other uses would be for example: SELECT xyz WHERE uvw IN (SELECT ID FROM MyTable)
Useless for most people
Jan 26th
Hi fellow SQL Server users, I created a new category that I will use to mark posts that are useless for the greater part of the population.
This are either tips and tricks that define a very uncommon special case or are just for very very high end solutions and the practical application is limited. So watch out for the category and don't be surprised when you read a post marked like this when the content does not apply to you.
But on the other hand there will be a bunch of SQL Server users that are just looking for that information
A little bit more information on multi location backups
Jan 26th
On of the advantages of backing up to multiple locations is that the data is read on the SQL Server just once, this is an advantage because the IO on the database files is kept to a minimum (in comparison on doing two backups one after the other). Then the data is sent to all destenations in parallel this results in the fact that the backup will take as long as is takes to write to the slowest target location.
You can backup full, differential and log backups to multtiple locations the MIRROR TO option is build in into all of them
I do not backup full backups to two locations (you can alsways take the backup before the last to start your restore if you lose the last one) but I backup my logs to two locations to reduce the risk of a broken log chain by a missing or corrupt file.
If you are really paranoid you should write the data trough two different network cards from different manufactuers with different drivers to avoid data corruption by a faulty driver and then have a constant verify by restore on all destinations.
Backup to multiple locations at the same time (multiple copies of the backup files)
Jan 25th
Sometimes it can be usefull to have two ore more copies of the same backup (e.g. you have two locations/disks and want a copy in/on both)
So lets explain how to backup to two locations at once. First the bad news this is an Enterprise (SQL Server 2005, 2008 and 2008R2) and Datacenter Edition (SQL Server 2008R2) only feature.
If the backup to one location looks like this
BACKUP DATABASE MyDatabase
TO DISK = 'D:\BACKUP\MyDatabase.bak'
Backing up to two locations looks like this
BACKUP DATABASE tg
TO DISK = 'D:\BACKUP\MyDatabase.bak'
MIRROR
TO DISK = 'E:\BACKUP\MyDBBackup2.bak'
WITH FORMAT
The WITH FORMAT is required even if the backup files do not exist
You can go wild and backup to up to 8 locations at the same time.
BACKUP DATABASE tg
TO DISK = 'D:\BACKUP\MyDatabase.bak
MIRROR
TO DISK = 'E:\BACKUP\MyDBBackup2.bak'
MIRROR
TO DISK = 'E:\BACKUP\MyDBBackup3.bak'
MIRROR
TO DISK = 'E:\BACKUP\MyDBBackup4.bak'
MIRROR
TO DISK = 'E:\BACKUP\MyDBBackup5.bak'
MIRROR
TO DISK = 'E:\BACKUP\MyDBBackup6.bak'
MIRROR
TO DISK = 'E:\BACKUP\MyDBBackup7.bak'
MIRROR
TO DISK = 'E:\BACKUP\MyDBBackup8.bak'
WITH FORMAT
I would not recommend to backup to 8 locations thats because the feature does not work as you might expect. It works like any other transaction in the database all or nothing. This means if one of your locations is unavailable the backup does not start and if one location fails during the backup the whole backup operation fails.
Hello World
Jan 24th
Hello fellow SQL Server users.
I have spent half my life working with SQL Server and accumulated a lot of knowlege in this past 20 years. I started presenting on several conferences over the last few years and more and more people asked me to start blogging. This is what I am going to do here.
My focus is on building reliable, avalable and scaleable infrastructures for SQL Server and this is also the main focus of this blog but you will see the ocasional general tip entry as well.
If someone has specific questions feel free to ask them I will do my best to answer them
=tg=