标签: sql-server-2012

从聚集索引中找到每个项目最早日期的最佳方法是什么

我有一个 SQL Server 2012 表,其中包含这样的列:

ID int NOT NULL,
EventDate datetime NOT NULL,
... 32 other columns...
Run Code Online (Sandbox Code Playgroud)

其中该表在大约 10000 个不同的 ID 值范围内有大约 50 亿行。

该表有一个唯一的聚集索引,如下所示:

CREATE UNIQUE CLUSTERED INDEX [MyIndex] ON [dbo].[MyTable] (
    [ID] ASC,
    [EventDate] ASC
)
Run Code Online (Sandbox Code Playgroud)

我需要找到最早的每个 ID 的 EventDate,我可以使用以下查询获得它:

SELECT ID, min(EventDate) FROM [dbo].[MyTable] GROUP BY ID
Run Code Online (Sandbox Code Playgroud)

但是,此查询只需不到 2 分钟即可完成。

由于 NDA 限制,我无法分享我正在查看的问题的细节(查询计划等),但我可以建议我看到的是聚集索引扫描,因此它正在检查表中的所有行。鉴于数据是按 EventDate 序列组织的,我希望检索速度会快得多,但我不太确定如何。任何其他特定于 ID 的范围查询都会在几毫秒内响应,并且该表最近已重建并重新编制索引,因此我认为没有任何统计更新会有所帮助。

任何人都可以建议一种更好的方法来确定避免扫描整个聚集索引的最小 per-ID EventDate 值吗?

我确实有一个包含(10,000)个不同id值的表格。

performance sql-server sql-server-2012 greatest-n-per-group query-performance

5
推荐指数
2
解决办法
509
查看次数

我想知道SQL Server 2012 是否保护msdb.dbo.sp_send_dbmail 参数?

我使用这个系统存储过程 dbo.sp_send_dbmail从我的数据库发送电子邮件,我想知道这个过程是否可以防止 SQL 注入?

如果你有一些参考,这对我来说是有用的。

提前致谢。

sql-server stored-procedures sql-server-2012 database-mail

5
推荐指数
1
解决办法
522
查看次数

需要关于备份策略的建议

我们的客户已同意一天数据丢失的 RPO。所以我将改变备份策略以消除空间限制。

数据库处于完全恢复模式。

现有的备份计划:-

  1. 我们每天对数据库进行一次完整备份。

想改变如下: -

  1. 每周,在周日或周六,我们都会对数据库进行完整备份。
  2. 并计划每天对​​数据库进行一次事务备份或差异备份。

这将避免我的空间限制。

如果我们备份事务日志,那么 RTO 会不会更大,因为我们每天只备份一个事务?

无论如何,我们需要执行事务日志备份以在日志文件中腾出空间。

那么你能建议哪种备份类型会更好,差异或事务日志?

如果我走错了方向,请根据我的 RPO 建议一个备份策略。

谢谢。

sql-server backup t-sql restore sql-server-2012

5
推荐指数
2
解决办法
944
查看次数

间隙和岛屿 - 寻找最近的岛屿

我正在处理以下场景,其中我的时间数据属于island 和 gaps。每隔一段时间,我需要根据事件发生的时间将落入现有间隙内的事件与其最近的岛屿相关联。

为了演示,假设我有以下定义我的时间段的数据:

在此处输入图片说明

这个数据是除了哪个ID之间存在间隙连续的27,对于所述时间段2017-07-26 00:03:00通过2017-07-26 00:07:00

为了确定最近的岛屿,我目前将差距分为两个时期,如下所示:

在此处输入图片说明

如果我有一个属于这个差距的事件,GapWindowStart/End时间将决定我需要将事件与哪个岛相关联。因此,例如,如果我有一个发生在 的事件2017-07-26 00:03:20,我会将该事件与 ID 相关联,2相反,如果我有一个事件发生在 ,2017-07-26 00:05:35我会将该事件与 ID 相关联7

最有效的方法,我已经能够编写我的方法,迄今为止,是组装使用的空白伊茨克奔甘的从SQL Server MVP深海潜水书第3解决方案通过ROW_NUMBER窗口函数,然后每一个分裂的差距CROSS APPLY作用的语句就像一个简单的UNPIVOT操作。

这是我用来组装最近的岛屿集的方法的db<>fiddle计划。

确定最近的岛屿后,我使用事件的事件时间来确定与所述事件相关联的最近岛屿。因为这些岛屿全天都在变化,所以我无法制作静态主表,而是必须在遇到事件时在运行时构建所有内容。

这是一个db<>fiddle 计划,显示应该针对随机事件时间使用什么 NearestIsland 值。

对于通常会落入间隙的给定事件,是否有更好的方法来找出最近的岛屿?例如,是否有更有效的方法来识别间隙或更有效的方法来识别最近的岛屿?我什至以最好的逻辑方式来解决这个问题吗?这个问题没有什么重要的,但我总是试图弄清楚是否有一种“更好”的方法来解决问题,我认为这个问题有助于一些创造力,所以我很想看到其他高性能的选择。

我目前使用的环境是 SQL 2012,但我们很快就会迁移到 SQL 2016 环境,所以我几乎可以接受任何东西。

第二个 db<>fiddle 链接的代码如下:

-- Creation of Test Data
CREATE TABLE #tmp
( …
Run Code Online (Sandbox Code Playgroud)

sql-server sql-server-2012 gaps-and-islands sql-server-2016

5
推荐指数
1
解决办法
818
查看次数

禁用参数嗅探以获得更好的性能 - 好主意?

我在 SQL Server 2012 中有一个优化的查询,它持续运行大约 1-3 秒。

当我在 SSMS 中运行它时,它运行得很快,但是当应用程序执行它时(通过sp_executesql),它真的很慢,对于较大的数据大约需要 13 分钟。

应用程序中进行一些挖掘和阅读之后,在 SSMS 中速度很快?,我得出结论,参数嗅探有问题(有一个参数)。

我禁用了它,OPTION (QUERYTRACEON 4136)它可以快速运行sp_executesql

这是一个好主意(我应该保留禁用参数嗅探的选项)还是我应该调整查询以使其与sp_executesql参数嗅探一起使用?

sql-server sql-server-2012 parameter-sniffing

5
推荐指数
1
解决办法
2483
查看次数

在 1.5TB 表上启用页面压缩

我需要想出最好的方法来在大小为 1500 GB 的表上启用页面压缩,有 363,957,740 行。数据库大小本身为 1.71 TB,并保存存档数据。

如果我理解正确,它需要磁盘空间(可能是相同的数量,只是为了更安全),以便它可以创建启用页面压缩的表副本并释放空间。这是在FULL恢复模型中,因此将被大量记录。

我已与我的容量规划资源进行了交谈,他同意为此维护提供额外的临时所需空间,并在此活动完成后收回空间。说了这么多,你认为最好的方法是:

  1. 进行完整备份
  2. 将备份还原到新的临时驱动器上
  3. 将恢复模式更改为 SIMPLE
  4. 启用页面压缩
  5. 压缩后进行完整备份并恢复原始数据库
  6. 将恢复模型更改为 FULL

此外,而不是启用页面压缩。Step #3 之后,截断最大的表,启用页面压缩,然后执行

SELECT * INTO ReplicaDB.dbo.ReplicaTbl
Run Code Online (Sandbox Code Playgroud)

这是否在现有索引上启用页面压缩?

我没有测试环境来测试上述步骤。或者,如果有更好的方法可用,请告诉我。

目标是最大限度地减少当前增长所需的未来磁盘空间。我们是一家 ERP 软件公司,我们拥有企业版许可。该表仅用于在执行某些检查并且所有数据都驻留在该表中时存档。我有 2 个索引(1 个 CI,1 个非 CI)。没有任何列是VARCHAR (MAX),它们要么是NVARCHARint要么是date类型。

sql-server compression sql-server-2012

5
推荐指数
2
解决办法
2070
查看次数

Tempdb 接近磁盘最大值:可以等待吗?

今天我的tempdb推到了分配的磁盘边缘。目前,所述磁盘仅剩 10 MB。我很确定当天早些时候一位同事运行的一些不好的报告将其推高tempdb到这个大小。

但是,现在我的tempdb大小为 20932 MB,可用空间为 20373 MB。所以看起来我们有足够的空间可以使用。我宁愿等到周末重新启动并将其恢复到更合理的大小。只要不寻常的事情不再发生,我可以让这趟旅程吗?

在此处使用 SQL Server 2012。谢谢。

sql-server sql-server-2012 tempdb

5
推荐指数
1
解决办法
182
查看次数

@SortOrder='cpu' 上的 sp_BlitzCache 结果缓慢

sp_BlitzCache几天来,我一直在使用我的数据库来调查一些问题。这是一个巨大的帮助,但就在今天,它开始表现得有点奇怪,我很好奇是否有人知道发生了什么。

昨天我用@SortOrder“读取”或“CPU”运行了许多检查,它运行良好,并且总是在大约相同的时间内返回结果。

今天,'reads' 返回的时间与昨天大致相同,但 'cpu' 需要 10 倍或更多的时间。它进入“检查功能”,然后在那里坐了很长时间。'xpm' 也和往常一样快。

我正在使用 v5.7(20170901)

我意识到我的 SQL 会话已经打开了 +24 小时,并认为##temp文件可能变得太大了。但是在我重新启动会话并且那些表消失后,cpu 排序顺序仍然很慢。所以不是这样。

关于什么会导致这种情况的任何想法?

performance sql-server sql-server-2012 sp-blitzcache

5
推荐指数
1
解决办法
550
查看次数

即使引号转义,也可以通过 .NET 进行 Microsoft SQL Server SQL 注入

我一直在阅读 SQL 注入,作为对相当大的 Web 服务进行安全审计的一部分。我一直在谷歌搜索并阅读我可以在这里和 SO 上找到的所有帖子,并且对真正应该如何构建动态查询以及 MySQL 和 MSSQL 之间的一些差异有相当深入的了解。我最终看到了今年早些时候由 Microsoft 发布的名为SQL Injection 的页面。在标题为“过滤输入”的部分中,它指出:

通过删除转义字符,过滤输入也可能有助于防止 SQL 注入。但是,由于可能会出现问题的字符数量众多,因此这不是可靠的防御。以下示例搜索字符串定界符。

private string SafeSqlLiteral(string inputSQL)  
{  
  return inputSQL.Replace("'", "''");  
}  
Run Code Online (Sandbox Code Playgroud)

编写安全代码第二版也在第 401-402 页讨论了这一点,但看起来作者实际上并没有尝试 C# 示例(或者他在 2003 年使用的 SQL 版本可能没有正确处理转义字符串)。它指出字符串输入将导致无效查询(实际上,转义只是查询其中带有单引号的值),然后指出它也可能会被使用未加引号的数字字段的值攻击(尽管不能,因为示例中的字段来自类型为 的局部变量int,它不可能包含注入所需的信息)。

我不怀疑这里存在可能的攻击向量,但我无法找到有关如何实现这一点的任何解释。从我的其他研究来看,一种可能的方法可能涉及非 Unicode 字符串中的奇怪字节序列。就我而言,我正在使用 .NET,所以不可能有这样的序列,我认为 ADO.NET、SQL Server 或两者都可以正确处理 Unicode 字符串与单个内部的任何其他类型的字符-引号。(虽然有趣的是示例代码似乎是在 C# 中)。

我也很清楚微软页面上列出的其他 SQL 注入方法,对于这个问题,我并不担心这些。此外,我只关心此处正确键入的字符串文字输入。此代码始终在编写 SQL 查询之前将传入类型解析为其适当的运行时类型,因此引号转义仅适用于数据是文字字符串数据时。所以就我而言,该函数实际上更像是:

private string SafeSqlStringLiteral(string inputString)  
{  
  return "'" + inputString.Replace("'", "''") + "'";  
}  
Run Code Online (Sandbox Code Playgroud)

我最关心的就是文档中的下面这句话:

但是,由于可能会出现问题的字符数量众多,因此这不是可靠的防御。

这只是指奇怪的单字节编码,还是有适用于的 Unicode 字符(我无法以编程方式找到一个)?

我正在审查的代码非常广泛,并且在很多地方都使用了这种类型的转义(并且以一种不容易修复的方式)。我不是直接要求利用漏洞(这对 IIRC …

sql-server sql-injection t-sql sql-server-2012

5
推荐指数
1
解决办法
2013
查看次数

如何在从新版本的备份文件还原之前明确清除数据库

我们是一个数学家团队(即,没有 DBA 经验)。

我们正在从旧服务器盒 (SQL Server 2012) 迁移到新服务器盒 (SQL Server 2017)。对于旧服务器上的每个数据库,我们制作了一个备份副本,将其移植到新服务器,并从备份文件中将其恢复到完整的数据库荣耀。

到现在为止还挺好。

但是,我们的入住日期有所延迟,我们仍在使用旧服务器。随着我们继续在旧服务器上工作,这些数据库中的更改继续累积。因此,这意味着位于新服务器上的复制数据库现在已过时且已过时。(讽刺,不是吗?)

对于那些已更改的数据库,我们知道我们最终必须制作新的备份副本并将其移植到新服务器上。

到了时候,在恢复最新的备份副本之前摆脱新服务器上那些现在已经过时的数据库的最聪明方法是什么?

我们担心如果我们不小心,使用相同的名称,可能会发生一些遮挡或遮蔽。在恢复最新版本之前,我们希望确保新服务器上的过时副本完全消失。

sql-server migration sql-server-2012 sql-server-2017

5
推荐指数
1
解决办法
169
查看次数