powershelldba.de
REF: PSDB-PART-2026 SCOPE: SQL Server 2016–2022 STATUS: v1.7.0
Module

Automatic SQL Server table partitioning, sqmPartitionTool

Partition existing tables, maintain them automatically (sliding window + retention), and migrate them completely into a separate archive database, with a transparent cutover via a view, so existing application code keeps running unchanged. Built on dbatools and sqmSQLTool.

PowerShell 5.1+ Built on dbatools SQL Server 2016–2022 dtcSoftware © Uwe Janke

What is sqmPartitionTool?

sqmPartitionTool is a PowerShell module by dtcSoftware (author: Uwe Janke) for the full lifecycle of a partitioned SQL Server table: from the one-time conversion of an existing table, through ongoing automatic maintenance (creating new partitions ahead of time, removing old ones after their retention period), to fully migrating an entire table into a separate archive database.

The module is built on dbatools and sqmSQLTool (reusing its logging, configuration, and WinForms theme) and supports numeric and string date-surrogate keys alongside real date columns, as well as composite keys with no single unique column, situations that come up regularly in production databases that have grown organically.

PowerShell 5.1+ dbatools sqmSQLTool ≥ 1.9.2.0 SQL Server 2016–2022

Feature highlights

In-place partitioning

Partition an existing table directly in its source database, including a variant for very large tables with little free disk space.

Sliding-window maintenance

New, empty partitions are created automatically ahead of time, the last partition never fills up.

Automatic retention

Expired partitions are removed automatically, optionally copying them to an archive database first.

Archive-DB migration with cutover

Migrate an entire table month by month into an archive database, ending with a view over the copy, transparent to existing application code.

Composite keys

Up to four columns as a key, plus numeric/string date-surrogate keys (e.g. an INT column formatted as YYYYMMDD).

GUI wizard + CLI

A WinForms wizard for the whole process, every core function also works standalone from the PowerShell console.

A, In-place partitioning

Invoke-sqmTablePartitionConversion , partition an existing table, even with little free disk space

What it does

Converts an existing, non-partitioned table into a partitioned one, pre-flight check, min/max detection, boundary calculation, filegroup creation, and the actual partitioning in one call. Works for heaps and clustered-index tables, including automatically extending the PRIMARY KEY with the partition column when needed. -Method BatchedSwap builds a new, empty partitioned copy for very large tables and moves the data in segments with periodic DBCC SHRINKFILE, instead of one single large operation.

When to use it

A table that has grown large and isn't partitioned needs to be partitioned without downtime risk. -Method BatchedSwap specifically when the disk doesn't have enough free space for a classic single-step conversion.

Common pitfalls

  • A PRIMARY KEY/UNIQUE constraint without the partition column in the key, extending it changes uniqueness semantics and must be confirmed deliberately
  • -Method BatchedSwap currently doesn't support tables with incoming foreign keys or triggers
  • Without enough free disk space, the standard method fails partway through the operation

Benefits

  • Automatically detects the right approach (constraint extension, index rebuild, or table swap)
  • Segment-by-segment migration with shrink, for environments with little free disk space
  • Automatically registers the table for automatic maintenance (scenario B)
# Partition an existing table by month
Invoke-sqmTablePartitionConversion -SqlInstance "SQL01" -Database "Sales" -Schema "dbo" -Table "OrderHistory" -PartitionColumn "OrderDate" -Granularity Month -AllowKeyChange

# Very large table, little free disk space
Invoke-sqmTablePartitionConversion -SqlInstance "SQL01" -Database "Sales" -Schema "dbo" -Table "OrderHistory" -PartitionColumn "OrderDate" -Granularity Month -Method BatchedSwap -DataCompression Page

B, Automatic maintenance

New-sqmPartitionExtendJob , sliding-window extension as a SQL Agent job

What it does

Creates a SQL Agent job that periodically runs sqm_ExtendPartitionWindow (a T-SQL procedure), it reads the registry of all registered tables and creates new, empty partitions within the configured lead time (FutureBufferPeriods). Idempotent: running it multiple times on the same day changes nothing.

When to use it

Set this up once, right after the conversion (scenario A), after that, extension runs automatically forever, without anyone needing to remember before "the last partition" fills up.

Common pitfalls

  • Without this job, the most recently created partition eventually fills up and new rows land in the wrong, last partition
  • Needs rights on msdb to create the SQL Agent job

Benefits

  • Fully automatic, no manual intervention after initial setup
  • Covers every table registered in sqm_PartitionRegistry at once
# Set up the maintenance job for sliding-window extension
New-sqmPartitionExtendJob -SqlInstance "SQL01"

Register-sqmPartitionTable + New-sqmPartitionRetentionJob, automatic retention and archiving

What it does

Registers a table with a retention period (-RetentionValue/-RetentionUnit) and an optional target archive database (-ArchiveEnabled/-ArchiveDatabaseName). New-sqmPartitionRetentionJob then creates the matching SQL Agent job, which removes expired partitions via Invoke-sqmPartitionArchive, optionally only after copying them to the archive database first (SWITCH PARTITION, batch copy, MERGE RANGE).

When to use it

Old partitions should disappear automatically after a set period, either deleted permanently, or copied first to a cheaper or differently-backed-up archive database.

Common pitfalls

  • Without -ArchiveEnabled, expired partitions are deleted permanently, test before using in production
  • Only affects individual partitions of a still-active table as they expire one by one, not the whole table at once (for that, see scenario C)

Benefits

  • Configurable retention in months or years
  • Optional archiving instead of deletion, with no extra manual effort
# Set up retention with archiving instead of deletion
Register-sqmPartitionTable -SqlInstance "SQL01" -Database "Sales" -Schema "dbo" -Table "OrderHistory" -RetentionValue 36 -RetentionUnit Months -ArchiveEnabled -ArchiveDatabaseName "SalesArchive"
New-sqmPartitionRetentionJob -SqlInstance "SQL01"

C, Archive-DB migration with cutover

Invoke-sqmTableArchiveMigration , move an entire table into an archive database, transparently via a view

What it does

Migrates an active table month by month, resumable via an idempotent MERGE batch procedure, into a partitioned copy in a separate archive database. Supports single-column and composite keys (up to four columns), real date columns as well as numeric/string date-surrogate keys (e.g. an INT column formatted as YYYYMMDD). -PurgeSourceAfterArchive reclaims disk space in the source via DBCC SHRINKFILE after each confirmed archived month. -CutoverToArchiveView renames the source table at the end and replaces it with a view over the archive copy, existing application code keeps accessing the same table name, unchanged.

When to use it

An entire, active table needs to move permanently to another database, e.g. a separate archive instance with a different backup/storage profile, without adjusting application code. Also suited to very large tables (hundreds of GB up to TB): progress is visible via Write-Progress and a console line per month, and stopping at any point loses nothing.

Common pitfalls

  • The target archive database must already exist, it isn't created automatically
  • A heap, or a key with more than four columns, needs an explicit -KeyColumn
  • Without an index with the date column as its leading column, every batch potentially scans the entire table, consider a suitable index first for very large tables
  • The renamed original table is never deleted automatically, deliberately, so nothing is lost, but check it manually before deleting it for good

Benefits

  • Fully resumable, a stop (network, maintenance window) loses nothing; running it again picks up exactly where it last committed
  • Transparent cutover via a view, no application code needs to change
  • The archive copy is automatically registered for its own sliding-window maintenance
  • Visible progress for migrations that can take hours to days
# Full migration with space reclaim and cutover
Invoke-sqmTableArchiveMigration -SqlInstance "SQL01" -Database "Sales" -Schema "dbo" -Table "OrderHistory" -ArchiveDatabaseName "SalesArchive" -DateColumn "OrderDate" -AllowKeyChange -PurgeSourceAfterArchive -CutoverToArchiveView

GUI wizard

Show-sqmPartitionToolGui , a WinForms wizard for the whole process

What it does

Walks step by step through connection, table selection, column selection, min/max preview, granularity, boundary preview, and execution. Step 6 offers two mutually exclusive modes: immediate migration into an archive database (scenario C), or later automated maintenance in the same database (scenario B). A "Key Column(s)" picker with the table's actual columns only appears when the key can't be derived automatically.

When to use it

For a one-time, interactively guided conversion of a table, with a preview before every critical step. For very long-running migrations (scenario C on very large tables), a direct PowerShell call is a better fit instead, since you don't want to keep the GUI window open for hours.

Common pitfalls

  • WinForms needs the desktop CLR, still available under PowerShell 7 on Windows, but not on PowerShell 7 on Linux/macOS

Benefits

  • Supports both Windows and SQL Server authentication
  • Boundary preview before actual execution, no surprises
  • Live log directly in the window during execution
# Open the GUI wizard
Show-sqmPartitionToolGui -SqlInstance "SQL01"
sqmPartitionTool partitioning wizard, step 6/8 boundary preview with 15 boundary values and 16 partitions, three of them marked as future buffer
Step 6/8 in the partitioning wizard: boundary preview before the actual partitioning, here, 16 monthly partitions, three already created ahead of time as a future buffer.

Quick start

Installation & first steps

# Import the module
Import-Module sqmPartitionTool

# GUI wizard
Show-sqmPartitionToolGui -SqlInstance "SQL01"

# Or directly via CLI: partition an existing table
Invoke-sqmTablePartitionConversion -SqlInstance "SQL01" -Database "Sales" -Schema "dbo" -Table "OrderHistory" -PartitionColumn "OrderDate" -Granularity Month