To create a partitioned table in SQL Server, you must follow a specific sequence: create a partition function , create a partition scheme , and then apply that scheme to your table [1](https://devcom.com/tech-blog/how-to-partition-a-table-in-sql-server/#:~:text=Create%20Partitioned%20Table:%20Use%20partition%20scheme%20to,table%2C%20improve%20data%20management%2C%20and%20optimize%20performance. "1"), [2](https://learn.microsoft.com/en-us/answers/questions/1097746/step-by-step-partition-table-in-sql-server#:~:text=Hi%20All%2C,rows%29%20to%20new%20partitioned%20table. "2"). This process splits data into logical segments to improve management and performance of large datasets [1](https://www.rudderstack.com/guides/sql-table-and-data-partitioning-how-to/#:~:text=The%20benefits%20of%20SQL%20partitioning,-The%20benefits%20such&text=If%2C%20for%20example%2C%20you%20have,cheaper%20and%20slower%20storage%20media. "1"), [2](https://www.youtube.com/watch?v=q06fH80w7Os&t=1 "2").
1. Create the Partition Function
This defines how the data is split based on a boundary value (like a date or ID) [1](https://www.certlibrary.com/blog/understanding-table-partitioning-in-sql-server-a-beginners-guide/#:~:text=The%20Role%20of%20Partition%20Functions,based%20on%20those%20date%20cutoffs. "1"), [2](https://www.sqlservertutorial.net/sql-server-administration/sql-server-table-partitioning/#:~:text=2%29%20Create%20a%20partition%20function,of%20partitions%20and%20partition%20boundaries.&text=In%20this%20statement:,belong%20to%20the%20partition%203. "2").
- RANGE LEFT : The boundary value is the maximum value in the lower partition [1](https://learn.microsoft.com/en-us/sql/relational-databases/partitions/partitioned-tables-and-indexes?view=sql-server-ver17#:~:text=In%20other%20words%2C%20the%20lowest,2022%2D12%2D01'%29; "1"), [2](https://www.dbi-services.com/blog/sql-server-manage-large-data-ranges-using-partitioning/#:~:text=We%20want%20to%20partition%20a,to%20multiple%20or%20one%20filegroup. "2").
- RANGE RIGHT : The boundary value is the minimum value in the higher partition (commonly used for dates) [1](https://learn.microsoft.com/en-us/sql/relational-databases/partitions/partitioned-tables-and-indexes?view=sql-server-ver17#:~:text=In%20other%20words%2C%20the%20lowest,2022%2D12%2D01'%29; "1"), [2](https://www.dbi-services.com/blog/sql-server-manage-large-data-ranges-using-partitioning/#:~:text=We%20want%20to%20partition%20a,to%20multiple%20or%20one%20filegroup. "2"), [3](https://www.certlibrary.com/blog/understanding-table-partitioning-in-sql-server-a-beginners-guide/#:~:text=The%20Role%20of%20Partition%20Functions,based%20on%20those%20date%20cutoffs. "3").
sql
-- Example: Partitioning by year using RANGE RIGHT
CREATE PARTITION FUNCTION pfSalesDate (datetime2)
AS RANGE RIGHT FOR VALUES ('2023-01-01', '2024-01-01', '2025-01-01');
-- This creates 4 partitions: < 2023, 2023, 2024, and >= 2025
2. Create the Partition Scheme
This maps the logical partitions created by the function to physical filegroups [1](https://www.dbi-services.com/blog/sql-server-manage-large-data-ranges-using-partitioning/#:~:text=We%20want%20to%20partition%20a,to%20multiple%20or%20one%20filegroup. "1"), [2](https://devcom.com/tech-blog/how-to-partition-a-table-in-sql-server/#:~:text=Create%20Partitioned%20Table:%20Use%20partition%20scheme%20to,table%2C%20improve%20data%20management%2C%20and%20optimize%20performance. "2"). You can map all partitions to a single filegroup (like PRIMARY) or distribute them across multiple disks [1](https://learn.microsoft.com/en-us/sql/relational-databases/partitions/create-partitioned-tables-and-indexes?view=sql-server-ver17#:~:text=are%20being%20created.-,Create%20a%20partitioned%20table%20on%20one%20filegroup%20using%20Transact%2DSQL,col1%20as%20the%20partitioning%20column. "1"), [2](https://www.sqlshack.com/sql-partition-overview/#:~:text=What%20does%20SQL%20partition%20mean%20in%20a%20table?,Horizontal%20partition%20and%20vertical%20partition.&text=In%20the%20previous%20image%2C%20we,separated%20Filegroup%20and%20hard%20disk.&text=In%20horizontal%20partitioning%2C%20we%20divide,table%20partitioning%20in%20SQL%20Server "2").
sql
-- Map all partitions to the PRIMARY filegroup
CREATE PARTITION SCHEME psSalesDate
AS PARTITION pfSalesDate
ALL TO ([PRIMARY]);
3. Create the Partitioned Table
Apply the scheme to the table during creation by specifying the partitioning column [1](https://pragmaticworks.com/blog/table-partitioning-in-sql-server-partition-switching "1"), [2](https://learn.microsoft.com/en-us/sql/relational-databases/partitions/create-partitioned-tables-and-indexes?view=sql-server-ver17#:~:text=are%20being%20created.-,Create%20a%20partitioned%20table%20on%20one%20filegroup%20using%20Transact%2DSQL,col1%20as%20the%20partitioning%20column. "2").
sql
CREATE TABLE Sales (
SalesID INT IDENTITY(1,1),
OrderDate DATETIME2 NOT NULL,
Amount DECIMAL(18,2)
) ON psSalesDate (OrderDate); -- The table is now partitioned by OrderDate
Key Considerations
- Partition Elimination : SQL Server only reads the relevant partitions if your query filters by the partition key, significantly boosting performance [1](https://www.cathrinewilhelmsen.net/table-partitioning-in-sql-server/#:~:text=What%20is%20Table%20Partitioning?,covered%20in%20this%20blog%20post.%29 "1"), [2](https://www.rudderstack.com/guides/sql-table-and-data-partitioning-how-to/#:~:text=The%20benefits%20of%20SQL%20partitioning,-The%20benefits%20such&text=If%2C%20for%20example%2C%20you%20have,cheaper%20and%20slower%20storage%20media. "2").
- Maintenance : Partitioning makes it easier to "switch" data in or out for archiving, or to truncate specific time periods without affecting the whole table [1](https://www.youtube.com/watch?v=LRYDt9qjjq0&t=2 "1"), [2](https://pragmaticworks.com/blog/table-partitioning-in-sql-server-partition-switching "2").
- Clustered Indexes : For an existing table, you can partition it by recreating the clustered index on the partition scheme [1](https://www.mssqltips.com/sqlservertip/2888/how-to-partition-an-existing-sql-server-table/#:~:text=SQL%20Server%20Partitioned%20Table%20Creation%20Table_content:%20header:,row:%20%7C%20objectname:%20TABLE1%20%7C%20indexname:%20IX_TABLE1_partiti "1"), [2](https://learn.microsoft.com/en-us/answers/questions/1097746/step-by-step-partition-table-in-sql-server#:~:text=Hi%20All%2C,rows%29%20to%20new%20partitioned%20table. "2").
We can use the built-in Create Partition Wizard in SQL Server Management Studio (SSMS) to generate this script without writing manual code [1](https://learn.microsoft.com/en-us/sql/relational-databases/partitions/create-partitioned-tables-and-indexes?view=sql-server-ver17#:~:text=to%20partition%20col1%20.-,In%20Object%20Explorer%2C%20connect%20to%20an%20instance%20of%20Database%20Engine,SELECT%20Execute. "1"), [2](https://www.sqlshack.com/database-table-partitioning-sql-server/#:~:text=Partitioning%20a%20table%20using%20the,in%20SQL%20Server%20Management%20Studio.&text=Other%20options%20in%20the%20Create,with%20the%20same%20partition%20scheme.&text=Click%20the%20Next%20button%20and,is%20based%20on%20Value%20%3C%20Boundary.&text=The%20Estimate%20storage%20option%20determines,of%20records%20in%20the%20table. "2").
Using the SSMS Partition Wizard
- Open the Wizard : Right-click your table, select Storage > Create Partition... [1](https://learn.microsoft.com/en-us/sql/relational-databases/partitions/create-partitioned-tables-and-indexes?view=sql-server-ver17#:~:text=to%20partition%20col1%20.-,In%20Object%20Explorer%2C%20connect%20to%20an%20instance%20of%20Database%20Engine,SELECT%20Execute. "1"), [2](https://www.sqlshack.com/database-table-partitioning-sql-server/#:~:text=Partitioning%20a%20table%20using%20the,in%20SQL%20Server%20Management%20Studio.&text=Other%20options%20in%20the%20Create,with%20the%20same%20partition%20scheme.&text=Click%20the%20Next%20button%20and,is%20based%20on%20Value%20%3C%20Boundary.&text=The%20Estimate%20storage%20option%20determines,of%20records%20in%20the%20table. "2").
- Select Column: Choose your date column.
- Set Boundaries : On the Map Partitions page, click the Set Boundaries... button [1](https://learn.microsoft.com/en-us/sql/relational-databases/partitions/create-partitioned-tables-and-indexes?view=sql-server-ver17#:~:text=to%20partition%20col1%20.-,In%20Object%20Explorer%2C%20connect%20to%20an%20instance%20of%20Database%20Engine,SELECT%20Execute. "1").
- Configure Range :
- Start Date :
2020-01-01 - End Date :
2030-01-01 - Date Range : Select Daily [1](https://learn.microsoft.com/en-us/sql/relational-databases/partitions/create-partitioned-tables-and-indexes?view=sql-server-ver17#:~:text=to%20partition%20col1%20.-,In%20Object%20Explorer%2C%20connect%20to%20an%20instance%20of%20Database%20Engine,SELECT%20Execute. "1").
- Start Date :
- Script It : On the final page, select Script to New Query Window rather than running it immediately. This allows you to review the thousands of generated boundary lines [1](https://learn.microsoft.com/en-us/sql/relational-databases/partitions/create-partitioned-tables-and-indexes?view=sql-server-ver17#:~:text=to%20partition%20col1%20.-,In%20Object%20Explorer%2C%20connect%20to%20an%20instance%20of%20Database%20Engine,SELECT%20Execute. "1"), [2](https://www.sqlservercentral.com/forums/topic/automate-new-partition-creation-in-table-partitioning "2").
To maintain a partitioned table---especially one with daily partitions ---you primarily use Sliding Windowoperations. This allows you to add new days and archive old ones without moving data row-by-row.
1. Adding a New Partition (SPLIT)
To prepare for tomorrow's data, you "split" the last partition. Warning: The target filegroup must be empty or the operation will be slow.
sql
-- 1. Update the Scheme to tell it where the next partition goes
ALTER PARTITION SCHEME psDaily
NEXT USED [PRIMARY];
-- 2. Split the Function to add the new boundary (e.g., Jan 2, 2030)
ALTER PARTITION FUNCTION pfDaily()
SPLIT RANGE ('2030-01-02');
2. Removing Old Data (TRUNCATE or SWITCH)
If you want to delete a specific day's data instantly:
-
Option A: Truncate a specific partition (Fastest, SQL 2016+)
sqlTRUNCATE TABLE Sales WITH (PARTITIONS (1)); -- Removes all rows in Partition 1 -
Option B: Switch to an Archive table (Best for moving data to history)
sql-- Move Partition 1 data to an identical empty table ALTER TABLE Sales SWITCH PARTITION 1 TO Sales_Archive;
3. Merging Partitions (MERGE)
After archiving or deleting data, you "merge" the empty partition boundary to keep the total number of partitions manageable.
sql
-- Removes the boundary for Jan 1, 2020, merging that range into the next one
ALTER PARTITION FUNCTION pfDaily()
MERGE RANGE ('2020-01-01');
4. Checking Partition Health
Use this query to see exactly how many rows are in each day and which partition number they belong to:
sql
SELECT
p.partition_number,
f.name AS [PartitionFunction],
rv.value AS [BoundaryValue],
p.rows
FROM sys.partitions p
JOIN sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id
JOIN sys.partition_schemes s ON i.data_space_id = s.data_space_id
JOIN sys.partition_functions f ON s.function_id = f.function_id
LEFT JOIN sys.partition_range_values rv ON f.function_id = rv.function_id
AND p.partition_number = rv.boundary_id + 1
WHERE p.object_id = OBJECT_ID('Sales') AND i.index_id <= 1;
5. Index Maintenance
You can rebuild indexes for a single partition instead of the whole table, which saves time and transaction log space.
sql
ALTER INDEX PK_Sales ON Sales
REBUILD PARTITION = 500; -- Rebuilds only the 500th day/partition