Friday, 10 January 2014

An SP to Fix Logshipping After Adding a New Database File

UPDATE: 22 Jan 2014 - Fixed some bugs, added multi-file support and added a few notes

Every month I need to maintain the various sliding partition windows on several databases. If you've read some of my previous posts you may remember that this involves adding new files for the upcoming partitions. My company's databases are also logshipped as part of the disaster recovery strategy.

What invariably happens every month is I add new files make the necessary partition changes and then wonder why, a little later in the day, I'm receiving alerts for failed transaction log restores. The logshipped database obviously doesn't "know" about the new file and I end up with an error message like this:

Monday, 18 November 2013

Database Snapshot Stored Procedure

We've been trying to tighten up the database release process at work. This involves lots of big and small changes including things like using version control software better, documenting database code as well as putting together some default scripts that run with every release.

It occurred to me that even if you have a good process and set of check lists for the release cycle it is still quite easy to miss out on small but ultimately important steps. Things get hectic, last minute changes are made, etc, etc., and the next thing you know you've forgotten a basic, but important, step like creating a database snapshot or disabling scheduled jobs or revoking user access for the duration of the release. There are probably a dozen other small tasks that can be left out.

Saturday, 5 October 2013

Automating Sliding Partition Windows - Part 2

Sliding Partition Window Concept

Before we continue, let’s remind ourselves of what the Sliding Partition Window is and what it gets us. The whole point of the sliding window is to create a sort of data conveyor belt. New data comes into the production table and is placed in the empty partitions (and files where relevant) and the old data is “switched” or moved off to a staging table for further processing and, crucially, removal. In this way the table slides forward along its partitions but remains essentially the same size. There will always be a set number of partitions worth of data in your production table keeping it lean and fit. In addition, once you’ve moved the data from the staging tables to an archive or reporting database the physical files can be removed and your production database can be maintained at a manageable, near constant, size.

Tuesday, 24 September 2013

Automating Sliding Partition Windows - Part 1

Introduction

Table partitioning, as it was introduced in SQL Server 2005 Enterprise Edition, is an incredibly useful feature. It enhances the potential for performance tuning as well as data, well, err, partitioning - or to use another word data separation.

In terms of performance, partitioning a table and its indexes allows queries (assuming they are written to exploit the partitioning column) to target specific sets of data to reduce table or index scans and therefore improve (reduce) locking on large tables. If you add to this the ability to place a table’s individual partitions on separate filegroups, I/O contention can be reduced by separating the data further, potentially providing even greater performance gains.

Sunday, 18 August 2013

DMV Queries Tied to My Custom Index Stats Tables

I've mentioned a set of DMV queries that I use in a previous post on this blog. I've been chopping and changing the base set of queries for quite a while to suit my needs.

I have also written a series of posts describing how to perform index and statistics maintenance on a SQL Server's databases without losing the very important index stats that the queries mentioned above return.

So, in this post I will show you how I've modified a few of the index focused DMV queries to include the maintenance tables where I now store the cumulative index statistics.

Wednesday, 7 August 2013

Defragging Indexes Without Losing Index Stats - Part 5

The stored procedure

/*********************************************************************************
UPDATE: Bug fixes and increased FILLFACTOR control!
*********************************************************************************/
The first 4 posts of this series covered the concepts of recording index usage statistics for performance tuning while continuing to maintain a database’s tables and indexes. They also presented the individual SQL scripts to perform the various parts of that process.  The most recent post put all of those scripts together into a single set of queries that could be run on a single database.
Most of us, however, have more than one database on a SQL Server instance. Therefore, deploying that last script on a large number of databases is a bit messy. Any modifications will be difficult to manage.
In this post I will present a sample execute statement to run the stored procedure. It is designed to be run centrally, and will loop through all the databases in the instance (there is a parameter to include/exclude the system databases). I deployed the SP onto my Admin_DB where I also store the tables that keep the index usage statistics and table maintenance history.

Wednesday, 3 July 2013

A Script to Fix Orphaned Users

I find that one (well, actually, one of many) really annoying things of restoring databases to different servers is the orphaned user! I am notorious for forgetting about them. Here's a common scenario in my office:
Colleague: Hey DBA, can you refresh a copy of the database on the QA server
Me: Sure
Me (after restore finishes): Hey colleague, it's done.
Colleague: Hey DBA! I CAN'T LOG IN!
Me: *!*&^%$$£"!"£$%"£$
So, in order to help me with this, I've written a little script to make my life a little easier:
DECLARE @loop int = 1
DECLARE @username sysname
DECLARE @orphanedusers TABLE
    (
      id int identity(1, 1) ,
      UserName sysname ,
      UserSID varchar(36)
    )
INSERT  INTO @orphanedusers
        ( [UserName], [UserSID] )
        EXEC sp_change_users_login 'report'

WHILE @loop <= ( SELECT MAX(id)
                 FROM   @orphanedusers
               )
    BEGIN      
        SET @username = ( SELECT    UserName
                          FROM      @orphanedusers
                          WHERE     id = @loop
                        )      
        IF @username IN ( SELECT    name
                          FROM      master.sys.[syslogins] )
            BEGIN
                EXEC sp_change_users_login 'auto_fix', @username      
            END      
        SET @loop = @loop + 1

    END

Hope this helps.

Tuesday, 4 June 2013

Defragging Indexes Without Losing Index Stats - Part 4

Generate UPDATE STATISTICS scripts

In the previous post of this series I provided the script that both determines the indexes that need attention and builds the individual ALTER INDEX scripts. So, now that the indexes have been tended to it’s time to do the same for table and index statistics. 

The update statements created are based on the defrag type carried out on the table as well as a few thresholds to determine whether it is necessary to rebuild the statistics. Those thresholds are:
- (Time passed since last update: >3 days
- And Minimum row count of the table: >=1000 rows
- And Percentage change in number of rows: >20% more or less)
- Or Time passed since last update: >30 days

Script out the indexes in a database

I'm just about to begin a big performance improvement project. I'll be starting with an evaluation of indexes. This will involve synchronizing a development environment's indexes with those that are in live. I need to, however, keep a record of the existing indexes on that dev environment.

So I've written the code below. It will return a table with the object_id, table name, index name, index_id and a create index script. This script includes the drop and create statements for both primary keys and unique constraints. There are quite a few good scripts out in the wider web world, but I needed a few specific things so I just wrote my own.

Thursday, 23 May 2013

Defragging Indexes Without Losing Index Stats - Part 3

In Part 1 and Part 2 of this series I discussed synchronizing index maintenance and index usage statistics logging as an important part of a DBA's performance tuning routine and the script for saving a database's index usage statistics. This part of the series will go into the query that both identifies the indexes that are fragmented and dynamically generates the defrag scripts.