我有一个非常大的表(超过1000万行),它开始显示查询性能下降的迹象。由于这个表的大小可能会相对很快增加一倍或三倍,所以我正在考虑对表进行分区以挤出一些查询性能。
表格如下所示:
CREATE TABLE [my_data] (
[id] [int] IDENTITY(1,1) NOT NULL,
[topic_id] [int] NULL,
[data_value] [decimal](19, 5) NULL
)
所以,任何给定主题的一堆值。此表上的查询将始终按主题ID,因此在(id,topic_id)上有聚簇索引。
无论如何,由于主题ID没有限制(可以添加任意数量的主题),我想尝试在主题ID的模数函数上对此表进行分区。如下所示:
topic_id % 4 == 0 => partition 0
topic_id % 4 == 1 => partition 1
topic_id % 4 == 2 => partition 2
topic_id % 4 == 3 => partition 3
但是,在决定分区时,我还没有看到任何告诉“创建分区函数”或“创建分区方案”来执行此操作的方法。
这甚至可能吗?我们如何根据对输入值执行的操作来创建分区函数?
答案 0 :(得分:5)
您只需要将模数列创建为PERSISTED计算列。
Blue Peter风格,这是我之前制作的风格(虽然我不是100%确定我有分区值子句):
CREATE PARTITION FUNCTION [PF_PartitonFour] (int)
AS RANGE RIGHT
FOR VALUES (
0,
1,
2)
GO
CREATE PARTITION SCHEME [PS_PartitionFourScheme]
AS PARTITION [PF_PartitonFour]
TO ([TestPartitionGroup1],
[TestPartitionGroup2],
[TestPartitionGroup3],
[TestPartitionGroup4])
GO
CREATE TABLE [my_data] (
[id] [int] IDENTITY(1,1) NOT NULL,
[topic_id] [int] NULL,
[data_value] [decimal](19, 5) NULL
[PartitionElement] AS [topic_id] % 4 PERSISTED,
) ON [PS_PartitionFourScheme] (PartitionElement);
GO
答案 1 :(得分:3)
SQL Server 2005/2008中不提供散列分区。您必须使用范围分区。
话虽如此,您应该知道分区主要是一个存储选项,请参阅Partitioned Table and Index Concepts:
分区使大表或 索引更多可管理,因为 通过分区,您可以管理和 快速访问数据子集 有效地,同时保持 数据收集的完整性。通过 使用分区,这样的操作 从OLTP到加载数据 OLAP系统只需几秒钟, 而不是分钟和小时 操作需要早期版本的 SQL Server。 维护操作 在数据子集上执行 也更有效地执行 因为这些操作仅针对目标 所需的数据,而不是 整个表格。
如您所见,MSDN中的分区介绍侧重于维护,可管理性和数据加载。根据我的经验,分区最多只能提供0性能提升。特别是在SQL 2005中。通常它会降低性能。要提高性能,您应该使用正确的聚簇索引和正确设计的非聚集索引。
在SQL 2008中,如果从IO的角度对分区进行了适当的分发,并行运算符在分区方面有所改进,请参阅Designing Partitions to Improve Query Performance。虽然它们的好处是微不足道的,并且被适当设计的集群和非集群索引集的好处所掩盖。例如,(id,topic_id)中的聚簇索引,其中id是一个标识,仅用于通过id查找单个项目。另一方面,聚集索引(topic_id,id)将有益于查找特定主题的任何查询。我不知道你的系统要求和你运行的查询,但这样一个狭窄的表上的10M行性能问题就像索引和查询问题一样,没有分区问题。
答案 2 :(得分:0)
从文档中,您似乎必须为函数赋值:
创建4个分区......
CREATE PARTITION FUNCTION myRangePF1 (int)
AS RANGE LEFT FOR VALUES (1, 100, 1000);
难道你不能在这次调用之上进行计算并找到要拆分的正确值吗?将值替换为呼叫?或者我错过了你为什么要使用模数?根据您的ID存在差距的可能性,您可能需要使用一些统计数学来找出分区的位置。
CREATE PARTITION FUNCTION myRangePF1 (int)
AS RANGE LEFT FOR VALUES (@low, @Med, @High);
答案 3 :(得分:0)
1000万行对于SQL服务器来说并不是那么多;常规索引设计可能无需分区即可解决此问题。如前所述,尝试在不同的列集上进行聚类;在topicid上进行聚类,id似乎是要测试的东西,特别是如果大多数查询都将topicid作为标准。像这样的聚簇索引具有与分区大致相同的效果,至少在于它将相关的数据行组合在磁盘上并允许范围扫描快速获取它们。
如果该设计有效,那么您只需要担心插入碎片,但这是可管理的。获得正确的索引后,请确保您有足够的RAM,并且没有磁盘瓶颈。