为建立最佳实践,并在T-SQL查询版本记录(Best practice for setup and

2019-10-16 18:28发布

我试图优化我的SQL查询和我总是回到这个问题,我希望能得到一些见解,我怎么能最优化此。

为了简便起见,可以说我有一个简单的员工表:

tbl_employees

Id     HiredDateTime
------------------
1      ...        
2      ...      

已版本信息在另一个另一个表为每个员工:

tbl_emplyees_versioned

Id     Version   Name     HourlyWage
-------------------------------
1      1         Bob      10
1      2         Bob      20
1      3         Bob      30
2      1         Dan      10
2      2         Dan      20

这是最新版本的记录是如何在一个视图中检索:

Select tbl_employees.Id, employees_LatestVersion.Name, employees_LatestVersion.HourlyWage, employees_LatestVersion.Version
From tbl_employees
Inner Join tbl_employees_versioned
 ON tbl_employees.Id = tbl_employees_versioned.Id
CROSS APPLY 
   (SELECT Id, Max(Version) AS Version
    FROM tbl_employees_versioned AS employees_LatestVersion
    WHERE Id = tbl_employees_versioned.Id
    GROUP BY Id) AS employees_LatestVersion

为了得到这样的回应:

Id     Version   Name     HourlyWage
-------------------------------
1      3         Bob      30
2      2         Dan      20

当拉有超过500名员工记录,每个有一对夫妇几个版本的查询,此查询开始哽咽起来,需要几秒钟才能运行。

有一对夫妇的罢工马上蝙蝠,但我不知道如何克服它们。

  1. 显然,跨应用增加了一些性能损失。 有没有像这样的版本化信息处理时,最好的做法? 有没有更好的方式来获得只是一个最高版本记录?

  2. 该版本表没有一个聚集索引beause没有标识或版本是唯一的。 连接到一起,他们会是这样,但它不喜欢的工作。 取而代之的是ID的非聚集索引,另一个用于版本。 有没有指标更好的方法此表来获得任何性能提升? 将索引视图真正帮助吗?

Answer 1:

我认为结构中的数据的最佳方法是使用的开始日期和结束日期。 因此,对于您的原始表中的数据结构将如下所示:

create table tbl_EmployeesHistory (
    EmployeeHistoryId int,
    EffDate date not null,
    EndDate date,
    -- Fields that describe the employee during this time
)

然后,您可以使用一个视图中看到的当前版本:

create view vw_Employees as
    select *
    from tbl_EmployeesHistory
    where EndDate is NULL

在某些情况下,未来的结束日期是允许的,where子句是:

where coalesce(EndDate, getdate()) >= getdate()

另外,在这种情况下,您可以默认结束日期到将来的某一天很远很远,如'01 -o1-9999' 。 你想补充一点作为create table语句的默认情况下,使列不为空,然后你可以随时使用语句:

where getdate() between EffDate and EndDate

正如马丁在他的评论中指出,聚结()可能会妨碍使用索引(它在SQL Server)的,而这并不存在这样的问题。

这就是所谓的渐变维度。 拉尔夫·金博尔论述了他对数据仓库的书籍有些长了这一概念。



Answer 2:

这里是你可以得到的最新版本为每个员工一个观点的一种方式:

Select Id, Name, HourlyWage, Version
FROM (
  Select E.Id, V.Name, V.HourlyWage, V.Version,
   row_number() OVER (PARTITION BY V.ID ORDER BY V.Version DESC) as nRow
  From tbl_employees E
  Inner Join tbl_employees_versioned V ON E.Id = V.Id
) A
WHERE A.nRow = 1

我怀疑这将执行比以前的更好的解决方案。 在tbl_employees_versioned跨Id和版本的一个指数很可能也有帮助。

另外请注意,您只需要加入对tbl_employees,如果你选择在tbl_employees_versioned不属于域。



文章来源: Best practice for setup and querying versioned records in T-SQL
标签: sql tsql