English 中文(简体)
T-SQL中建立和查询版本记录的最佳做法
原标题:Best practice for setup and querying versioned records in T-SQL
  • 时间:2012-05-24 19:41:50
  •  标签:
  • sql
  • t-sql

我试图优化我 SQL 查询, 我总是回来 回到这个问题, 我希望得到一些洞察力 如何我可以 最佳优化这一点。

简洁的说,我有一个简单的雇员表:

< 强> tbl_ 雇员 < / 强 >

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

这在另一个表格中为每个雇员提供了以下信息:

< strength> tbl_ enderen- version 用户名: <% 1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

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. 显然,Cross Apper增加了一些性能损失。 处理这种版本信息是否有最佳做法? 是否有更好的方法获得最高版本的记录?

  2. 版本的表格没有集成索引, 无论是Id还是版本, 都不是独一无二的。 将组合成一组, 但不会这样工作 。 相反, ID 和 版本有非集成索引 。 是否有更好的方法将这个表格索引化, 以获得任何绩效收益? 索引化的视图是否真的有用?

最佳回答

我认为构建数据的最佳方式是使用起始日期和结束日期。 因此,您原始表格的数据结构将看起来是:

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 coalesce(EndDate, getdate()) >= getdate()

或者,在此情况下, 您可以默认 EndDate 在未来某个遥远的日期, 远如 01- o1- 9999 。 您可以在创建表格语句中添加此默认值, 使列不是空的, 然后您可以总是使用该语句 :

where getdate() between EffDate and EndDate

正如Martin在其评论中指出的,联合()可能会妨碍使用指数(在SQL服务器中确实如此),但这并不有问题。

这被称为一个缓慢变化的层面。 Ralph Kimball在他的关于数据仓的书籍中用一段长的篇幅讨论了这一概念。

问题回答

以下是您对每位员工最新版本的浏览方式:

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

我怀疑这将比先前的解决方案效果更好。 跨 Id 和 版本的 tbl_ employenes_ version 中有一个索引也很有可能有用 。

另外,请注意,只要您重新选择不包含 tbl_ employenes_ version 的字段,您只需加入 tbl_ employenes 。





相关问题
SQL SubQuery getting particular column

I noticed that there were some threads with similar questions, and I did look through them but did not really get a convincing answer. Here s my question: The subquery below returns a Table with 3 ...

难以执行 REGEXP_SUBSTR

I m 查询Oracle 10g。 我有两张表格(样本数据见下文)。 i m 试图提取一些领域

SQL Query Shortcuts

What are some cool SQL shorthands that you know of? For example, something I learned today is you can specify to group by an index: SELECT col1, col2 FROM table GROUP BY 2 This will group by col2

PHP array callback functions for cleaning output

I have an array of output from a database. I am wondering what the cleanest way to filter the values is example array Array ( [0] => Array ( [title] => title 1 ...

OracleParameter and DBNull.Value

we have a table in an Oracle Database which contains a column with the type Char(3 Byte). Now we use a parameterized sql to select some rows with a DBNull.Value and it doesn t work: OracleCommand ...

Running numbers in SQL

I have a SQL-statement like this: SELECT name FROM users WHERE deleted = 0; How can i create a result set with a running number in the first row? So the result would look like this: 1 Name_1 2 ...

How to get SQL queries for each user where env is production

I’m developing an application dedicated to generate statistical reports, I would like that user after saving their stat report they save sql queries too. To do that I wrote the following module: ...

热门标签