8

我有一个 Kimball 风格的 DW(星型模型中的事实和维度 - 没有迟到的事实行或列,除了作为类型 2 缓慢变化维度的一部分过期外,没有列的维度发生变化),每天处理繁重的插入和更新行(新日期)以及每月和每日报告流程。事实表按日期分区,以便于旧数据的滚降。

我理解这WITH(NOLOCK)可能会导致读取未提交的数据,但是,我也不希望创建任何会导致 ETL 进程失败或阻塞的锁。

在所有情况下,当我们从 DW 中读取数据时,我们正在从事实表中读取一个不会更改的日期(事实表按日期分区)和维度表,这些数据表的属性不会因为它们链接到的事实而发生变化.

那么 - 有什么缺点吗?- 可能在执行计划或此类操作中SELECT- 仅在同一张表上并行运行的查询。

4

6 回答 6

5

这可能是您需要的:

`ALTER DATABASE AdventureWorks SET READ_COMMITTED_SNAPSHOT ON;

ALTER DATABASE AdventureWorks SET ALLOW_SNAPSHOT_ISOLATION ON;`

然后继续使用

SET TRANSACTION ISOLATION LEVEL READ COMMITTED

在您的查询中。根据 BOL:

READ COMMITTED 的行为取决于 READ_COMMITTED_SNAPSHOT 数据库选项的设置:

如果 READ_COMMITTED_SNAPSHOT 设置为 OFF(默认值),则数据库引擎使用共享锁来防止其他事务在当前事务正在运行读取操作时修改行。共享锁还阻止语句读取其他事务修改的行,直到其他事务完成。共享锁类型决定何时释放。在处理下一行之前释放行锁。读取下一页时释放页锁,语句完成时释放表锁。

如果 READ_COMMITTED_SNAPSHOT 设置为 ON,则数据库引擎使用行版本控制为每个语句提供数据的事务一致快照,因为它在语句开始时就存在。锁不用于保护数据不被其他事务更新。

希望这有帮助。拉吉

于 2009-06-19T02:58:23.033 回答
2

只要都是无更新数据就没有害处,但如果有很多好处,我会感到惊讶。我会说值得一试。最糟糕的情况是,如果您处于批量插入的中间,您将获得不完整和/或不一致的数据,但您可以决定这是否会使任何有用的东西失效。

于 2009-06-18T20:24:55.497 回答
2

您是否考虑过为您的 DW 创建一个DATABASE SNAPSHOT并运行您的报告?

于 2009-06-19T10:06:09.657 回答
1

是的。您的 SQL 的可读性将大大降低。您将不可避免地错过一些 NOLOCK 提示,因为使用 NOLOCK 策略的 SQL SELECT 命令必须把它放在所有地方。

你可以通过设置隔离级别得到同样的东西

设置事务隔离级别读取未提交

最后你得到了 10% 的性能提升(对不起,我太懒了,也懒得去查这篇文章,但它就在那里)

我会说 10% 的收益不值得降低可读性。

于 2009-06-18T23:11:23.973 回答
1

如果使整个数据库只读是可能的,那么这是一个更好的选择。您将获得未提交的读取性能,而无需修改所有代码。

ALTER DATABASE adventureworks SET read_only
于 2009-06-19T00:03:03.590 回答
0

NOLOCK 执行“脏读”(不雅读 READ UNCOMMITTED 与 NOLOCK 做同样的事情)。如果数据库在您阅读时正在更新,那么您可能会收到不一致的数据。唯一的选择是要么接受锁定并因此阻塞,要么选择此处讨论的 SQL 2005 及更高版本中提供的两个新隔离级别之一。

于 2009-07-16T17:10:09.957 回答