我有一个存储过程,它使用 Id 列表填充临时表 #employee_benefits。该表最终大约有 10,000 行长。下面的查询然后从一个名为 EmployeeBenefitData 的表中进行选择,该表有大约 400 万行。
SELECT ebd.EmployeeBenefitDataId, ebd.EmployeeBenefitId, ebd.[DataDefinitionId]
FROM #employee_benefits eb
INNER JOIN EmployeeBenefitData ebd ON eb.EmployeeBenefitId = ebd.EmployeeBenefitId
Run Code Online (Sandbox Code Playgroud)
瓶颈是 EmployeeBenefitData 表上的索引扫描。它首先进行索引扫描,然后将其加入临时表。临时表充当过滤器,这意味着在连接之前扫描所有数据的效率非常低。我添加了以下代码以将扫描更改为搜索并显着减少所需的读取量。
DECLARE @MinEmpBenId INT, @MaxEmpBenId INT
SELECT @MinEmpBenId = MIN(EmployeeBenefitId), @MaxEmpBenId = MAX(EmployeeBenefitId)
FROM #employee_benefits
SELECT ebd.EmployeeBenefitDataId, ebd.EmployeeBenefitId, ebd.[DataDefinitionId],
dd.TypeId, dd.DataDefinitionId, dd.Name, ebd.[Value], ebd.[Date], ebd.[Text]
FROM #employee_benefits eb
INNER JOIN EmployeeBenefitData ebd ON eb.EmployeeBenefitId = ebd.EmployeeBenefitId
INNER JOIN DataDefinition dd ON ebd.DataDefinitionId = dd.DataDefinitionId
WHERE ebd.EmployeeBenefitId >= @MinEmpBenId AND ebd.EmployeeBenefitId <= @MaxEmpBenId
Run Code Online (Sandbox Code Playgroud)
它对客户端统计数据产生了巨大的影响 …
基于该 msdn 页面: 服务器内存设置,最好保留 SQL-Servers min 和 max memory 的默认值以使其保持动态...
根据我通过教程学到的知识,您应该始终定义一个最大值,关于最小值,我没有听说过太多。我正在使用简单的旧 perfmon 监视我的页面文件,我意识到很少发生磁盘交换,一旦它几乎导致服务器崩溃。
这可能与 SQL Server 中的默认最大内存设置有关吗?数据库大约为 150 GB,内存为 48 GB,该机器上没有其他应用程序在运行。
另外,为什么你应该有一个最小值?我知道太低的值会阻止 SQL-Server 启动,我知道 SQL-Server 将内容保存在内存中,因此不会尝试释放它的缓存。
我正在使用 SQL-Server 2012,在此先感谢您!
我有一个处于FULL恢复模式的主数据库,它是Always On组的一部分。有没有办法在FULL恢复模式下最小化记录插入操作?
我有一个每天执行的进程,并在表中插入几百万条记录。随着操作的继续,事务日志文件的大小急剧增加(从 1 GB 到 40 GB)。
正如我所读到的,我可以使用一些未完INSERT全记录操作的变体,但我担心切换恢复模型的效果?
t-sql sql-server-2012 transaction-log availability-groups bulk-insert
我们刚刚从 SQL Server 2008 R2 切换到 SQL Server 2012。我遇到了标识列的问题:
每当我重新启动 SQL Server 时,每个标识列的种子值都会增加 1000(对于int标识列是 1000,对于bigint它是 10,000)。例如,如果表的下一个int标识值是 3,那么在重新启动 SQL Server 后它将是 1003。如果我再次重新启动 SQL Server,它将是 2003,以此类推。
在谷歌搜索后,我发现它是 SQL Server 2012 中的一个新功能(不知道它的用途),如果您想要旧的身份行为,只有两种解决方案:
使用序列对象
这对我来说是不可能的,因为:
a) 我在 SQL Server 2008 和 2012 中使用相同的数据库。我不能在 2008 中使用序列。
b) 如果我使用序列,那么我需要更改每个表的保存过程,这对我们来说将是一项繁重的任务。
使用跟踪标志 272 (-T272)
我可以使用此解决方案,因为无需对我的应用程序进行任何更改。有人建议添加-T272作为启动参数,之后此 SQL Server 标识将像在以前的版本中一样工作。我做了同样的事情,但它不起作用。
我不想对我的数据库结构进行任何更改。请提出解决方案或解释为什么-T272不起作用。
我创建了一个简单的 CLR 函数来压缩/解压缩NVARCHAR列:
[SqlFunction(DataAccess = DataAccessKind.None, IsDeterministic = true)]
public static SqlBinary Compress( string str ){
if( str == null ){return new SqlBinary();}
if( String.IsNullOrEmpty( str ) ){str = " ";}
byte[] bytes = Encoding.Unicode.GetBytes( str );
using( MemoryStream msi = new MemoryStream( bytes ) ){
using( MemoryStream mso = new MemoryStream() ){
using( GZipStream gs = new GZipStream( mso, CompressionMode.Compress ) ){
msi.CopyTo( gs );
}
return new SqlBinary( mso.ToArray() );
}
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的压缩率大约是 4,或者如果我有 1024 …
我已经使用 AlwaysON AG 很长时间了,目前在 120 个数据库和 3 个 AG 组中拥有大约 10TB 的数据,用于 SQL 2012 上的任何应用程序并取得了巨大成功。每个 AG 组在补丁级别 11.0.5058.0 上运行,主数据中心有 2 个同步副本(在不同的 SAN 上),DR 中有 1 个异步副本。迁移一直不是问题,因为没有一个数据库足够大,以至于我无法适应 SAT 早上 12 点到 4 点的维护窗口。
我的问题是,我最后一个迁移到 2012 年的应用程序包含一个 4TB TDE 加密数据库数据库,它比我之前迁移的任何应用程序大 10 倍左右。数据库在大量调优后需要 4 小时才能备份(我讨厌 TDE !!)
由于种子增量,恢复到主副本是即时的,但问题来自必须在添加到可用性组之前备份数据库。4 小时是我的确切停电窗口,我不能再得到更多了。
我迁移应用程序的计划是 -
第一个中断窗口
从 2008 年到 2012 年的主副本还原数据库
将应用程序 ARECORD(或 cname 不确定是哪个)更改为主副本
在单个节点上运行数据库直到下一个中断窗口
一周后:
我不喜欢这个的地方是我整个星期都用 1 个节点而不是 3 个节点,这很令人担忧。如果其他人对如何实现这一点有任何更好的想法,我很乐意听取您的意见,或在可用性组中使用 VLDB 的人员的任何类型的评论,以及您喜欢/讨厌/喜欢这样做的地方。我正在尝试全力以赴地使用这个软件,到目前为止我一直很喜欢它,但在涉及到 VLDB 迁移时却很担心。
我有一个增长到 20 GB 的数据库,在归档一些数据后,表的实际大小仅为 5GB。备份脚本会将备份副本保存到其他位置。移动 20GB 或 5Gb 确实有所不同,所以我想减小物理尺寸,但如果我不想影响性能,我读到的任何地方都不要缩小。
但是在这种(定期/每季度/每年)归档的情况下,是否仍然建议不要收缩?
我面临着与不断增长的日志文件相关的问题,因此我收到了错误。当我检查 SQL 日志时,我发现以下消息(错误日志中几乎 90% 都填充了这些消息)
SQL Server 遇到 1 次 I/O 请求需要超过 15 秒才能在文件中完成
几乎所有数据库都会发生这种情况,包括 temdb [.mdf 和 .ndf 文件] 以及我也收到以下消息
平均吞吐量:0.34 MB/秒 I/O 饱和度:196 次上下文切换 1210
最后一个未完成的目标:530 avgWriteLatency 2
FlushCache:在 142370 毫秒内清理了 6233 个 buf,384 次写入(避免了 99 个新的脏 buf),用于 db 6:0
我的 temdb 大小和其他数据库和日志文件大小足够大。
历史:
我的行动计划:
我发现日志文件的初始大小很小,增长了 10%。我计划将初始大小增加 512 MB,增加 512 MB 以获得合理数量的 VLF。
问题 1:虽然我会在非高峰时段进行工作,但进行这些更改是否有可能损坏我的数据库或日志文件?
问题二:数据库压缩方式会影响IO操作吗?如果是,我该如何解决?
我计划从防病毒检查中删除所有数据库和日志文件。
我计划将目标恢复时间更改为 < 1 分钟的数据库(特别是 tempdb 和我的数据库)
问题 3:这会影响我的数据库吗?我的意思是刷新缓冲区和写入磁盘应该可以提高性能,对吗?
问题 4:我有 3 个 tempdb …
我正在尝试优化以下查询(这是我能想到的最简化的版本):
SELECT tr.Id, StatusDate
FROM (
SELECT tr.Id, tr.StatusDate
FROM mon.ArchivedTaskResults_201504 as tr WITH (NOLOCK)
INNER JOIN mon.ViewDevicesWithGroups dev WITH (NOLOCK) ON tr.DeviceId = dev.Id
WHERE tr.ClientId = 4 AND dev.Deleted = 0
) AS tr
ORDER BY StatusDate DESC
OFFSET 1000000 rows
FETCH NEXT 25 ROWS ONLY
Run Code Online (Sandbox Code Playgroud)

问题是,查询性能与 OFFSET 成正比 - 对于 offset=0 查询在 0.0 秒内执行,但对于 offset=1000000 执行时间约为 23 秒(如果偏移量更大,则可能需要几分钟)。
我几乎可以肯定我的问题可以通过 ArchivedTaskResults 表上的适当聚集索引来解决,但是在尝试了几个小时之后我仍然没有找到好的索引。
ArchivedTaskResults 表真的很大,大约有 50000000 行(50 M)
附加信息:
如果有人能解决我上面描述的问题,我会非常高兴,但说实话,我的真实查询更加奇怪(免责声明:我不是设计这个数据库的人):
SELECT tr.Id, StatusDate
FROM (
(
SELECT tr.Id, StatusDate …Run Code Online (Sandbox Code Playgroud) 对于我们在 SQL Server 2012 RTM 上的数据库之一,
正如错误所说,我们几乎无法执行任何故障排除步骤:
" 由于 'CHECKPOINT',事务日志已满
这是一个开发数据库,它的备份从未发生过,所以我们甚至无法选择。
尝试缩小日志文件但没有成功并得到以下错误:
日志空间不足 - 由于“检查点”,事务日志已满,出现级联错误
DBCC CHECKDB 大多只是给出错误,因为事务日志因“CHECKPOINT”而已满
我无法将恢复模式更改为完整 - 出现错误,因为“CHECKPOINT”导致事务日志已满
无法备份:同样的错误:
甚至尝试在其他服务器(SQL server 2012 RTM)上分离和附加,但同样的错误:
尝试在数据库上手动执行 CHECKPOINT,但仍然出现相同的错误:
已经在这里参考了这篇文章Simple model database transaction log full 'CHECKPOINT'
和
由于 'XTP_CHECKPOINT',数据库 'database_name' 的事务日志已满,但没有成功。
注意:我们没有在当前服务器或任何数据库上设置复制。
请帮助,因为我无法找到根本原因并解决此问题!
谢谢!
sql-server-2012 ×10
sql-server ×6
performance ×3
compression ×2
bulk-insert ×1
identity ×1
memory ×1
migration ×1
shrink ×1
sql-clr ×1
t-sql ×1
tempdb ×1