Can I move rows between partitions by updating the partition key?
I would think that this would be a fairly simply question, but I've actually had a difficult time finding an answer for this.
The question:
Can you move rows of data within a partitioned table from one partition to another by simply updating the partition column so that it crosses the partition boundary?
For example, if I have a table that has a partition key:
CREATE TABLE SampleTable
(
SampleID INT PRIMARY KEY,
SampleResults VARCHAR(100) NOT NULL,
)
With the partition function that maps to the primary key:
CREATE PARTITION FUNCTION MyPartitionFunc (INT) AS
RANGE LEFT FOR VALUES (10000, 20000);
Can I move a row from the first partition to the third partition by changing the SampleID from 1 to (say) 500,000?
Note: I'm tagging this as both sql server 2005 and 2008, since they both support partitioning. Do they handle it differently?
sql-server sql-server-2008 sql-server-2005 partitioning
add a comment |
I would think that this would be a fairly simply question, but I've actually had a difficult time finding an answer for this.
The question:
Can you move rows of data within a partitioned table from one partition to another by simply updating the partition column so that it crosses the partition boundary?
For example, if I have a table that has a partition key:
CREATE TABLE SampleTable
(
SampleID INT PRIMARY KEY,
SampleResults VARCHAR(100) NOT NULL,
)
With the partition function that maps to the primary key:
CREATE PARTITION FUNCTION MyPartitionFunc (INT) AS
RANGE LEFT FOR VALUES (10000, 20000);
Can I move a row from the first partition to the third partition by changing the SampleID from 1 to (say) 500,000?
Note: I'm tagging this as both sql server 2005 and 2008, since they both support partitioning. Do they handle it differently?
sql-server sql-server-2008 sql-server-2005 partitioning
add a comment |
I would think that this would be a fairly simply question, but I've actually had a difficult time finding an answer for this.
The question:
Can you move rows of data within a partitioned table from one partition to another by simply updating the partition column so that it crosses the partition boundary?
For example, if I have a table that has a partition key:
CREATE TABLE SampleTable
(
SampleID INT PRIMARY KEY,
SampleResults VARCHAR(100) NOT NULL,
)
With the partition function that maps to the primary key:
CREATE PARTITION FUNCTION MyPartitionFunc (INT) AS
RANGE LEFT FOR VALUES (10000, 20000);
Can I move a row from the first partition to the third partition by changing the SampleID from 1 to (say) 500,000?
Note: I'm tagging this as both sql server 2005 and 2008, since they both support partitioning. Do they handle it differently?
sql-server sql-server-2008 sql-server-2005 partitioning
I would think that this would be a fairly simply question, but I've actually had a difficult time finding an answer for this.
The question:
Can you move rows of data within a partitioned table from one partition to another by simply updating the partition column so that it crosses the partition boundary?
For example, if I have a table that has a partition key:
CREATE TABLE SampleTable
(
SampleID INT PRIMARY KEY,
SampleResults VARCHAR(100) NOT NULL,
)
With the partition function that maps to the primary key:
CREATE PARTITION FUNCTION MyPartitionFunc (INT) AS
RANGE LEFT FOR VALUES (10000, 20000);
Can I move a row from the first partition to the third partition by changing the SampleID from 1 to (say) 500,000?
Note: I'm tagging this as both sql server 2005 and 2008, since they both support partitioning. Do they handle it differently?
sql-server sql-server-2008 sql-server-2005 partitioning
sql-server sql-server-2008 sql-server-2005 partitioning
edited Aug 17 '11 at 16:26
Richard
asked Aug 9 '11 at 19:50
RichardRichard
4,22353156
4,22353156
add a comment |
add a comment |
4 Answers
4
active
oldest
votes
I do not have a 2005 server to test with. 2008 however, appears to handle this as expected:
USE [Test]
GO
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
--Add one record to each partition
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
GO
--Move row between partitions
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
You should see one record in each partition before the update, and both records in the first partition afterwards.
1
that's a nicely done piece of answer!
– Marian
Aug 9 '11 at 21:20
This executes as you describe in SQL Server 2005 as well
– Ben Brocka
Oct 26 '11 at 21:31
-1 This does not test the scenario.$PARTITION
only computes the partition number based on the input; it doesn't actually test where the row physically lives.
– Jon Seigel
Oct 3 '13 at 17:04
add a comment |
To test this, the experiment actually needs to partition the table. See http://www.kodyaz.com/articles/how-to-partition-table-non-partitioned-table-sql-server-2008.aspx
Querying the partitioning function just tells you what the partitioning function says. It doesn't say where the data is stored. You can set up a partitioning function and run it without actually partitioning a table, as has been demonstrated here already.
In order to partition the table, you also have to create file groups and a partitioning scheme that uses the partitioning function to assign function results to file groups. Then you have to put a clustered key on the table that uses that partitioning scheme.
Set up the partitioning
I'm no expert in command line SQL. I used SSMS interface to set up file groups pfg1 (with a pf1 file) and pfg2 (with a pf2 file). Then I declared the partitioning function and scheme:
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
CREATE PARTITION SCHEME ps_IDRange1
AS PARTITION IDRange1
TO (pfg1, pfg2)
GO
Create the table and clustered index
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE CLUSTERED INDEX PK_IDRanges
ON dbo.IDRanges(id) ON ps_IDRange1 (ID)
GO
After you do this, when you query sys.partitions (I have 2005), you see that the table now has two partitions instead of just one for the table. This indicates that we have fully implemented partitioning for this table.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 0
72057597780361216 770674389 1 2 72057597780361216 0
Now that we have two partitions (with a row count for each), we can conduct an experiment.
Insert the rows
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
Check the sys.partitions to see what happened.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 1
72057597780361216 770674389 1 2 72057597780361216 1
Yep. One row in each partition.
Move a row.
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
Check the partitions
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 2
72057597780361216 770674389 1 2 72057597780361216 0
The first partition now has two rows instead of 1, and the second partition has zero rows instead of two.
I think this confirms that the row was automatically moved as a result of modifying the clustered key in a partitioned table.
1
+1 for the first answer to this question that actually tests the scenario. Welcome to DBA.SE!
– Jon Seigel
Oct 3 '13 at 17:02
-1 Can you please point me to the MSDN documents that support your requirements to 'fully' partition a table? Specifically the necessity for separate file-groups and a clustered index?
– Kenneth
Nov 18 '13 at 22:38
add a comment |
Once created the table partition for (IDRanges) table. Then Shall I update the table(IDRanges) through PartitionNumber? Is it possible. Please revert the script soon.
New contributor
add a comment |
I don't think that answer is correct. When you use the value
$PARTITION.IDRange1([ID]) AS Partition
you are simply recalculating what the partition should be, not where the record currently is.
You should use:
select * from sys.partitions where object_id = object_id('IDRanges')
In my tests on sql 2005 the value changes but the record stays in the same partition. This will probably mess with stats and the optimizer as it will run in a multi threaded mode expecting a partition to be in a specific range. It will also be completely wrong when it tries to use partition elimination to only query the relevant partition. I think you need to delete and re-insert each record to get them to move.
2
Searching for$partition
over here suggests that the accepted answer is correct. How are you confirming that the record stays in the same partition after it has been updated?
– Nick Chammas
Oct 26 '11 at 21:38
The first point is true, but the conclusion that the row doesn't move is false -- presumably there's something wrong with the test that was run.
– Jon Seigel
Oct 3 '13 at 17:08
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f4511%2fcan-i-move-rows-between-partitions-by-updating-the-partition-key%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
I do not have a 2005 server to test with. 2008 however, appears to handle this as expected:
USE [Test]
GO
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
--Add one record to each partition
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
GO
--Move row between partitions
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
You should see one record in each partition before the update, and both records in the first partition afterwards.
1
that's a nicely done piece of answer!
– Marian
Aug 9 '11 at 21:20
This executes as you describe in SQL Server 2005 as well
– Ben Brocka
Oct 26 '11 at 21:31
-1 This does not test the scenario.$PARTITION
only computes the partition number based on the input; it doesn't actually test where the row physically lives.
– Jon Seigel
Oct 3 '13 at 17:04
add a comment |
I do not have a 2005 server to test with. 2008 however, appears to handle this as expected:
USE [Test]
GO
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
--Add one record to each partition
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
GO
--Move row between partitions
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
You should see one record in each partition before the update, and both records in the first partition afterwards.
1
that's a nicely done piece of answer!
– Marian
Aug 9 '11 at 21:20
This executes as you describe in SQL Server 2005 as well
– Ben Brocka
Oct 26 '11 at 21:31
-1 This does not test the scenario.$PARTITION
only computes the partition number based on the input; it doesn't actually test where the row physically lives.
– Jon Seigel
Oct 3 '13 at 17:04
add a comment |
I do not have a 2005 server to test with. 2008 however, appears to handle this as expected:
USE [Test]
GO
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
--Add one record to each partition
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
GO
--Move row between partitions
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
You should see one record in each partition before the update, and both records in the first partition afterwards.
I do not have a 2005 server to test with. 2008 however, appears to handle this as expected:
USE [Test]
GO
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
--Add one record to each partition
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
GO
--Move row between partitions
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
GO
--Verify records in partition
SELECT $PARTITION.IDRange1([ID]) AS Partition, COUNT(*) AS [COUNT]
FROM IDRanges
GROUP BY $PARTITION.IDRange1([ID])
ORDER BY Partition ;
You should see one record in each partition before the update, and both records in the first partition afterwards.
answered Aug 9 '11 at 20:38
KennethKenneth
62958
62958
1
that's a nicely done piece of answer!
– Marian
Aug 9 '11 at 21:20
This executes as you describe in SQL Server 2005 as well
– Ben Brocka
Oct 26 '11 at 21:31
-1 This does not test the scenario.$PARTITION
only computes the partition number based on the input; it doesn't actually test where the row physically lives.
– Jon Seigel
Oct 3 '13 at 17:04
add a comment |
1
that's a nicely done piece of answer!
– Marian
Aug 9 '11 at 21:20
This executes as you describe in SQL Server 2005 as well
– Ben Brocka
Oct 26 '11 at 21:31
-1 This does not test the scenario.$PARTITION
only computes the partition number based on the input; it doesn't actually test where the row physically lives.
– Jon Seigel
Oct 3 '13 at 17:04
1
1
that's a nicely done piece of answer!
– Marian
Aug 9 '11 at 21:20
that's a nicely done piece of answer!
– Marian
Aug 9 '11 at 21:20
This executes as you describe in SQL Server 2005 as well
– Ben Brocka
Oct 26 '11 at 21:31
This executes as you describe in SQL Server 2005 as well
– Ben Brocka
Oct 26 '11 at 21:31
-1 This does not test the scenario.
$PARTITION
only computes the partition number based on the input; it doesn't actually test where the row physically lives.– Jon Seigel
Oct 3 '13 at 17:04
-1 This does not test the scenario.
$PARTITION
only computes the partition number based on the input; it doesn't actually test where the row physically lives.– Jon Seigel
Oct 3 '13 at 17:04
add a comment |
To test this, the experiment actually needs to partition the table. See http://www.kodyaz.com/articles/how-to-partition-table-non-partitioned-table-sql-server-2008.aspx
Querying the partitioning function just tells you what the partitioning function says. It doesn't say where the data is stored. You can set up a partitioning function and run it without actually partitioning a table, as has been demonstrated here already.
In order to partition the table, you also have to create file groups and a partitioning scheme that uses the partitioning function to assign function results to file groups. Then you have to put a clustered key on the table that uses that partitioning scheme.
Set up the partitioning
I'm no expert in command line SQL. I used SSMS interface to set up file groups pfg1 (with a pf1 file) and pfg2 (with a pf2 file). Then I declared the partitioning function and scheme:
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
CREATE PARTITION SCHEME ps_IDRange1
AS PARTITION IDRange1
TO (pfg1, pfg2)
GO
Create the table and clustered index
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE CLUSTERED INDEX PK_IDRanges
ON dbo.IDRanges(id) ON ps_IDRange1 (ID)
GO
After you do this, when you query sys.partitions (I have 2005), you see that the table now has two partitions instead of just one for the table. This indicates that we have fully implemented partitioning for this table.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 0
72057597780361216 770674389 1 2 72057597780361216 0
Now that we have two partitions (with a row count for each), we can conduct an experiment.
Insert the rows
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
Check the sys.partitions to see what happened.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 1
72057597780361216 770674389 1 2 72057597780361216 1
Yep. One row in each partition.
Move a row.
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
Check the partitions
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 2
72057597780361216 770674389 1 2 72057597780361216 0
The first partition now has two rows instead of 1, and the second partition has zero rows instead of two.
I think this confirms that the row was automatically moved as a result of modifying the clustered key in a partitioned table.
1
+1 for the first answer to this question that actually tests the scenario. Welcome to DBA.SE!
– Jon Seigel
Oct 3 '13 at 17:02
-1 Can you please point me to the MSDN documents that support your requirements to 'fully' partition a table? Specifically the necessity for separate file-groups and a clustered index?
– Kenneth
Nov 18 '13 at 22:38
add a comment |
To test this, the experiment actually needs to partition the table. See http://www.kodyaz.com/articles/how-to-partition-table-non-partitioned-table-sql-server-2008.aspx
Querying the partitioning function just tells you what the partitioning function says. It doesn't say where the data is stored. You can set up a partitioning function and run it without actually partitioning a table, as has been demonstrated here already.
In order to partition the table, you also have to create file groups and a partitioning scheme that uses the partitioning function to assign function results to file groups. Then you have to put a clustered key on the table that uses that partitioning scheme.
Set up the partitioning
I'm no expert in command line SQL. I used SSMS interface to set up file groups pfg1 (with a pf1 file) and pfg2 (with a pf2 file). Then I declared the partitioning function and scheme:
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
CREATE PARTITION SCHEME ps_IDRange1
AS PARTITION IDRange1
TO (pfg1, pfg2)
GO
Create the table and clustered index
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE CLUSTERED INDEX PK_IDRanges
ON dbo.IDRanges(id) ON ps_IDRange1 (ID)
GO
After you do this, when you query sys.partitions (I have 2005), you see that the table now has two partitions instead of just one for the table. This indicates that we have fully implemented partitioning for this table.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 0
72057597780361216 770674389 1 2 72057597780361216 0
Now that we have two partitions (with a row count for each), we can conduct an experiment.
Insert the rows
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
Check the sys.partitions to see what happened.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 1
72057597780361216 770674389 1 2 72057597780361216 1
Yep. One row in each partition.
Move a row.
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
Check the partitions
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 2
72057597780361216 770674389 1 2 72057597780361216 0
The first partition now has two rows instead of 1, and the second partition has zero rows instead of two.
I think this confirms that the row was automatically moved as a result of modifying the clustered key in a partitioned table.
1
+1 for the first answer to this question that actually tests the scenario. Welcome to DBA.SE!
– Jon Seigel
Oct 3 '13 at 17:02
-1 Can you please point me to the MSDN documents that support your requirements to 'fully' partition a table? Specifically the necessity for separate file-groups and a clustered index?
– Kenneth
Nov 18 '13 at 22:38
add a comment |
To test this, the experiment actually needs to partition the table. See http://www.kodyaz.com/articles/how-to-partition-table-non-partitioned-table-sql-server-2008.aspx
Querying the partitioning function just tells you what the partitioning function says. It doesn't say where the data is stored. You can set up a partitioning function and run it without actually partitioning a table, as has been demonstrated here already.
In order to partition the table, you also have to create file groups and a partitioning scheme that uses the partitioning function to assign function results to file groups. Then you have to put a clustered key on the table that uses that partitioning scheme.
Set up the partitioning
I'm no expert in command line SQL. I used SSMS interface to set up file groups pfg1 (with a pf1 file) and pfg2 (with a pf2 file). Then I declared the partitioning function and scheme:
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
CREATE PARTITION SCHEME ps_IDRange1
AS PARTITION IDRange1
TO (pfg1, pfg2)
GO
Create the table and clustered index
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE CLUSTERED INDEX PK_IDRanges
ON dbo.IDRanges(id) ON ps_IDRange1 (ID)
GO
After you do this, when you query sys.partitions (I have 2005), you see that the table now has two partitions instead of just one for the table. This indicates that we have fully implemented partitioning for this table.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 0
72057597780361216 770674389 1 2 72057597780361216 0
Now that we have two partitions (with a row count for each), we can conduct an experiment.
Insert the rows
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
Check the sys.partitions to see what happened.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 1
72057597780361216 770674389 1 2 72057597780361216 1
Yep. One row in each partition.
Move a row.
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
Check the partitions
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 2
72057597780361216 770674389 1 2 72057597780361216 0
The first partition now has two rows instead of 1, and the second partition has zero rows instead of two.
I think this confirms that the row was automatically moved as a result of modifying the clustered key in a partitioned table.
To test this, the experiment actually needs to partition the table. See http://www.kodyaz.com/articles/how-to-partition-table-non-partitioned-table-sql-server-2008.aspx
Querying the partitioning function just tells you what the partitioning function says. It doesn't say where the data is stored. You can set up a partitioning function and run it without actually partitioning a table, as has been demonstrated here already.
In order to partition the table, you also have to create file groups and a partitioning scheme that uses the partitioning function to assign function results to file groups. Then you have to put a clustered key on the table that uses that partitioning scheme.
Set up the partitioning
I'm no expert in command line SQL. I used SSMS interface to set up file groups pfg1 (with a pf1 file) and pfg2 (with a pf2 file). Then I declared the partitioning function and scheme:
CREATE PARTITION FUNCTION IDRange1 (int)
AS RANGE LEFT FOR VALUES (10) ;
GO
CREATE PARTITION SCHEME ps_IDRange1
AS PARTITION IDRange1
TO (pfg1, pfg2)
GO
Create the table and clustered index
CREATE TABLE [IDRanges](
[ID] [int] NOT NULL
)
GO
CREATE CLUSTERED INDEX PK_IDRanges
ON dbo.IDRanges(id) ON ps_IDRange1 (ID)
GO
After you do this, when you query sys.partitions (I have 2005), you see that the table now has two partitions instead of just one for the table. This indicates that we have fully implemented partitioning for this table.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 0
72057597780361216 770674389 1 2 72057597780361216 0
Now that we have two partitions (with a row count for each), we can conduct an experiment.
Insert the rows
INSERT INTO IDRanges ([ID]) VALUES (17)
INSERT INTO IDRanges ([ID]) VALUES (7)
Check the sys.partitions to see what happened.
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 1
72057597780361216 770674389 1 2 72057597780361216 1
Yep. One row in each partition.
Move a row.
UPDATE IDRanges
SET [ID] = 8 WHERE [ID] = 17
Check the partitions
select * from sys.partitions where object_id = object_id('IDRanges')
partition_id object_id index_id partition_number hobt_id rows
-------------------- ----------- ----------- ---------------- -------------------- --------------------
72057597780295680 770674389 1 1 72057597780295680 2
72057597780361216 770674389 1 2 72057597780361216 0
The first partition now has two rows instead of 1, and the second partition has zero rows instead of two.
I think this confirms that the row was automatically moved as a result of modifying the clustered key in a partitioned table.
edited Oct 3 '13 at 16:56
Jon Seigel
15.5k53573
15.5k53573
answered Oct 3 '13 at 15:51
Jason HolladayJason Holladay
9911
9911
1
+1 for the first answer to this question that actually tests the scenario. Welcome to DBA.SE!
– Jon Seigel
Oct 3 '13 at 17:02
-1 Can you please point me to the MSDN documents that support your requirements to 'fully' partition a table? Specifically the necessity for separate file-groups and a clustered index?
– Kenneth
Nov 18 '13 at 22:38
add a comment |
1
+1 for the first answer to this question that actually tests the scenario. Welcome to DBA.SE!
– Jon Seigel
Oct 3 '13 at 17:02
-1 Can you please point me to the MSDN documents that support your requirements to 'fully' partition a table? Specifically the necessity for separate file-groups and a clustered index?
– Kenneth
Nov 18 '13 at 22:38
1
1
+1 for the first answer to this question that actually tests the scenario. Welcome to DBA.SE!
– Jon Seigel
Oct 3 '13 at 17:02
+1 for the first answer to this question that actually tests the scenario. Welcome to DBA.SE!
– Jon Seigel
Oct 3 '13 at 17:02
-1 Can you please point me to the MSDN documents that support your requirements to 'fully' partition a table? Specifically the necessity for separate file-groups and a clustered index?
– Kenneth
Nov 18 '13 at 22:38
-1 Can you please point me to the MSDN documents that support your requirements to 'fully' partition a table? Specifically the necessity for separate file-groups and a clustered index?
– Kenneth
Nov 18 '13 at 22:38
add a comment |
Once created the table partition for (IDRanges) table. Then Shall I update the table(IDRanges) through PartitionNumber? Is it possible. Please revert the script soon.
New contributor
add a comment |
Once created the table partition for (IDRanges) table. Then Shall I update the table(IDRanges) through PartitionNumber? Is it possible. Please revert the script soon.
New contributor
add a comment |
Once created the table partition for (IDRanges) table. Then Shall I update the table(IDRanges) through PartitionNumber? Is it possible. Please revert the script soon.
New contributor
Once created the table partition for (IDRanges) table. Then Shall I update the table(IDRanges) through PartitionNumber? Is it possible. Please revert the script soon.
New contributor
New contributor
answered 6 mins ago
Mohamed IrsathMohamed Irsath
1
1
New contributor
New contributor
add a comment |
add a comment |
I don't think that answer is correct. When you use the value
$PARTITION.IDRange1([ID]) AS Partition
you are simply recalculating what the partition should be, not where the record currently is.
You should use:
select * from sys.partitions where object_id = object_id('IDRanges')
In my tests on sql 2005 the value changes but the record stays in the same partition. This will probably mess with stats and the optimizer as it will run in a multi threaded mode expecting a partition to be in a specific range. It will also be completely wrong when it tries to use partition elimination to only query the relevant partition. I think you need to delete and re-insert each record to get them to move.
2
Searching for$partition
over here suggests that the accepted answer is correct. How are you confirming that the record stays in the same partition after it has been updated?
– Nick Chammas
Oct 26 '11 at 21:38
The first point is true, but the conclusion that the row doesn't move is false -- presumably there's something wrong with the test that was run.
– Jon Seigel
Oct 3 '13 at 17:08
add a comment |
I don't think that answer is correct. When you use the value
$PARTITION.IDRange1([ID]) AS Partition
you are simply recalculating what the partition should be, not where the record currently is.
You should use:
select * from sys.partitions where object_id = object_id('IDRanges')
In my tests on sql 2005 the value changes but the record stays in the same partition. This will probably mess with stats and the optimizer as it will run in a multi threaded mode expecting a partition to be in a specific range. It will also be completely wrong when it tries to use partition elimination to only query the relevant partition. I think you need to delete and re-insert each record to get them to move.
2
Searching for$partition
over here suggests that the accepted answer is correct. How are you confirming that the record stays in the same partition after it has been updated?
– Nick Chammas
Oct 26 '11 at 21:38
The first point is true, but the conclusion that the row doesn't move is false -- presumably there's something wrong with the test that was run.
– Jon Seigel
Oct 3 '13 at 17:08
add a comment |
I don't think that answer is correct. When you use the value
$PARTITION.IDRange1([ID]) AS Partition
you are simply recalculating what the partition should be, not where the record currently is.
You should use:
select * from sys.partitions where object_id = object_id('IDRanges')
In my tests on sql 2005 the value changes but the record stays in the same partition. This will probably mess with stats and the optimizer as it will run in a multi threaded mode expecting a partition to be in a specific range. It will also be completely wrong when it tries to use partition elimination to only query the relevant partition. I think you need to delete and re-insert each record to get them to move.
I don't think that answer is correct. When you use the value
$PARTITION.IDRange1([ID]) AS Partition
you are simply recalculating what the partition should be, not where the record currently is.
You should use:
select * from sys.partitions where object_id = object_id('IDRanges')
In my tests on sql 2005 the value changes but the record stays in the same partition. This will probably mess with stats and the optimizer as it will run in a multi threaded mode expecting a partition to be in a specific range. It will also be completely wrong when it tries to use partition elimination to only query the relevant partition. I think you need to delete and re-insert each record to get them to move.
edited Oct 26 '11 at 21:31
answered Oct 26 '11 at 21:14
Steve LedridgeSteve Ledridge
11
11
2
Searching for$partition
over here suggests that the accepted answer is correct. How are you confirming that the record stays in the same partition after it has been updated?
– Nick Chammas
Oct 26 '11 at 21:38
The first point is true, but the conclusion that the row doesn't move is false -- presumably there's something wrong with the test that was run.
– Jon Seigel
Oct 3 '13 at 17:08
add a comment |
2
Searching for$partition
over here suggests that the accepted answer is correct. How are you confirming that the record stays in the same partition after it has been updated?
– Nick Chammas
Oct 26 '11 at 21:38
The first point is true, but the conclusion that the row doesn't move is false -- presumably there's something wrong with the test that was run.
– Jon Seigel
Oct 3 '13 at 17:08
2
2
Searching for
$partition
over here suggests that the accepted answer is correct. How are you confirming that the record stays in the same partition after it has been updated?– Nick Chammas
Oct 26 '11 at 21:38
Searching for
$partition
over here suggests that the accepted answer is correct. How are you confirming that the record stays in the same partition after it has been updated?– Nick Chammas
Oct 26 '11 at 21:38
The first point is true, but the conclusion that the row doesn't move is false -- presumably there's something wrong with the test that was run.
– Jon Seigel
Oct 3 '13 at 17:08
The first point is true, but the conclusion that the row doesn't move is false -- presumably there's something wrong with the test that was run.
– Jon Seigel
Oct 3 '13 at 17:08
add a comment |
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f4511%2fcan-i-move-rows-between-partitions-by-updating-the-partition-key%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown