目前我遇到查询和性能问题 存储过程。以下是场景:
我们在数据库(SQL Server 2000 SP4
)中有3-4个表
有大量的记录。其中一个表有超过2500万
记录。这些表保持销售记录和数千个
记录每天添加到他们。每当执行存储过程时都需要
15-30分钟即可完成。桌子上有3-4个连接。用户是
经常抱怨它。索引是正确的。提高性能
我们已经实现了分区视图。该解决方案由实施
参考以下article on MSDN
我们按年度和业绩划分了销售记录
已经改进,查询/存储过程现在需要3-5分钟才能运行。改善
表现进一步,我们按月划分销售记录。我们正在维持
4年的数据,现在我们已接近48个销售数据表(After
按月拆分销售数据)。我期待这可以提高性能。但
这没有发生。查询执行速度比前一个慢得多
(年度明智的数据拆分)让我感到惊讶。也看了之后
查询计划我发现它正在对所有48个销售表进行索引扫描
仅扫描相关表格。例如。当查询存储过程时
期间19-NOV-2012
和20-DEC-2012
,它应该只考虑2个表NOV-2012
和DEC-2012
。但它正考虑所有48个表。所以我的问题是:
为什么只考虑所有表而不是考虑
相关表格。例如。在上面的示例NOV-2012
和DEC-2012
为什么年度明智的逻辑(按年分割销售记录)是 表现优于月份逻辑(按月拆分销售记录)
以下是分区视图的代码 例如,其他年份被省略。
SELECT * FROM tbl_Sales_Jan2010
UNION ALL
SELECT * FROM tbl_Sales_Feb2010
UNION ALL
SELECT * FROM tbl_Sales_Mar2010
UNION ALL
SELECT * FROM tbl_Sales_Apr2010
UNION ALL
SELECT * FROM tbl_Sales_May2010
UNION ALL
SELECT * FROM tbl_Sales_Jun2010
UNION ALL
SELECT * FROM tbl_Sales_Jul2010
UNION ALL
SELECT * FROM tbl_Sales_Aug2010
UNION ALL
SELECT * FROM tbl_Sales_Sep2010
UNION ALL
SELECT * FROM tbl_Sales_Oct2010
UNION ALL
SELECT * FROM tbl_Sales_Nov2010
UNION ALL
SELECT * FROM tbl_Sales_Dec2010
以下是表格结构。
CREATE TABLE [dbo].[tbl_Sales_Jan2010](
[SalesID] [numeric](10, 0) NOT NULL,
[StoreNumber] [char](3) NOT NULL,
[SomeColumn1] [varchar](15) NOT NULL,
[Quantity] [int] NOT NULL,
[SalePrice] [numeric](18, 2) NOT NULL,
[SaleDate] [datetime] NOT NULL,
[DeptID] [int] NOT NULL,
[CatCode] [char](3) NOT NULL,
[AuditDate] [datetime] NOT NULL CONSTRAINT [DF_tbl_Sales_Jan2010_EditDate] DEFAULT (getdate()),
[SomeColumn2] [varchar](15) NULL,
[SaleMonthYear] [int] NULL CONSTRAINT [DF__tbl_Sales__SaleY__Jan2010] DEFAULT (12010),
[SaleDateInIntFormat] [int] NULL,
CONSTRAINT [PK_tbl_Sales_Jan2010] PRIMARY KEY CLUSTERED
(
[SalesID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [dbo].[tbl_Sales_Jan2010] WITH CHECK ADD CHECK (([SaleMonthYear] = 12010))
以下是查询
SELECT SUM(C.Quantity) as total
FROM Productdatabase.dbo.tbl_Product A , Productdatabase.dbo.tbl_Product_Category B, XDatabase.dbo.vw_Sales_Test C, tbl_Store D
WHERE A.ProductID = B.ProductID AND B.CategoryID = @CateID
AND C.SomeColumn = A.PRoductCode
AND D.StoreCode = C.StoreNumber
AND D.country = @country
AND D.status = 0
And C.SaleMonthYear between @BeginMonthYear and @EndMonthYear
AND C.SalDate between @FromSaleDate and @ToSaleDate
答案 0 :(得分:3)
任何设置分区的人都没有想到他在做什么。除了不使用分区(这是一个SQL Server函数),最有可能是成本......
SELECT * FROM tbl_Sales_Jan2010
在联盟中添加WHERE条件,然后查询分析器可以排除由于那里的坏where子句而不相关的表。即添加:
(([SaleMonthYear] = 12010
就在那里。
其次,解决您的其他问题。真。重点是:
我们在数据库(SQL Server 2000 SP4)中有3-4个表,这些表有很大的 记录数量。其中一个表有超过2500万 记录。
让我笑。 2500万不小,不小,但“休”是什么?我的意思是,我使用表格每天增加数亿行并保持数据2年。 2500万是中端服务器轻松处理的东西。我建议你有坏硬件(我的意思是坏),或者其他一些事情正在发生。
设计问题如:
[SaleMonthYear]
这应该不存在 - 它应该是SaleYearMonth,所以你可以进行一个范围测试(在201005和201008之间)你现在不能有效地做,并且如果你曾经使用它,你完全bork任何索引排序。
这很荒谬,因为这是一个你在这里完全增加的数字。
Whenever a stored procedure is executed it takes 15-30 minutes to complete
让我在这里说清楚。在可接受的中档硬件上,这样的静音(即适当的服务器,32-64gb内存,十几到24个高速光盘)没有办法这需要15到30分钟。不是你在那里写的代码。
除非你有锁拥塞(糟糕的应用程序设计)或服务器超载其他东西(糟糕的应用程序设计/糟糕的管理)之类的东西。我会用适当的索引来表达这样的查询,以便在分钟之下返回。
无论如何,分区的工作方式是快速消除大量检查 - 在你的情况下也是/大多数是删除优化(你可以只删除表,不需要删除语句使硬索引更新)。但是,你实现它的方式不是MS sasys应该完成的方式,而不是逻辑说它应该完成的方式,并且不会产生任何结果,因为你的分区没有集成到查询中。
如果你查看表和查询,它仍然必须检查每个表。
答案 1 :(得分:1)
来自您引用的同一篇MSDN文章:
分区视图不需要CHECK约束来返回正确的结果。但是,如果尚未定义CHECK约束,则查询优化器必须搜索所有表,而不是仅搜索覆盖分区列上的搜索条件的表。如果没有CHECK约束,视图将像使用UNION ALL的任何其他视图一样运行。查询优化器不能对存储在不同表中的值进行任何假设,也不能跳过搜索参与视图定义的表。
在您的问题中,您指定的查询具有日期范围 - 2012年11月19日至2012年12月20日。我假设这是SaleDate列中包含的值,但您的约束是在SaleMonthYear列上。
您确定定义的约束是否正确?你也可以发帖询问吗?
拉吉