小编RTh*_*mas的帖子

参数嗅探 vs 变量 vs 重新编译 vs 优化未知

所以今天早上我们有一个长时间运行的 proc 导致问题(30 秒 + 运行时间)。我们决定检查参数嗅探是否是罪魁祸首。因此,我们重写了 proc 并将传入的参数设置为变量,以阻止参数嗅探。一种尝试过的/真实的方法。Bam,查询时间得到改善(不到 1 秒)。在查看查询计划时,在原始未使用的索引中发现了改进。

为了验证我们没有得到误报,我们对原始 proc 进行了 dbcc freeproccache 并重新运行以查看改进的结果是否相同。但是,令我们惊讶的是,原来的 proc 仍然运行缓慢。我们再次尝试使用 WITH RECOMPILE,但仍然很慢(我们尝试在对 proc 的调用以及在 proc 内部进行重新编译)。我们甚至重新启动了服务器(显然是开发箱)。

所以,我的问题是……当我们在空计划缓存上得到相同的慢查询时,参数嗅探怎么会受到指责……不应该有任何参数嗅探???

我们是否会受到与计划缓存无关的表统计信息的影响。如果是这样,为什么将传入参数设置为变量会有所帮助??

在进一步的测试中,我们还发现,将在PROC的内部的OPTION(OPTIMIZE未知)DID得到预期的改进计划。

所以,你们中的一些人比我更聪明,你能提供一些关于幕后发生了什么来产生这种结果的线索吗?

另一方面,慢计划也有理由提前中止,GoodEnoughPlanFound而快计划在实际计划中没有提前中止原因。

总之

  • 从传入参数中创建变量(1 秒)
  • 重新编译(30+秒)
  • dbcc freeproccache(30 秒以上)
  • 选项(优化 UKNOWN)(1 秒)

更新:

在此处查看慢速执行计划:https : //www.dropbox.com/s/cmx2lrsea8q8mr6/plan_slow.xml

在此处查看快速执行计划:https : //www.dropbox.com/s/b28x6a01w7dxsed/plan_fast.xml

注意:出于安全原因,表、架构、对象名称已更改。

sql-server-2008 execution-plan cache

41
推荐指数
2
解决办法
2万
查看次数

相互验证两个表的快速方法

我们正在做一个 ETL 过程。当一切都说完后,有一堆表格应该是相同的。验证这些表(在两个不同的服务器上)实际上相同的最快方法是什么?我说的是架构和数据。

我可以在表上做一个散列,就像我可以在单个文件或文件组上一样 - 将一个与另一个进行比较。我们有 Red-Gate 数据比较,但由于有问题的表每个都包含数百万行,我想要一些性能更高的东西。

一种让我感兴趣的方法是对 union 语句的这种创造性使用。但是,如果可能的话,我想进一步探索散列的想法。

发布答案更新

对于任何未来的访客......这是我最终采取的确切方法。它工作得很好,我们在每个数据库的每个表上都这样做。感谢下面的答案为我指明了正确的方向。

CREATE PROCEDURE [dbo].[usp_DatabaseValidation]
    @TableName varchar(50)

AS
BEGIN

    SET NOCOUNT ON;

    -- parameter = if no table name was passed do them all, otherwise just check the one

    -- create a temp table that lists all tables in target database

    CREATE TABLE #ChkSumTargetTables ([fullname] varchar(250), [name] varchar(50), chksum int);
    INSERT INTO #ChkSumTargetTables ([fullname], [name], [chksum])
        SELECT DISTINCT
            '[MyDatabase].[' + S.name + '].['
            + T.name + ']' …
Run Code Online (Sandbox Code Playgroud)

sql-server etl sql-server-2008-r2 except

15
推荐指数
3
解决办法
3万
查看次数

更改数据捕获 - 如何知道谁进行了更改?

跟踪谁进行了 CDC 确定的更改。

沿着我的 datetime hack的路线,尝试了相同的方法,将 suser_sname 添加为 cdc 更改跟踪表上具有默认值的新字段。但是,这似乎返回了 cdc 进程的所有者,而不是在基表上启动更改的用户。我也试过 original_login 但它返回了 sql 服务帐户登录。同样,可能与 cdc 进程相关,而不是与发起更改的用户相关。

在堆栈溢出上发现了一个类似的问题,但除了从前端或通过触发器跟踪更改之外没有其他答案,这似乎违背了使用 cdc 的目的。我不会重新发布,但由于原版是在 stackoverflow 上,我想我会在这里尝试一下,特别是如果 R2 或 2012 引入了更好的方法。

因此,简而言之:我如何知道谁对变更数据捕获进行了更改?

sql-server-2012 change-data-capture

11
推荐指数
2
解决办法
9646
查看次数

什么会导致孤立的##MS_PolicyEventProcessingLogin##?

今天早上我注意到我的 SQL 日志充满了以下消息:

在队列 'msdb.dbo.syspolicy_event_queue' 上运行的激活过程 '[dbo].[sp_syspolicy_events_reader]' 输出以下内容:
'无法作为数据库主体执行,因为主体“##MS_PolicyEventProcessingLogin##”不存在,这种类型的主体不能被冒充,或者您没有权限。

运行以下EXEC sp_change_users_login 'report'显示登录实际上已被孤立。

我能够按照此 MSDN 帖子中的建议运行以下命令来修复它。

EXEC sp_change_users_login 
    'Auto_Fix', '##MS_PolicyEventProcessingLogin##', 
    NULL, 'fakepassword'
Run Code Online (Sandbox Code Playgroud)

但问题仍然存在:究竟是什么原因导致这位校长成为孤儿?谷歌搜索和研究表明其他人也有这个问题,但我还没有找到原因的描述。在错误开始出现的那一刻,我没有注意到任何值得注意的事情。

去年夏天,我们将整个服务器迁移到 SAN 存储模型,在迁移期间我们恢复了所有内容(包括 msdb),但那是几个月前的事情。只是最近的事情才使症状明显,因为它没有出现在几周前的日志中。

sql-server-2008 sql-server logins

9
推荐指数
1
解决办法
9794
查看次数

更改数据捕获和 __$update_mask 二进制文件

我们正在使用 CDC 来捕获对生产表所做的更改。更改的行正在导出到数据仓库 (informatica)。我知道 __$update_mask 列存储了以 varbinary 形式更新的列。我也知道我可以使用各种 CDC 函数从该掩码中找出这些列是什么。

我的问题是这个。任何人都可以为我定义该掩码背后的逻辑,以便我们可以识别仓库中已更改的列吗?由于我们在服务器外部进行处理,因此我们无法轻松访问那些 MSSQL CDC 函数。我宁愿自己在代码中分解面具。SQL 端的 cdc 函数的性能对于此解决方案是有问题的。

简而言之,我想从 __$update_mask 字段中手动识别更改的列。

更新:

作为替代方案,也可以将已更改列的人类可读列表发送到仓库。我们发现这可以以远高于我们原始方法的性能来执行。

以下 CLR 对此问题的回答符合此备选方案,并包括为未来访问者解释掩码的详细信息。然而,对于相同的最终结果,使用 XML PATH 接受的答案是最快的。

sql-server-2008 change-data-capture

9
推荐指数
1
解决办法
6255
查看次数

SQL 磁盘设置建议 - TempDB、日志 DB、数据文件放置问题

我们有一个非常活跃的数据库服务器,上面运行着不拘一格的应用程序集合。其中最繁忙的两个是全天进行文档扫描和工作流处理的 Laserfiche 数据库(平均约 2800 批请求/秒)和路由电子邮件的黑莓服务器应用程序。还有大约 25 个其他的小型应用程序数据库。

我们是政府机构,所以我们只获得了单个数据库服务器许可证的预算。

最近,我们获得了一个 SAN 来解决磁盘争用问题。

因此,目前我们在其自己的磁盘(raid 1 镜像对)上运行 TempDB,并且我们已将事务日志和数据文件移至 SAN。事务日志放在一个逻辑位置,数据文件放在另一个位置。从物理上讲,它是同一个阵列,但它是一个由 14 个轴(磁盘)组成的阵列,采用 RAID 1+0 配置。

一个非常强大的 SAN - 事情运行得更好。队列长度减半。

就在今天,我们还获得了另一种选择。如果我们当前在文件服务器上需要它,我们也可以有一个 4 磁盘阵列。我知道通常建议在两个单独的阵列上使用 MDF 和 LDF,但在我们的情况下,唯一的方法是将数据或事务日志从 SAN 移到配置为 Raid 5 的 4 磁盘阵列上。请记住它们是当前位于不同的逻辑卷中,但共享相同的物理阵列。

从臀部拍摄我觉得将 MDF 和 LDF 放在 14 轴 raid 1+0 阵列上可能与将它们与 4 轴 raid 5 阵列上的一个分开一样好。但是,我不会在这里问我是否是磁盘逻辑专家。两个选项都使用基本相同的 15k SAS 磁盘 - 即每个主轴基本上是相同的。

所以,本质上问题是。通过将数据或日志移动到它自己的 4 轴 raid 5 阵列,在配置为 RAID 1+0 的单个 14 轴阵列上的 MDF/LDF 是否会得到任何显着的改善(或根本没有)?

想法?

更新信息:

我还将注意到,当前日志卷上的平均队列长度始终保持在 0.55 左右。Data volume 上的平均队列长度很少超过 0.01(通常为 0.00) …

sql-server-2008 disk-structures san

8
推荐指数
1
解决办法
2401
查看次数

捕获 SQL Server CDC 中更改的日期时间

因此,我们已经开始探索在我们的生产数据库之一上使用变更数据捕获。我们想知道每次更改的日期时间。阅读演练和教程等,似乎标准方法是使用 LSN 与cdc.lsn_time_mapping系统表相关联。这种方法有效,但在谈论每天成千上万的变化时不是很直接也不是很有效。

在测试环境中,我对变更跟踪表进行了以下调整。我发布了一个ALTER TABLE声明,在名为的末尾添加一列并将其设为[__ChangeDateTime]默认值GetDate()。该方法似乎有效,更改跟踪仍然正常运行,正在捕获日期时间。 但是乱搞系统表让我有点紧张。

如果这不是微软从一开始添加系统字段,他们一定有他们的理由。既然他们选择了 LSN 到 cdc.lsn_time_mapping 方法,我是否通过这种方式创建自己的 hack 来解决问题?

更新:

在测试期间发现 GetDate() 有时不足以满足我们的需求 - 多个更改同时共享。建议使用sysdatetime() 和 datetime2将值移出到纳秒。显然只有 2008+ 的选项。

sql-server-2008 change-data-capture system-tables

8
推荐指数
1
解决办法
7952
查看次数

通过 VPN 使用集成安全性

我们有一个客户端,我们将允许它使用我们的一个应用程序。现场工作人员定期通过 VPN 连接到我们的网络。连接到 SQL Server 的 .Net 应用程序使用集成安全性。他们使用的笔记本电脑是我们域的成员。

客户也请求使用该应用程序。所以我们给了他们一个网络帐户和在我们的网络上创建 VPN 会话的能力。我让该帐户在 SQL 服务器上登录,其权限与我们自己的员工相同。

问题是,当他们尝试使用该应用程序时,会收到以下错误: 登录来自不受信任的域,无法与 Windows 身份验证一起使用。

我猜因为他们使用的计算机不在我们的域中,所以他们使用 VPN 登录并不重要。那么,解决这个问题的最佳方法是什么?我宁愿不为这个小应用程序切换到 SQL 身份验证。

sql-server-2008 security

6
推荐指数
1
解决办法
1658
查看次数

SQL Server 审计规范 - 按除一名用户之外的所有用户过滤 DML

我正在设置数据库审计。我想捕获除与应用程序相关的服务帐户之外的数据库用户发出的任何 DML 更改。

简而言之,这是为了向我们的外部审计员证明没有用户在应用程序之外篡改数据。

以下脚本设置了对所有原则通用的 DML 审计。

CREATE DATABASE AUDIT SPECIFICATION [OurDatabaseAuditSpec]
FOR SERVER AUDIT [OurAudit]
ADD (DELETE ON OBJECT::[dbo].[SensitiveData] BY [public]),
ADD (INSERT ON OBJECT::[dbo].[SensitiveData] BY [public]),
ADD (UPDATE ON OBJECT::[dbo].[SensitiveData] BY [public])
WITH (STATE = ON)
GO
Run Code Online (Sandbox Code Playgroud)

我如何修改此审计规范以捕获除应用程序服务帐户正在执行的操作之外的所有内容?

我仅限于单独指定每个原则还是可以指定一个例外?通过 BOL 阅读似乎我只能列出要审核的原则 - 而不是要忽略的原则。

sql-server audit sql-server-2012

6
推荐指数
1
解决办法
7818
查看次数

TSQL DateTime DataType - 小数秒与毫秒

想要从一天中获取所有记录。所以2013-03-05 00:00:00.000和之间的一切2013-03-05 23:59:59.999。我们在后端与发生在2013-03-06 00:00:00.000.

因此,在测试中,我在 SSMS 中运行:

select cast('2013-03-05 23:59:59.999' as datetime)
select cast('2013-03-05 23:59:59.996' as datetime)
select cast('2013-03-05 23:59:59.994' as datetime)
Run Code Online (Sandbox Code Playgroud)

并得到:

2013-03-06 00:00:00.000
2013-03-05 23:59:59.997
2013-03-05 23:59:59.993
Run Code Online (Sandbox Code Playgroud)

毫秒部分会稍微回落。在第一行的情况下,它真的很重要。因为我不想要 2013-03-06 00:00:00.000 - 我想要午夜前一毫秒。

TSQL 在文档中声明它使用小数秒,而不是使用毫秒的 .Net 日期时间。这似乎只是语法上的差异,但如果您真的关心 TSQL 中的毫秒精度,您是否会被迫全面使用DateTime2。从datetime2to 转换datetime仍然会在几毫秒内把事情搞砸。

在 c# 中DateTime.Parse("03/5/2013 23:59:59.999").Millisecond仍然返回 999。

我这样解释好吗?如果我关心毫秒精度,我datetime2只坚持使用。

通常,这将是一个简单的修复,但在这种情况下,我们使用的是datetime作为参数接收的 Microsoft 系统函数。

sql-server-2008 sql-server datetime

2
推荐指数
1
解决办法
1852
查看次数