5

我关注了这篇文章: http ://www.mssqltips.com/sqlservertip/1796/creating-a-table-with-horizo ​​ntal-partitioning-in-sql-server/ 本质上执行以下操作:

  1. 创建一个包含三个文件组的数据库,分别称为 A、B 和 C
  2. 创建一个分区方案,映射到三个文件组
  3. 使用分区方案创建表 - SalesArchival
  4. 在表中插入几行,在文件组中拆分。

我想执行这样的查询(请原谅我的伪代码)

select * from SalesArchival
where data in filegroup('A')

有没有办法做到这一点,或者如果没有,我该怎么做。

我想要完成的是每天运行一个批处理,将超过 90 天的数据移动到不同的文件组,并且只对“当前”文件组执行我的前端查询。

4

3 回答 3

2

要获取特定的文件组,您总是希望在谓词中利用分区消除来确保读取最少的记录。如果您要从分区中获得任何好处,这一点非常重要。

对于存档,我认为您正在寻找如何拆分和合并范围。您应该始终保持第一个和最后一个分区为空,但这应该让您了解如何使用分区进行归档。仅供参考,将数据从一个文件组移动到另一个文件组非常耗费资源。此外,如果您使用范围正确的 pf,结果会略有不同。由于您正在进行分区,因此希望您已经阅读了最佳实践。

不要在生产中运行。这只是一个可供学习的例子。

此示例假设您定义了 4 个文件组(FG1、FG2、FG3 和 [PRIMARY])。

IF EXISTS(SELECT NULL FROM sys.tables WHERE name = 'PartitionTest')
    DROP TABLE PartitionTest;
IF EXISTS(SELECT NULL FROM sys.partition_schemes WHERE name = 'PS')
    DROP PARTITION SCHEME PS;
IF EXISTS(SELECT NULL FROM sys.partition_functions WHERE name = 'PF')
    DROP PARTITION FUNCTION PF;
CREATE PARTITION FUNCTION PF (datetime) AS RANGE LEFT FOR VALUES ('2012-02-05', '2012-05-10','2013-01-01');
CREATE PARTITION SCHEME PS AS PARTITION PF TO (FG1,FG2,FG3,[PRIMARY]);
CREATE TABLE PartitionTest( Id int identity(1,1), DT datetime) ON PS(DT);

INSERT PartitionTest (DT) SELECT '2012-02-05' --FG1 UNION ALL SELECT '2012-02-06' --FG2(This is the one 90 days old to archive into FG1) UNION ALL SELECT '2012-02-07' --FG2 UNION ALL SELECT '2012-05-05' --FG2 (This represents a record entered recently)

检查与每条记录关联的文件组:
SELECT O.name TableName, fg.name FileGroup, ps.name PartitionScheme,pf.name PartitionFunction, ISNULL(prv.value,'Undefined') RangeValue,p.rows
FROM sys.objects O
INNER JOIN sys.partitions p on P.object_id = O.object_id
INNER JOIN sys.indexes i on p.object_id = i.object_id and p.index_id = i.index_id
INNER JOIN sys.data_spaces ds on i.data_space_id = ds.data_space_id
INNER JOIN sys.partition_schemes ps on ds.data_space_id = ps.data_space_id
INNER JOIN sys.partition_functions pf on ps.function_id = pf.function_id
LEFT OUTER JOIN sys.partition_range_values prv on prv.function_id = ps.function_id and p.partition_number = prv.boundary_id
INNER JOIN sys.allocation_units au on p.hobt_id = au.container_id
INNER JOIN sys.filegroups fg ON au.data_space_id = fg.data_space_id
WHERE o.name = 'PartitionTest' AND i.type IN (0,1) --Remove nonclustereds. 0 for heap, 1 for BTree
ORDER BY O.name, fg.name, prv.value
这证明 2012-02-05 在 FG1 中,而其余的在 FG2 中。

为了存档,您的第一反应是移动数据。但是,在分区时,您实际上必须滑动分区函数范围值。

现在让我们将 2012-02-06(在您的情况下为 90 天或更早)移动到 FG1:

--Move 2012-02-06 from FG2 to FG1
ALTER PARTITION SCHEME PS NEXT USED FG1;
ALTER PARTITION FUNCTION PF() SPLIT RANGE ('2012-02-06');
重新运行文件组查询以验证 2012-02-06 是否已移至 FG1。

于 2012-05-06T06:05:15.363 回答
1

$PARTITION (Transact-SQL)应该有你想做的事情。

运行以下命令以了解分区的大小和 ID:

USE AdventureWorks2012;
GO
SELECT $PARTITION.TransactionRangePF1(TransactionDate) AS Partition, 
COUNT(*) AS [COUNT] FROM Production.TransactionHistory 
GROUP BY $PARTITION.TransactionRangePF1(TransactionDate)
ORDER BY Partition ;
GO

以下内容应为您提供给定分区 id 的数据:

SELECT * FROM Production.TransactionHistory
WHERE $PARTITION.TransactionRangePF1(TransactionDate) = 5 ;
于 2015-05-26T22:41:58.597 回答
0

不可以。您需要使用在分区函数中使用的确切条件。这可能是

where keyCol between 3 and 7
于 2012-05-04T20:33:59.817 回答