SQL从表中选择 - 仅包括特定文件组中的数据

时间:2012-05-04 20:17:03

标签: sql sql-server sql-server-2008 tsql database-partitioning

我遵循了这篇文章: http://www.mssqltips.com/sqlservertip/1796/creating-a-table-with-horizontal-partitioning-in-sql-server/ 其实质上是以下内容:

  1. 创建一个包含三个文件组的数据库,称之为A,B和C
  2. 创建分区方案,映射到三个文件组
  3. 使用分区方案
  4. 创建表 - SalesArchival
  5. 在表格中插入几行,拆分文件组。
  6. 我想执行这样的查询(请原谅我的伪代码)

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

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

    我想要实现的是每天批量运行将超过90天的数据移动到不同的文件组,并仅在“当前”文件组上执行前端查询。

3 个答案:

答案 0 :(得分:2)

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

对于存档,我认为您正在寻找如何拆分和合并范围。您应始终将第一个和最后一个分区保留为空,但这应该可以让您了解如何使用分区进行归档。仅供参考,将数据从1个文件组移动到另一个文件组是非常耗费资源的。此外,如果您使用范围正确的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。

答案 1 :(得分: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 ;

答案 2 :(得分:0)

没有。您需要使用在分区函数中使用的确切条件。这可能就像

where keyCol between 3 and 7