Category Archives: SQL Server

All SQL Server posts that don’t fit in other categories

Get index fragmentation statistics

I recently attended a Pittsburgh SQL Server user group meeting where Brent Ozar gave a presentation on the silent performance killer.  This motivated me to create a stored procedure that could leverage the DMVs in SQL 2005/2008 to gather index fragmentation statistics for all databases on a given server.

Goal

The goal is very simple.  Build a query that could be scheduled to grab statistics that are helpful towards determining if an index needs to be defragged or reorganized.  I would like to throw these results into a table so I could analyze them at a later date.  I would also like to monitor the fill factor and padding to determine if I need to make changes and to analyze if the changes are really helpful.

Download Scripts

The following script uses the following DMV’s sys.dm_db_index_physical_stats, sys.objects and sys.indexes and this script is provided as is.

To download the script click here

To download the create table script for the table used click here


Table Definition

The following is an explanation of the columns.  The following descriptions come from MSDN.

Column Name

Description

databaseName

Name of database, unique within an instance of SQL Server.

objectName Object name.
indexName Name of the index. name is unique only within the object.

NULL = Heap

partitionNumber 1-based partition number within the owning object; a table, view, or index.

1 = Nonpartitioned index or heap.

fragmentation Logical fragmentation for indexes, or extent fragmentation for heaps in the IN_ROW_DATA allocation unit.

The value is measured as a percentage and takes into account multiple files. For definitions of logical and extent fragmentation, see Remarks.

0 for LOB_DATA and ROW_OVERFLOW_DATA allocation units.

NULL for heaps when mode = SAMPLED.

fill_factor > 0 = FILLFACTOR percentage used when the index was created or rebuilt.

0 = Default value

is_padded 1 = PADINDEX is ON.

0 = PADINDEX is OFF.

type_desc Description of index type:

HEAP
CLUSTERED
NONCLUSTERED
XML
SPATIAL

page_count Total number of index or data pages.

For an index, the total number of index pages in the current level of the b-tree in the IN_ROW_DATA allocation unit.

For a heap, the total number of data pages in the IN_ROW_DATA allocation unit.

For LOB_DATA or ROW_OVERFLOW_DATA allocation units, total number of pages in the allocation unit.

date this is the current date GETDATE()

Script

   1:  ALTER PROCEDURE [dbo].[GetStatsForIndexes]
   2:      @PageCount INT = 100
   3:  
   4:  AS
   5:  BEGIN
   6:      -- SET NOCOUNT ON added to prevent extra result sets from
   7:      -- interfering with SELECT statements.
   8:      SET NOCOUNT ON;
   9:  
  10:      -- Declare varables
  11:      DECLARE @dbID INT, @dbName VARCHAR(128), @SQL NVARCHAR(MAX)
  12:  
  13:      -- Create a temp table to store all active databases
  14:      CREATE TABLE #databaseList
  15:      (
  16:            databaseID        INT
  17:          , databaseName      VARCHAR(128)
  18:      );
  19:  
  20:      -- we only want non-system databases who are currenlty online
  21:      INSERT INTO #databaseList (databaseID, databaseName)
  22:      SELECT d.database_id, d.name FROM sys.databases d where d.[state] = 0 and d.database_id > 4
  23:  
  24:  
  25:      -- Loop through all databases 
  26:         WHILE (SELECT COUNT(*) FROM #databaseList) > 0  BEGIN
  27:  
  28:             -- get a database id
  29:          SELECT TOP 1 @dbID = databaseID, @dbName = databaseName
  30:          FROM #databaseList;
  31:  
  32:              SET @SQL = 'INSERT INTO DBA_Tools.dbo.IDX_FRAG (databaseName, ObjectName, indexName, partitionNumber, fragmentation, fill_factor, is_padded, type_desc, page_count, [date])
  33:                  SELECT
  34:                    db.name AS databaseName
  35:                  , obj.name AS ObjectName
  36:                  , idx.name AS indexName
  37:                  , ps.partition_number AS partitionNumber
  38:                  , ps.avg_fragmentation_in_percent AS fragmentation
  39:                  ,idx.fill_factor
  40:                  ,idx.is_padded
  41:                  ,idx.type_desc
  42:                  , ps.page_count
  43:                  , GETDATE() as [date]
  44:              FROM sys.databases db
  45:                INNER JOIN sys.dm_db_index_physical_stats ('+CAST(@dbID AS VARCHAR(10))+', NULL, NULL , NULL, N''Limited'') ps
  46:                    ON db.database_id = ps.database_id
  47:                INNER JOIN '+ @dbName+'.sys.objects obj ON obj.object_id = ps.object_id
  48:                INNER JOIN '+ @dbName+'.sys.indexes idx ON idx.index_id = ps.index_id AND idx.object_id = ps.object_id
  49:              WHERE ps.index_id > 0
  50:                 AND ps.page_count > 100
  51:              ORDER BY page_count desc
  52:              OPTION (MaxDop 1);'
  53:  
  54:          EXECUTE sp_executesql @SQL
  55:          -- remove the database from the databases table
  56:          DELETE FROM #databaseList WHERE databaseID = @dbID
  57:  
  58:          -- get the next database in the databases table
  59:          SELECT TOP 1 @dbID = databaseID, @dbName = databaseName
  60:          FROM #databaseList;
  61:  
  62:      END
  63:      -- temp table is no longer needed, so we will kill it.
  64:      DROP TABLE #databaseList;
  65:  END

Can SQLSaturday happen in Wheeling, WV?

I noticed a great event that is occurring down south.  Its called SQLSaturday and one of my short term goals is to see if it’s possible to bring this great event to Wheeling, WV. 

What is SQLSaturday?

SQLSaturday is a platform for free one day training events for SQL Server professionals. This event focuses on speakers, providing a good variety of topics, and making it all happen through the efforts of volunteers. Whether you’re attending one or thinking about hosting your own(this would be me), we think you’ll find it’s a great way to spend a Saturday.

Initial Goals:

  1. Bring technology professionals from Pittsburgh, Columbus and Morgantown to Wheeling.
  2. Have 50 to100 attendees attend this initial event.
  3. Provide great speakers to present topics about SQL Server and .NET
  4. Utilize sponsors to make the event 100% free to all who attend.
  5. Provide the opportunity for IT Professionals to network with their peers.
  6. Provide exposure for AITP and the Greater Wheeling Chapter of AITP 

Conclusion:

Will this event happen?  I sure hope so, but  I am still planning.  I hope to have an answer soon.  If we do go live I am targeting early 2010.

I will post my future action items and the decisions I make soon.  I hope that this series of posts are helpful for people who are contemplating if they should start a similar event in their area.

If you have any comments, thoughts or suggestions please share them.

Free SQL Server 2008 Training Kit

Are you looking for some free SQL Server training?  Are you looking to upgrade your SQL Skills to SQL Server 2008? If so, Microsoft has a download just for you.

Download SQL Server 2008 Developer Training Kit

The SQL Server 2008 Developer Training Kit includes presentations, sample code and labs that cover the following topics:

  • Spatial Support
  • FILESTREAM
  • CLR
  • Reporting Services
  • Date and Time
  • T-SQL enhancements including  Table Value Parameters, Merge, Row Constructors, Grouping Sets and more..

Find tables that contain column name

The following script is used when I need to perform a search to find tables that contain a column name.

-- Use Control+Shift+M to specify a value column name

SELECT    TABLE_SCHEMA + '.' + TABLE_NAME
FROM    INFORMATION_SCHEMA.COLUMNS
WHERE    COLUMN_NAME = N'<column_name,varchar,(column_name)>'

or you can also use the following query.. 

-- Use Control+Shift+M to specify a value column name

SELECT sc.[name] AS column_name, so.[name] AS [TABLE]
FROM syscolumns sc
INNER JOIN sysobjects so ON sc.id=so.id
WHERE sc.[name] LIKE N'<column_name,varchar,(column_name)>'
AND so.xtype = 'U'

I

T-SQL Scripts included with Management Studio

Have you ever wanted to quickly script T-SQL code to add columns to a table, alter a partition function, create endpoints, configure data capture, create an indexed view, backup or restore databases?  These tasks and more are included as templates.  The template explorer is included in SQL Server 2005 and SQL Server 2008 Management Studio (SSMS).   To view the template explorer hit Ctrl+Alt+T or select Template Explorer from the view menu in SSMS.  You will find templates to create objects such as databases, tables, views, indexes, stored procedures, triggers, statistics, and functions. In addition, there are templates that help you to manage your server by creating extended properties, linked servers, logins, roles, users, and templates for Analysis Services, and SQL Server Compact 3.5 SP1.

image

Once you load a template in the editor section in SSMS you can specify values for the template parameters values.  Press CTRL+Shift+M to specify values as shown on the next figure.

image
The templates are placed in the users Documents and Settings folder under Application Data\Microsoft\Microsoft SQL Server\100\Tools\Shell\Templates. Templates are available for solutions, projects, and various types of code editors as they are scripted as individual sql files.

Backup Compression with SQL Server 2008

I wanted to share my results towards using the backup compression utility built into SQL Server 2008 Enterprise Edition.   I have noticed a compression range from 65% to 75%.

Database SQL 2005 backup SQL 2008 (compression enabled) Compression
DB One 18.2 GB 5.6 GB 69%
DB Two 3.7 GB 1.3 GB 65%
DB Three 1.2 GB .3 GB 75%

By default, backups are not compressed. You can change this setting by using sp_configure to set the value of the backup_compression_default setting or by selecting the option in the Server Properties dialog box. ( I don’t recommend  this as you can specify the compression type as shown below)

For anyone using SQL Server 2008 who is  not familiar with the compression feature you can enable it by using the following example.

When you create a backup on the options page you will notice a compression section at the bottom of the screen.  There are three values in the dropdown including use default server settings, Compress backup, and do not compress backup.  Select compress backup and click OK (I highly recommend you also check the checkbox to verify backup when finished)

SQLBackup

For those who are using the backup compression what are your results?  Shoot a responses.  I want to know how its working out for you.

Load SQL Function in SSRS Header or Footer

Today I had an interesting problem that I believe is common with SSRS so I wanted to share my solution.  I had a new requirement to display the result of a SQL function into the header of a report.  Quickly, I found out that you cannot drag a dataset item into the header.  To solve this problem I created a new internal parameter that obtains its default value from the dataset I wanted to display on the header.

In this example I have an Id that is passed into the report as a parameter. I call a SQL function in a dataset that displays a different identifier based on the criteria inside the SQL function.    Below is an image that displays the setting I used for the internal parameter.

image

Once this parameter exist I was able to use the following code in the header section to display your data returned from the SQL function.

Parameters!ConflictReportId.Value