当使用系统版本控制的时态表(SQL Server 2016 中的新功能)时,当使用此功能处理大型关系数据仓库中的缓慢变化维度时,查询创作和性能影响是什么?
例如,假设我有一个Customer带有Postal Code列的 100,000 行维度和一个Sales带有CustomerID外键列的数十亿行事实表。并假设我想查询“按客户邮政编码划分的 2014 年总销售额”。简化的 DDL 是这样的(为了清楚起见省略了很多列):
CREATE TABLE Customer
(
CustomerID int identity (1,1) NOT NULL PRIMARY KEY CLUSTERED,
PostalCode varchar(50) NOT NULL,
SysStartTime datetime2 GENERATED ALWAYS AS ROW START NOT NULL,
SysEndTime datetime2 GENERATED ALWAYS AS ROW END NOT NULL,
PERIOD FOR SYSTEM_TIME (SysStartTime, SysEndTime)
)
WITH (SYSTEM_VERSIONING = ON);
CREATE TABLE Sale
(
SaleId int identity(1,1) NOT NULL PRIMARY KEY CLUSTERED,
SaleDateTime …Run Code Online (Sandbox Code Playgroud) data-warehouse sql-server slowly-changing-dimension temporal-tables sql-server-2016
tl; dr:为什么 CHECKDB 读取具有内存优化表的用户数据库的事务日志?
CHECKDB 在检查我的一个数据库时似乎正在读取用户数据库的事务日志文件 - 特别是使用内存中 OLTP 表的数据库。
这个数据库的 CHECKDB 仍然在合理的时间内完成,所以我主要只是对这种行为感到好奇;但这绝对是该实例上所有数据库中 CHECKDB 持续时间最长的。
在查看 Paul Randal 的史诗“ CHECKDB From Every Angle:所有 CHECKDB 阶段的完整描述”时,我看到 SQL 2005 之前的 CHECKDB用于读取日志以获得一致的数据库视图。但由于这是 2016 年,它使用内部数据库快照。
源数据库不得包含 MEMORY_OPTIMIZED_DATA 文件组
我的用户数据库有这些文件组之一,所以看起来快照不在表中。
根据CHECKDB 文档:
如果无法创建快照,或者指定了 TABLOCK,DBCC CHECKDB 将获取锁以获得所需的一致性。在这种情况下,需要一个排他数据库锁来执行分配检查,并且需要共享表锁来执行表检查。
好的,所以我们正在做数据库和表锁定而不是快照。但这仍然不能解释为什么它必须读取事务日志。那么什么给呢?
我在下面提供了一个脚本来重现该场景。它用于sys.dm_io_virtual_file_stats识别日志文件读取。
请注意,大多数时候它读取日志的一小部分 (480 KB),但偶尔读取更多 (48.2 MB)。在我的生产场景中,当我们运行 CHECKDB 时,它会在每晚午夜读取大部分日志文件(2 GB 文件中的约 1.3 GB)。
以下是我目前使用脚本获得的输出示例:
collection_time num_of_reads num_of_bytes_read
2018-04-04 15:12:29.203 106 50545664
Run Code Online (Sandbox Code Playgroud)
或这个:
collection_time num_of_reads num_of_bytes_read …Run Code Online (Sandbox Code Playgroud) 我正在使用 Microsoft SQL Server 2016 (SP2-CU11) (KB4527378) - 13.0.5598.27 (X64) Nov 27 2019 18:09:22 版权所有 (c) Windows Server 2012 R2 上的 Microsoft Corporation 标准版(64 位)标准 6.3(内部版本 9600:)
该服务器位于 SSD 驱动器上,最大内存为 128 GB。Parallelism 的 CostTheshold 是 70,MaxDegree of Parallelism 是 3。
我有一个“行程”表,它由 23 个外键引用,带有 ON DELETE CASCADE 选项。
这个表本身并没有那么大(530 万行,1.3 GB 数据)。但是在 23 个引用的表中,有两个表非常大(超过 10 亿行,每行 54 和 69 GB)。
问题是当我们尝试删除“Trips”表中的少量行(假设为 4 行)时,SQL 估计将要删除这么多行,它需要 10GB 的 RAM,估计将有数百万行返回,并锁定表。一切都停止,其他查询阻塞,应用程序超时。
以下是 1 个删除语句的主表和行数:
sql-server delete execution-plan sql-server-2016 query-performance
每次我重新启动 Windows 时,对于某些数据库,我都会收到此错误:
操作系统返回错误 21(设备未就绪。)
chkdsk /r- 没有坏扇区。我执行DBCC CHECKDB没有错误:
*(CHECKDB found 0 allocation errors and 0 consistency errors in database)*
Run Code Online (Sandbox Code Playgroud)Windows 10 和 SQL Server 2016 Express。
CACHESTORE_SQLCP Sql 计划在几天后占用 > 38 GB。
我们已经在运行“优化临时工作负载”选项。(实体框架和自定义报告创建了很多临时!)
具有多可用区镜像的 AWS RDS 上的 SQL Server 2016 SE 3.00.2164.0.v1
当我运行时:
DBCC FREESYSTEMCACHE('SQL Plans');
Run Code Online (Sandbox Code Playgroud)
或者
DBCC FREEPROCCACHE
Run Code Online (Sandbox Code Playgroud)
或者
DBCC FREESYSTEMCACHE ('SQL Plans') WITH MARK_IN_USE_FOR_REMOVAL
Run Code Online (Sandbox Code Playgroud)
或者
DBCC FREESYSTEMCACHE ('ALL') WITH MARK_IN_USE_FOR_REMOVAL;
Run Code Online (Sandbox Code Playgroud)
它似乎没有清除它:
SELECT TOP 1 type, name, pages_kb FROM sys.dm_os_memory_clerks ORDER BY pages_kb desc
type name pages_kb
CACHESTORE_SQLCP SQL Plans 38321048
Run Code Online (Sandbox Code Playgroud)
我在启用查询存储的情况下运行,但我禁用了它以查看是否有任何干扰,它似乎没有帮助,但我将其关闭。
真正奇怪的是
SELECT COUNT(*) FROM sys.dm_exec_cached_plans
Run Code Online (Sandbox Code Playgroud)
是 1-3 左右(它似乎只显示显示当前正在运行的查询),即使所有内存都已保留,甚至在我尝试清除任何内容之前。我错过了什么?
CACHESTORE_SQLCP 占用了所有可用内存的 60% 以上,这是一个问题,因为偶尔会发生内存等待。此外,我们不得不在周末终止一个持续 4 小时的例行 DBCC CHECKDB,因为内存不足导致等待(它立即完成,没有错误,打开 PHYSICAL_ONLY)。
有没有办法回收这些内存(除了每晚重启!?)?
当我跑
SELECT * FROM …Run Code Online (Sandbox Code Playgroud) 在最大内存设置为 25GB 的 SQL Server 2016 SP2 上,我们有一分钟执行大约 80 次的查询。该查询将大约 4000 页溢出到 tempdb。这会导致 tempdb 的磁盘上出现大量 IO。
当您查看查询计划(简化查询)时,您会看到估计行数等于实际行数,但仍然会发生溢出。所以过时的统计数据不能成为问题的原因。
我做了一些测试和以下查询溢出到 Tempdb:
select id --uniqueidentifier
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
Run Code Online (Sandbox Code Playgroud)
但是,如果我选择不同的列,则不会发生溢出:
select startdate --datetime
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
Run Code Online (Sandbox Code Playgroud)
所以我试图“放大” id 列的大小:
select CONVERT(nvarchar(512),id)
from SortProblem
where [status] ='A'
order by SequenceNumber asc
option (maxdop 1)
Run Code Online (Sandbox Code Playgroud)
然后也不会发生溢出。
为什么 uniqueidentifier 不会溢出到 tempdb 和 datatime 列?当我删除大约 20000 条记录时,当我选择 id …
sql-server tempdb sorting sql-server-2016 cardinality-estimates
我知道隐式类型转换不是一个好习惯。但当较低的值突然变得较高时,这确实是意想不到的行为。
declare @LastSelectedDate DATETIME = '2021-11-09 13:52:29.187'
declare @LastSelectedDate_1 DATETIME2(7) = '2021-11-09 13:52:29.1866667'
SELECT IIF(@LastSelectedDate_1 > CAST(@LastSelectedDate AS DATETIME2), 1, 0)
SELECT IIF(@LastSelectedDate_1 > @LastSelectedDate, 1, 0)
Run Code Online (Sandbox Code Playgroud)
这是一个错误还是我遗漏了什么?我正在使用 SQL Server 2016。
我有20M行的表,每一行有3列:time,id,和value。对于每个id和time,value状态都有一个。我想知道time特定id.
我使用了两种方法来实现这一点。一种方法是使用加入和另一种方法是使用功能导致的窗口/滞后与聚簇索引time和id。
我通过执行时间比较了这两种方法的性能。join方法需要16.3秒,窗口函数方法需要20秒,不包括创建索引的时间。这让我感到惊讶,因为窗口函数似乎是先进的,而连接方法是蛮力的。
下面是这两种方法的代码:
创建索引
create clustered index id_time
on tab1 (id,time)
Run Code Online (Sandbox Code Playgroud)
select a1.id,a1.time
a1.value as value,
b1.value as value_lag,
c1.value as value_lead
into tab2
from tab1 a1
left join tab1 b1
on a1.id = b1.id
and a1.time-1= b1.time
left join tab1 c1
on a1.id = c1.id
and a1.time+1 = c1.time
Run Code Online (Sandbox Code Playgroud)
使用SET STATISTICS TIME, IO ON以下方法生成的 IO …
performance join sql-server window-functions sql-server-2016 query-performance
如果在事件会话中向事件添加“太多”操作,您将收到此错误:
消息 25639,级别 16,状态 23,第 1 行 事件“[事件名称]”超出了允许的绑定操作数。
允许多少动作?它是否因事件而异?
根据实验,答案似乎是 27 sqlserver.rpc_completed。但我没有在任何Microsoft 文档中找到该数字。它似乎因事件而异,因为我能够为sqlserver.sql_batch_completed.
失败的示例代码:
CREATE EVENT SESSION [Test] ON SERVER
ADD EVENT sqlserver.rpc_completed(
ACTION(
package0.callstack,
package0.collect_cpu_cycle_time,
package0.collect_current_thread_id,
package0.collect_system_time,
package0.event_sequence,
package0.last_error,
package0.process_id,
sqlos.cpu_id,
sqlos.numa_node_id,
sqlos.scheduler_address,
sqlos.scheduler_id,
sqlos.system_thread_id,
sqlos.task_address,
sqlos.task_elapsed_quantum,
sqlos.task_resource_group_id,
sqlos.task_resource_pool_id,
sqlos.task_time,
sqlos.worker_address,
sqlserver.client_app_name,
sqlserver.client_connection_id,
sqlserver.client_hostname,
sqlserver.client_pid,
sqlserver.context_info,
sqlserver.database_id,
sqlserver.database_name,
sqlserver.is_system,
sqlserver.nt_username,
sqlserver.plan_handle))
GO
DROP EVENT SESSION [Test] ON SERVER
GO
Run Code Online (Sandbox Code Playgroud)
成功的示例代码(相同但不包括最后一项):
CREATE EVENT SESSION [Test] ON SERVER
ADD EVENT sqlserver.rpc_completed(
ACTION(
package0.callstack,
package0.collect_cpu_cycle_time,
package0.collect_current_thread_id,
package0.collect_system_time, …Run Code Online (Sandbox Code Playgroud) 我们有一个在 VMware 虚拟机中运行的 SQL Server 2016 SP1 实例。它包含 4 个数据库,每个数据库用于不同的应用程序。这些应用程序都在单独的虚拟服务器上。它们都没有在生产中使用。不过,测试应用程序的人报告了性能问题。
这些是服务器的统计信息:
用户通过基于 C++ 的 ERP 应用程序执行单屏幕访问。
当我ostress使用许多小查询或大查询对 Microsoft 的 SQL Server 进行压力测试时,我获得了最大性能。唯一的限制是客户端,因为他不能足够快地回答。
但是当几乎没有任何用户时,SQL Server 几乎不做任何事情。然而,人们必须永远等待才能在应用程序中保存任何内容。
根据 Paul Randal 的“告诉我它在哪里受到伤害”查询,所有等待事件中有 50% 是ASYNC_NETWORK_IO.
这可能意味着网络问题,或应用程序服务器或客户端的性能问题。他们甚至都没有以最大能力远程使用他们的资源。大多数情况下,所有机器(客户端、应用程序服务器、数据库服务器)上的 CPU 都在 26% 左右。
网络连接的延迟约为 1-3 毫秒。数据库服务器的 IO 在应用程序正常使用期间的最大写入速度为 20MB/s(平均为 7-9MB/s)。当我进行压力测试时,我的速度最高可达 5GB/s。
缓冲区缓存大小为我们的 ERP 系统 DB 为 60GB,我们的财务软件为 20GB,质量保证软件为 1GB,文档归档系统为 3GB。
我授予 …
sql-server ×10
sql-server-2016 ×10
performance ×2
amazon-rds ×1
datetime ×1
datetime2 ×1
dbcc-checkdb ×1
delete ×1
errors ×1
join ×1
memory ×1
optimization ×1
sorting ×1
tempdb ×1
vmware ×1
windows-10 ×1