我在生产中有一个用于存储workflow
给定项目的数据库表;表中的每条记录基本上代表特定日期的项目状态。
过度简化的表结构是这样的:
工作流表
|-------------|------------|---------|----------------|
| Category | ItemCode | Status | InsertDate |
|-------------|------------|---------|----------------|
| Cat1 | Foo1 | 01 | 2012-01-01 |
|-------------|------------|---------|----------------|
| Cat1 | Foo1 | 02 | 2012-03-02 |
|-------------|------------|---------|----------------|
| Cat1 | Foo1 | 03 | 2012-04-01 |
|-------------|------------|---------|----------------|
| Cat1 | Foo2 | 01 | 2012-04-06 |
|-------------|------------|---------|----------------|
| Cat1 | Foo2 | 02 | 2012-05-07 |
|-------------|------------|---------|----------------|
| Cat1 | Foo2 | 04 | 2012-05-09 |
|-------------|------------|---------|----------------|
| Cat2 | Foo3 | 01 | 2011-02-03 |
|-------------|------------|---------|----------------|
| ... | ... | .. |.... |
|-------------|------------|---------|----------------|
因此,在2012-01-01,项目Foo1已达到状态01;在2012-04-01已达到状态03等等。
StoredProcedurePR_GetCategoryItemsInformation
将给定的值Category
作为输入,读取 Workflow 表并给出如下结果:
@输入:Cat1
输出:
|------------------|---------------|------------------|---------------------|
| Category | ItemCode | DateOfFirstRecord| StatusOfLatestRecord|
|------------------|---------------|------------------|---------------------|
| Cat1 | Foo1 | 2012-01-01 | 03 |
| Cat1 | Foo2 | 2012-04-06 | 04 |
SP,给定一个Category
,对于每个ItemCode
需要获取工作流的第一行来读取的InsertDate
和工作流的最后一行来获取当前的Status
。
它归结为如下所示的 SP 实现:
CREATE PROCEDURE dbo.PR_GetFooItemInformation
@Category CHAR(3)
AS
BEGIN
CREATE TABLE #TabTemp (
Category CHAR(3),
ItemCode CHAR(3),
Status CHAR(2),
InsertDate DATETIME
)
CREATE CLUSTERED INDEX XIE1TabTemp
ON #TabTemp (...)
CREATE NONCLUSTERED INDEX XIE2TabTemp
ON #TabTemp (...)
INSERT INTO #TabTemp
SELECT
Category,
ItemCode,
Status,
InsertDate
FROM Workflow
WHERE (Some rules to cut down the number of rows)
SELECT
T1.Category,
Item.ItemCode,
T1.InsertDate,
T2.Status
FROM
Item
INNER JOIN
#TabTemp as T1 ON Item.ItemCode = Workflow.ItemCode
INNER JOIN
#TabTemp as T2 ON Item.ItemCode = Workflow.ItemCode
WHERE
...
AND
T1.InsertDate= SELECT
MIN(InsertDate)
FROM
#TabTemp as T3
WHERE ..
AND
T2.InsertDate = SELECT
MAX(InsertDate)
FROM
#TabTemp as T4
WHERE ..
SP 已经按预期工作了很多年(2005 年),但是几个月前它开始给出一些随机超时;由于workflow
表的记录数在增长(2.5M 并且还在增加),它的性能肯定会越来越差*。
这些表已正确编入索引,而且就其价值而言,sql management studio 不建议在 SP 上建立任何进一步的索引。
不使用临时表的同一个 SP 速度要慢 4 倍。
此时的临时表在每次调用时平均填充 150 万行。
就我有限的 dba 知识而言,这个问题与MIN
需要MAX
计算以到达给定类别的每个项目的第一行和最后一行的函数有关。
我省略了有关工作流表和 SP 实现的一些细节,但我希望我所描述的内容足以让您了解问题所在。
最后一个问题:
您知道处理这种情况的任何 sql 策略甚至 sql-server 专有解决方案吗?
我有什么样的限制?
好吧,SP 用于 BackOffice 函数,应该返回所有实时记录,而不是预处理的子集。
* 我不是 dba;其中一位 dba 目前正在他黑暗的实验室里研究这个小怪物。