Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Open Database Connectivity wikipedia , lookup
Functional Database Model wikipedia , lookup
Clusterpoint wikipedia , lookup
Microsoft SQL Server wikipedia , lookup
Entity–attribute–value model wikipedia , lookup
Object-relational impedance mismatch wikipedia , lookup
Relational model wikipedia , lookup
SQL Server Technical Article Table Partitioning Implementation with advanced scenarios Writer: Mustafa EL-Masry Technical Reviewer: SQLSERVER Performance tuning (http://sqlserver-performance-tuning.net/) Published: December 2014 Applies to: SQL Server 2012, 2014 SlideShare: http://www.slideshare.net/MostafaElmasry3/table-partitioning-implementation-with- advanced-scenarios-43436743 About The Writer I am Mustafa El-Masry Senior Database administrator and DB Analyst of the Ministry of Higher Education (The first DB environment over KSA as accredited by Microsoft ), also I have deep practical knowledge about T-SQL performance , HW Performance issues, Data Warehousing and data mart solutions , SQL Server Replication, Clustering solutions (Active Active and active passive)and Database Designs for different kinds of systems , HAG, diving deeply more : Founder of Community :SQL DATABASE ADMINISTRATION https://mostafaelmasry.wordpress.com/ Audience Marketing Manager and Executive Board member : SQLSERVER PERFORMANCE TUNING COMMUNITY http://sqlserver-performance-tuning.net/ in fluent Participator at Microsoft Forums of SQL Server at http://Social.technet.microsoft.com Microsoft Profile :https://www.mcpvirtualbusinesscard.com/VBCServer/EngMostafaElamsry/profile Chart for all my posts: http://sqlserver-performance-tuning.net/?p=4526 If you have any issue any Performance Case , disaster recovery anything related to SQL Server technology. Please do not hesitate to contact me to arrange a time. I am available by phone at +966 543990968, 00201114668821 or VIA mail [email protected] , [email protected] Linked in: https://www.linkedin.com/in/mostafaelmasry SQL Training: https://mostafaelmasry.wordpress.com/training/ Summary: Table partitioning can make very large tables and indexes easier to manage, and improve the performance of appropriately filtered queries. This paper contains a thorough coverage of strategies for partitioning tables, including the required partition functions and partition schemes. The benefits of partition elimination, partition parallelism, and index partition maintenance are also explored. These strategies are applied to various partitioning scenarios such as the sliding window scenario, data archiving, and partition consolidation and movement. Introduction and overview When a database table grows in size to the hundreds of gigabytes or more, it can become more difficult to load new data, remove old data, and maintain indexes. Just the sheer size of the table causes such operations to take much longer. Even the data that must be loaded or removed can be very sizable, making INSERT and DELETE operations on the table impractical. The Microsoft® SQL Server® 2012 database software provides table partitioning to make such operations more manageable. Partitioning a large table divides the table and its indexes into smaller partitions, so that maintenance operations can be applied on a partition-by-partition basis, rather than on the entire table. In addition, the SQL Server optimizer can direct properly filtered queries to appropriate partitions rather than the entire table. This paper covers strategies and best practices for using partitioned tables and indexes in SQL Server 2012. It is intended for database architects, developers, and administrators of both data warehouse and OLTP systems, and the material is presented at an intermediate to advanced level. For more Information: Table Partitioning Implementation with advanced scenarios (Part 1) http://sqlserver-performance-tuning.net/?p=5061 Table Partitioning Implementation with advanced scenarios (Part 2) http://sqlserver-performance-tuning.net/?p=5075 Table Partitioning Implementation with advanced scenarios (Part 3) http://sqlserver-performance-tuning.net/?p=5091 Table Partitioning Implementation with advanced scenarios (Part 4) http://sqlserver-performance-tuning.net/?p=5098 What is Table Partitioning? Table partitioning consists in a technique adopted by some database management systems to deal with large databases. Instead of a single table storage location, they split your table in several files for quicker queries. If you have a table which will store large amounts of data (I mean REALLY large amounts, like millions of records) table partitioning will be a good option. Queries that access only a fraction of the data can run faster because there is less data to scan. Why we need to use Table Partitioning? Where tables and indexes become very large, partitioning can help by splitting large amounts of data into smaller more manageable chunks, the type of partitioning described in this post is termed horizontal partitioning. With horizontal partitioning, large chunks of rows will be stored in multiple separate partitions. The definition of the partitioned set is customized, defined, and managed – by your needs. Partitioning in SQL Server 2005 allows you to partition your tables based on specific data usage patterns using defined ranges. Pros and Cons of Partitioning in SQL Server? PROS: Low overhead (locks, speed) in sliding large amounts of data into separate table for truncation (our primary concern) Increased performance. No need to create separate physical tables for each ranges manually. There are few limitations when you insert data into Partition View like you cannot use BULK INSERT/BCP etc. Less complex to manage and administrate SQL Server automatically manages the placement of data in the proper partitions. CONS Major disadvantage is, we cannot have different index model for different range…In general, and we may need to have more number of indexes when the data is READ ONLY and less or different index model for the data which is READWRITE. That is not possible with partition table. You cannot rebuild a partitioned index with the ONLINE option set to ON, because the entire table will be locked during the rebuild. Additional data required in indexes (and queries) to have aligned indexes Other limitations associated with aligned indexes? Table patriating rules You cannot change the data type of the partitioning column once the table is partitioned. You can move an index to a partition scheme after it has been created. You cannot use the SWITCH option of ALTER TABLE statement on replicated tables. For a unique key or primary key index to be partitioned, the partitioning key must be part of the unique key (or the index key). Partitioning key of an index doesn’t have to be part of the index key. For More information check this Link http://www.toadworld.com/platforms/sql-server/w/wiki/9655.partitioned-table-rules-and-gotchas.aspx What is the Difference Partitioning Type on SQL SERVER We have two kind of partitioning in SQL Server Vertical Partitioning and Horizontal Partitioning let’s go deeply to know what is the difference between the two types For more Information about Horizontal Partitioning, Vertical Partitioning and Hardware Partitioning go for this Link http://technet.microsoft.com/en-us/library/ms178148(v=sql.105).aspx Vertical Partitioning Vertical partitioning segments columns into multiple tables containing the same rows Vertical partitioning divides a table into multiple tables that contain fewer columns. Vertical Partitioning The two types of vertical partitioning are normalization and row splitting: by removing some columns from the primary table to Secondary table that are linked to the primary table by primary key and foreign key relationships. We cannot decide vertical partitioning is good or bad from the performance because it’s based on x of reasons (Column Data Type, Column Size, and Volume of data …) so it’s ultimately not good not bad. As we can see from the image based on our requirement and our Queries hitting this table we can diced how we can splitting the Table by this way we will reduce the IO and CPU for the query scan When I can use Vertical Partitioning: If I had 100 columns (or some large number) and didn’t often query some of them, or queried others very often, then I can save I/O and unneeded reads by moving some data to another table. Like the Example on the image Horizontal Partitioning Horizontal partitioning divides a table into multiple tables. Each table have the same columns (Same table structure but the data distributed in this multiple tables according the igure2 Rang partition so if we have Millions of record we can partitioned horizontally into Multiple tables so any Query hitting our data will select from the Specific table and by this we will fast the Query Execution and the IO. Table partitioning dependence Partitioning Function That maps the rows of a table or index into partitions based on the boundary_value , we can build the Partition Function by two ways based on our Requirement and our business needed RANGE RIGHT RANGE LEFT Another thing the boundary value we can do it on three data type INT COLUMN DATETIME COLUMN CHAR COLUMN Partitioning Scheme That maps the partitions of a partitioned table or index to filegroups, partition scheme must be created on partition function, partition scheme can be used for one or more partitioned tables, indexes, and indexed views. Partitioning Table/Index is tied to a particular partition scheme when it is created, partition table has only an indirect relationship, through the partition scheme, to the partition function at the end The relationship between a partition function and a partition scheme is one-to-many as is the relationship between a partition scheme and partitioned tables and indexes, because moving data in and out of a partitioned table usually requires modifying the partition function for more information: Partitioned Tables and Indexes in SQL Server 2005 at http://msdn.microsoft.com/enus/library/ms345146.aspx Strategies for Partitioning Relational Data Warehouses in Microsoft SQL Server at http://technet.microsoft.com/en-us/library/cc966457.aspx let’s go now for the TECHNICAL DEMO to know How we can implement the table partitioning step by step from Scratch Range Direction How to implement Table partitioning Step by step (RANGE LEFT) How to implement table partitioning step by step (RANGE RIGHT) Implement Partitioned Table with Range Right to implement any partitioned table from SCRATCH we have basic 6 steps we will do it now by T-SQL and by SQL SERVER WIZARD Create Database (T-SQL / Wizard) Create FILEGROUP (T-SQL / Wizard) Create files and add it to the FILEGROUP (T-SQL / Wizard) Create partition Function (RANGE RIGHT / RANGE LEFT) (T-SQL only) Create partition Scheme (T-SQL only) Create Table Partitioning (T-SQL only) At the first i will do it by T-SQL Create Database I will create new database [DBForPartitioning] to be for our entire workshop to the end of the series CREATE DATABASE [DBForPartitioning] GO ALTER DATABASE [DBForPartitioning] MODIFY FILE ( NAME = N'DBForPartitioning', SIZE = 256MB , MAXSIZE = 10GB , FILEGROWTH = 512MB ); ALTER DATABASE [DBForPartitioning] MODIFY FILE ( NAME = N'DBForPartitioning_log', SIZE = 128MB , FILEGROWTH = 128MB ); GO Create Filegroups Here we will create four filegroup (FG1, FG2, FG3, and FG4) to can use it on the Partition Scheme USE [master] GO ALTER DATABASE [DBForPartitioning] ADD FILEGROUP [FG1] ALTER DATABASE [DBForPartitioning] ADD FILEGROUP [FG2] ALTER DATABASE [DBForPartitioning] ADD FILEGROUP [FG3] ALTER DATABASE [DBForPartitioning] ADD FILEGROUP [FG4] GO Create Files and add it to Filegroups In this step I will create four files and add it on the FILEGROUP and all of this i will do it dynamically Use DBForPartitioning Go DECLARE @path NVARCHAR(256) , @i TINYINT= 1 , @sql NVARCHAR(4000); SELECT TOP 1 @path = LEFT(physical_name, LEN(physical_name) - 4) FROM sys.database_files WHERE name = 'DBForPartitioning' WHILE @i <= 4 BEGIN SET @sql = N'ALTER DATABASE DBForPartitioning ADD FILE (name=File' + CAST(@i AS NCHAR(1)) + ', filename=''' + @path + N'File' + CAST(@i AS NCHAR(1)) + '.ndf' + ''', size=128MB, filegrowth=256MB) TO FILEGROUP FG' + CAST(@i AS NCHAR(1)) RAISERROR (@sql,0,0) EXEC sp_executesql @sql; SET @i += 1; END GO Range Direction Right and Date time Boundary Values Next three steps I will do everything on the RANGE RIGHT and RANGE LEFT so I will work on parallel Create Partitioning Function In this case I will do partition function with boundary_value DATETIME and Use DBForPartitioning GO CREATE PARTITION FUNCTION PF_DBForPartitioning_RangeRight (datetime) AS RANGE RIGHT FOR VALUES ( '2008-01-01','2009-01-01', '2010-01-01'); Create Partitioning Scheme I will create Partition scheme on PF (PF_DBForPartitioning_RangeRight) on the four filegroup Use DBForPartitioning GO CREATE PARTITION SCHEME PS_DBForPartitioning_RangeRight AS PARTITION PF_DBForPartitioning_RangeRight TO (FG1, FG2, FG3 ,FG4) GO Create Table Partitioning Now i will create table partitioning on Partitioning Scheme [PS_DBForPartitioning_RangeRight] on datetime Column Use DBFOrPartitioning GO CREATE TABLE Partitioning_RangeRight (Partitioning_ID int , Partitioning_time datetime) ON PS_DBForPartitioning_RangeRight (Partitioning_time); GO Now the sex basic steps for any table partitioning is finished and I will go now for fill the table by some test data then I will show some wonderful Stored Procedures and Scripts it will return to us all the information about the Partition Function ,Partition Scheme and table Partition , ….etc. Fill Table by adequate volumes of data Use DBFOrPartitioning GO INSERT INTO Partitioning_RangeRight (Partitioning_ID, Partitioning_time) SELECT 1 ,'2007-01-01'UNION ALL SELECT 2 ,'2007-10-01'UNION ALL SELECT 3 ,'2008-01-01'UNION ALL SELECT 4 ,'2008-08-09'UNION ALL SELECT 5 ,'2008-12-30'UNION ALL SELECT 6 ,'2009-01-01'UNION ALL SELECT 7 ,'2009-05-24'UNION ALL SELECT 8 ,'2010-01-24'UNION ALL SELECT 9 ,'2010-05-24'UNION ALL SELECT 10,'2011-05-24' GO How to Monitor Partitioned Table (Part1) Select Partitioned Table in DB Use DBFOrPartitioning GO select distinct t.name from sys.partitions p inner join sys.tables t on p.object_id = t.object_id where p.partition_number <> 1 Stored Procedure to return Partitioned Columns Create Proc partitioning_Column (@Table_Name Nvarchar(500)) AS Begin SELECT CAST(ic.partition_ordinal AS INT) AS [ID], c.name AS ColumnName FROM sys.tables AS tbl INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id AND idx.index_id < 2 INNER JOIN sys.index_columns ic ON (ic.partition_ordinal > 0) AND (ic.index_id = idx.index_id AND ic.object_id = CAST(tbl.object_id AS INT)) INNER JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id WHERE (tbl.name = @Table_Name AND SCHEMA_NAME(tbl.schema_id) = 'dbo') ORDER BY [ID] END Exec partitioning_Column 'Partitioning_RangeRight' Select Partition_Id with partition_Number select partition_id, index_id, partition_number, Rows FROM sys.partitions WHERE OBJECT_NAME(OBJECT_ID)='Partitioning_RangeRight' GO Select Partition Function and partition Scheme name select ps.Name PartitionScheme, pf.name PartitionFunction from sys.indexes i join sys.partition_schemes ps on ps.data_space_id = i.data_space_id join sys.partition_functions pf on pf.function_id = ps.function_id where i.object_id = object_id('Partitioning_RangeRight') Stored procedure To return all Detail about the data Create proc PartitionTableDetail(@tablename Nvarchar(500)) As begin SELECT ISNULL(quotename(ix.name),'Heap') as IndexName ,ix.type_desc as type ,prt.partition_number ,prt.data_compression_desc ,ps.name as PartitionScheme ,pf.name as PartitionFunction ,fg.name as FilegroupName ,case when ix.index_id < 2 then prt.rows else 0 END as Rows ,au.TotalMB ,au.UsedMB ,case when pf.boundary_value_on_right = 1 then 'less than' when pf.boundary_value_on_right is null then '' else 'less than or equal to' End as Comparison ,fg.name as FileGroup ,rv.value As Rang_value, T.name AS Range_Type FROM sys.partitions prt inner join sys.indexes ix on ix.object_id = prt.object_id and ix.index_id = prt.index_id inner join sys.data_spaces ds on ds.data_space_id = ix.data_space_id left join sys.partition_schemes ps on ps.data_space_id = ix.data_space_id left join sys.partition_functions pf on pf.function_id = ps.function_id inner join sys.partition_parameters PP on pf.function_id = PP.function_id inner join sys.types t on t.system_type_id = PP.system_type_id left join sys.partition_range_values rv on rv.function_id = pf.function_id AND rv.boundary_id = prt.partition_number left join sys.destination_data_spaces dds on dds.partition_scheme_id = ps.data_space_id AND dds.destination_id = prt.partition_number left join sys.filegroups fg on fg.data_space_id = ISNULL(dds.data_space_id,ix.data_space_id) inner join (select str(sum(total_pages)*8./1024,10,2) as [TotalMB] ,str(sum(used_pages)*8./1024,10,2) as [UsedMB] ,container_id from sys.allocation_units group by container_id) au on au.container_id = prt.partition_id WHERE prt.OBJECT_ID = object_id(@tablename) order by ix.type_desc; END Exec PartitionTableDetail 'Partitioning_RangeRight' Implement Partitioned Table with Range Left Create Partitioning Function In this case i will do partition function with boundary_value DATETIME and GO CREATE PARTITION FUNCTION PF_DBForPartitioning_RangeLeft (datetime) AS RANGE left FOR VALUES ( '2008-01-01','2009-01-01', '2010-01-01'); Create Partitioning Scheme I will create Partition scheme on PF(PF_DBForPartitioning_Rangeleft) on the four filegroup Use DBForPartitioning GO CREATE PARTITION SCHEME PS_DBForPartitioning_Rangeleft AS PARTITION PF_DBForPartitioning_RangeLeft TO (FG1, FG2, FG3 ,FG4) Create Table Partitioning Now I will create table partitioning on Partitioning Scheme [PS_DBForPartitioning_RangeLeft] on datetime Column Use DBFOrPartitioning GO CREATE TABLE Partitioning_Rangeleft (Partitioning_ID int , Partitioning_time datetime) ON PS_DBForPartitioning_Rangeleft (Partitioning_time); GO Fill Table by adequate volumes of data Use DBFOrPartitioning GO INSERT INTO Partitioning_Rangeleft (Partitioning_ID, Partitioning_time) SELECT 1 ,'2007-01-01'UNION ALL SELECT 2 ,'2007-10-01'UNION ALL SELECT 3 ,'2008-01-01'UNION ALL SELECT 4 ,'2008-08-09'UNION ALL SELECT 5 ,'2008-12-30'UNION ALL SELECT SELECT SELECT SELECT SELECT GO 6 ,'2009-01-01'UNION 7 ,'2009-05-24'UNION 8 ,'2010-01-24'UNION 9 ,'2010-05-24'UNION 10,'2011-05-24' ALL ALL ALL ALL Now to know more information about the data inserted and the table partition please check the and Execute the Stored procedure [PartitionTableDetail] Exec PartitionTableDetail 'Partitioning_Rangeleft' also you can Execute the below query it will return to you all the information about the current partition function and partition Schema Exist on DB [] and the boundary_value SELECT f.NAME AS file_group_name, SCHEMA_NAME(t.schema_id) AS table_schema, t.name AS table_name, p.partition_number, ISNULL(CAST(left_prv.value AS VARCHAR(MAX))+ CASE WHEN pf.boundary_value_on_right = 0 THEN ' < ' ELSE ' <= ' END , '-INF < ') + 'X' + ISNULL(CASE WHEN pf.boundary_value_on_right = 0 THEN ' <= ' ELSE ' < ' END + CAST(right_prv.value AS NVARCHAR(MAX)), ' < INF') AS range_desc, pf.boundary_value_on_right, ps.name AS partition_schem_name, pf.name AS partition_function_name, left_prv.value AS left_boundary, right_prv.value AS right_boundary FROM sys.partitions p JOIN sys.tables t ON p.object_id = t.object_id JOIN sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id JOIN sys.allocation_units au ON p.hobt_id = au.container_id JOIN sys.filegroups f ON au.data_space_id = f.data_space_id LEFT JOIN sys.partition_schemes ps ON ps.data_space_id = i.data_space_id LEFT JOIN sys.partition_functions pf ON ps.function_id = pf.function_id LEFT JOIN sys.partition_range_values left_prv ON left_prv.function_id = ps.function_id AND left_prv.boundary_id + 1 = p.partition_number LEFT JOIN sys.partition_range_values right_prv ON right_prv.function_id = ps.function_id AND right_prv.boundary_id = p.partition_number How to Monitor Partitioned Table (Part2) Determined the partition in which particular row is stored Only you need to put your table name as example if i need to know the inserted row with [Partitioning_time] = ‘2008-01-01 00:00:00.000′ inserted in witch Partition in the table [Partitioning_Rangeleft] with cte as( SELECT T.*, DDDPA.partition_id AS partition_number, ISNULL ( CAST(LEFT_PRV.value AS VARCHAR(MAX)) + CASE WHEN PF.boundary_value_on_right = 0 THEN ' < ' ELSE ' <= ' END , '-INF < ' ) + 'X' + ISNULL ( CASE WHEN PF.boundary_value_on_right = 0 THEN ' <= ' ELSE ' < ' END + CAST(RIGHT_PRV.value AS NVARCHAR(MAX)), ' < INF' ) AS range_desc, PF.boundary_value_on_right FROM dbo.Partitioning_Rangeleft AS T CROSS APPLY sys.fn_PhysLocCracker(T.%%physloc%%) AS FPLC JOIN sys.dm_db_database_page_allocations(DB_ID(),NULL,NULL,NULL,NULL) AS DDDPA ON DDDPA.allocated_page_page_id = FPLC.page_id AND DDDPA.allocated_page_file_id = FPLC.file_id JOIN sys.indexes AS I ON DDDPA.object_id = I.object_id AND DDDPA.index_id = I.index_id LEFT JOIN sys.partition_schemes PS ON PS.data_space_id = I.data_space_id LEFT JOIN sys.partition_functions pf ON ps.function_id = pf.function_id LEFT JOIN sys.partition_range_values left_prv ON left_prv.function_id = ps.function_id AND left_prv.boundary_id + 1 = DDDPA.partition_id LEFT JOIN sys.partition_range_values right_prv ON right_prv.function_id = ps.function_id AND right_prv.boundary_id = DDDPA.partition_id) Select * from CTE where Partitioning_time ='2008-01-01 00:00:00.000'; Or by another simple way but at this time you will select from the Partition function not from the table SELECT $PARTITION.PF_DBForPartitioning_RangeLeft ('2008-01-01 00:00:00.000') ; GO Special Condition for partitions Merge IF you wanted to remove a boundary instead. Let’s say you have a boundary in use that is completely empty, and you want to stop using that partition, to free it up for some reason, then you want to use the MERGE operator. The syntax is just like SPLIT, except the boundary point you pass will be removed from your PARTITION FUNCTION Note: Merge will not remove physical filegroup from the database structure, it just do merging of two different sets into one So let’s go now to MERGE boundary ’2009-01-01′ we will work on the Example of RANGE RIGHT ALTER PARTITION FUNCTION PF_DBForPartitioning_RangeRight() MERGE RANGE('2009-01-01') Now to check what happened for the boundary_value and our Partitioning Function you will found Filegroup FG3 is merged with FG2 this meaning FG3 is deleted?? NO filegroup still exist but not used in this Function Execute our main SP to check the Table partitioning after MERGE operator Exec PartitionTableDetail 'Partitioning_RangeRight' Compare Partition function Syntax before MERGE and after MERGE Before MERGE CREATE PARTITION FUNCTION PF_DBForPartitioning_RangeRight (datetime) AS RANGE RIGHT FOR VALUES ( '2008-01-01','2009-01-01', '2010-01-01'); After MERGE CREATE PARTITION FUNCTION [PF_DBForPartitioning_RangeRight](datetime) AS RANGE RIGHT FOR VALUES (N'2008-01-01T00:00:00.000', N'2010-01-01T00:00:00.000') GO Split Adds one partition to the partition function. boundary_value determines the range of the new partition, and must differ from the existing boundary ranges of the partition function. Based on boundary_value, the Database Engine splits one of the existing ranges into two. Of these two, the one where the new boundary_value resides is considered the new partition. At the first I will ALTER PARTITION SCHEME to Adds a filegroup to a partition scheme or alters the designation of the NEXT USED filegroup for the partition scheme. Make a new partition filegroup available to the partition scheme ALTER PARTITION SCHEME PS_DBForPartitioning_RangeRight NEXT USED [FG3] ; Add a new partition (which will use the filegroup identified as “next used”) ALTER PARTITION FUNCTION PF_DBForPartitioning_RangeRight() SPLIT RANGE ('2009-01-01') Now View information about the partitions and partitioned data I write in this series more scripts about this part so you can view this information by the our stored Procedure PartitionTableDetail or by the below new Script SELECT N'DatabaseName' = DB_NAME() , N'SchemaName' = s.name , N'TableName' = o.name , N'IndexName' = i.name , N'IndexType' = i.type_desc , N'PartitionScheme' = ps.name , N'DataSpaceName' = ds.name , N'DataSpaceType' = ds.type_desc , N'PartitionFunction' = pf.name , N'PartitionNumber' = dds.destination_id , N'BoundaryValue' = prv.value , N'RightBoundary' = pf.boundary_value_on_right -- 1 = TRUE (values are less than boundary) -- 0 = FALSE (values are less than or equal to boundary) , N'PartitionFileGroup' = ds2.name , N'RowsOfData' = p.[rows] FROM sys.objects AS o INNER JOIN sys.schemas AS s ON o.[schema_id] = s.[schema_id] INNER JOIN sys.partitions AS p ON o.[object_id] = p.[object_id] INNER JOIN sys.indexes AS i ON p.[object_id] = i.[object_id] AND p.index_id = i.index_id INNER JOIN sys.data_spaces AS ds ON i.data_space_id = ds.data_space_id LEFT OUTER JOIN sys.partition_schemes AS ps ON ds.data_space_id = ps.data_space_id LEFT OUTER JOIN sys.partition_functions AS pf ON ps.function_id = pf.function_id LEFT OUTER JOIN sys.partition_range_values AS prv ON pf.function_id = prv.function_id AND p.partition_number = prv.boundary_id LEFT OUTER JOIN sys.destination_data_spaces AS dds ON ps.data_space_id = dds.partition_scheme_id AND p.partition_number = dds.destination_id LEFT OUTER JOIN sys.data_spaces AS ds2 ON dds.data_space_id = ds2.data_space_id WHERE s.name = N'dbo' -- schema name AND o.name = N'Partitioning_RangeRight' -- table name ORDER BY DatabaseName , SchemaName , TableName , IndexName , PartitionNumber ;