我们有一些数据库有宽表COLUMNSTORE
压缩(21 或 30 COLUMNS)和 2500 个分区(按日期)。该数据库中大约有 4000 个 stats 对象,其中大部分是分区表上的 INCREMENTAL 列统计信息。
sys.dm_db_stats_properties
在这些数据库上运行时,这个表函数的性能极差。我们正在查看每行大约 1 秒 - 即此表函数的每次“运行”。
下面是一个简单查询生成的查询计划示例,其CROSS APPLY
语法用于针对 1605 个 stats-table 组合执行此表函数。
这里没有什么非常有帮助的 - DMV 的表现显然很差。
我目前的理论是,由于数据库中统计对象的性质,对 OPENROWSET 内部表的查询优化不佳(可能是TOP 1
,这就是导致速度变慢的原因。
CREATE FUNCTION sys.dm_db_stats_properties (@object_id int, @stats_id int)
RETURNS TABLE
AS
RETURN SELECT TOP 1 -- The first row in the TVF will be the root; avoid scanning entire TVF to find any additional rows.
object_id, -- Columns now explicit since underlying tvf …
Run Code Online (Sandbox Code Playgroud) 我有一个查询来检索基于来自 dm_exec_query_stats DMV 的总逻辑读取的前 10 个查询。
SELECT TOP 10
SUBSTRING(qt.TEXT, (qs.statement_start_offset/2)+1,
((CASE qs.statement_end_offset
WHEN -1 THEN DATALENGTH(qt.TEXT)
ELSE qs.statement_end_offset
END - qs.statement_start_offset)/2)+1),
db_name(qt.dbid) as db_name,
qs.execution_count,
qs.total_logical_reads,
qs.total_worker_time,
qs.total_elapsed_time/1000000 total_elapsed_time_in_S,
SUBSTRING(CONVERT(varchar(19),qs.last_execution_time),1,19)
FROM sys.dm_exec_query_stats qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) qt
CROSS APPLY sys.dm_exec_query_plan(qs.plan_handle) qp
ORDER BY qs.total_logical_reads DESC
Run Code Online (Sandbox Code Playgroud)
查询返回所有请求的信息,除了查询来自或指向的数据库的名称。无论我使用 dm_exec_sql_text 还是 dm_exec_query_plan 结果都是一样的。
db_name(qt.dbid) 作为 db_name dm_exec_sql_text
或者
db_name(qp.dbid) 作为 db_name dm_exec_query_plan
两者都返回 NULL 或 tempdb 作为数据库名称。
选择 Reports -> Performance Top Queries by Average IO 时会出现同样的问题。
数据库名称为空。
但是,如果我将查询计划添加到查询中,然后在 SSMS 中打开查询计划,我可以通过将鼠标悬停在各种索引查找、扫描或 RID …
当我执行下面的两个查询时,
SELECT
session_id, transaction_id
FROM sys.dm_tran_session_transactions;
Run Code Online (Sandbox Code Playgroud)
和
SELECT
session_id, request_id, at.transaction_id
FROM sys.dm_tran_active_transactions at
JOIN sys.dm_exec_requests r
ON r.transaction_id = at.transaction_id;
Run Code Online (Sandbox Code Playgroud)
我已经阅读了1和2的 BOL,但没有看到任何关于为什么会出现差异的明确解释。
我得到不同的结果。前一个查询不返回任何结果,但后者返回带有会话和事务 ID 的活动事务。该request_id
是0,我认为它,意味着它在会议上提出的唯一请求。有人可以帮助我理解为什么我上面查询的两个概念之间存在差异吗?
编辑
我只是重新运行了查询,现在我得到了第一个 DMV 的结果,该结果session_id
实际上并未包含在第二个结果集中。
在我们的 SQL Server 2014 实例之一上,根据 sys.dm_exec_cached_plans 用于缓存计划的内存量与根据 sys.dm_os_memory_clerks 查看 CACHESTORE_SQLCP 类型(我理解)的内存量之间存在奇怪的差异用于即席查询缓存计划)。
如果我们查询缓存计划如下:
select cp.cacheobjtype, cp.objtype,
sum(cast(cp.size_in_bytes as money))/1024/1024 as sizeMB
from sys.dm_exec_cached_plans as cp
group by cp.cacheobjtype, cp.objtype;
Run Code Online (Sandbox Code Playgroud)
那么我们似乎总共有大约 90 MB 用于缓存计划,只有 2MB 用于临时计划。缓存中也只有 300 个计划。
但是,如果我们查看 dm_os_memory_clerks 视图如下:
select mc.type, mc.pages_kb/1024 as pagesMB
from sys.dm_os_memory_clerks as mc
where mc.type = 'CACHESTORE_SQLCP'
Run Code Online (Sandbox Code Playgroud)
然后它报告大约使用了 12 GB。我们的实例有大约。其中有 300 GB 的 RAM。
我们想了解这种差异,并在理想情况下采取一些措施来确保计划缓存得到有效使用(即其中有 300 多个计划以提高目前非常差的缓存命中率)。能够考虑这个空间将是第一步。
关于差异可能是什么以及为什么这个空间不被用于缓存计划的任何想法?
我有以下查询,它告诉我我负责的数据库中查询的状态(尽管我不是 DBA)。
SELECT
T3.FullStatement as FullSQLStatement
,T3.ExecutingStatement
,req.session_id as SessionId
,T2.login_name as LoginName
,command as SQLCommand
,start_time as StartTime
,DateDiff(MINUTE,start_time,GetDate()) as ElapsedTimeMinutes
,req.status as QueryStatus
,req.wait_type as WaitType
,req.wait_time as WaitTimeMs
,blocking_session_id as BlockingSessionId
,req.row_count as [RowCount]
,req.cpu_time as CpuTimeMs
,req.total_elapsed_time as TotalElapsedTimeMs
,SubString(sqltext.TEXT,req.statement_start_offset,req.statement_end_offset-req.statement_start_offset)
FROM sys.dm_exec_requests req
Inner Join sys.dm_exec_sessions T2 ON T2.session_id = req.session_id
Cross Apply dbo.GetExecutingSQLStatement (req.session_id) T3
Cross Apply sys.dm_exec_sql_text(sql_handle) AS sqltext
where req.database_id = 5
Order By 6 Desc
Run Code Online (Sandbox Code Playgroud)
它生成的输出部分如下所示:
尽管它在我包含的示例中没有很好地显示,但 start_time 是完整语句的开始时间,而不是语句的执行部分。有什么地方可以获取执行部分的开始时间以及完整语句的开始时间。这对我很重要,因为很明显,一个完整的语句可能有许多单独的查询。
查看sys.dm_os_wait_stats 时,以下列定义为BIGINT
如果这些值中的任何一个超过9,223,372,036,854,775,807
,计数器是否重置为 0,或者只是停止计数?
从表定义中不清楚幕后发生了什么:
sp_helptext 'sys.dm_os_wait_stats'
Run Code Online (Sandbox Code Playgroud)
返回:
CREATE VIEW sys.dm_os_wait_stats AS
SELECT *
FROM OpenRowset(TABLE SYSWAITSTATS)
Run Code Online (Sandbox Code Playgroud)
所以这有点像一个黑匣子。
在某些 DMV 中,大量数字可能会变为负数。一个例子是 中的total_elapsed_time
列dm_exec_requests
。
我们最近在 SQL Server 2014 HADR 环境中遇到了一个问题,其中一台服务器用完了工作线程。得到消息:
AlwaysOn 可用性组的线程池无法启动新的工作线程,因为没有足够的可用工作线程
虽然我们能够通过将可用性组之一移动到另一台服务器来“解决”问题,但我想知道是否可以查看哪些查询在哪个调度程序(或工作程序或任务)上运行。
通过以下查询,我可以看到有多少工人可用、正在使用和等待资源:
declare @max int
select @max = max_workers_count from sys.dm_os_sys_info
select
@max as 'TotalThreads',
sum(active_Workers_count) as 'CurrentThreads',
@max - sum(active_Workers_count) as 'AvailableThreads',
sum(runnable_tasks_count) as 'WorkersWaitingForCpu',
sum(work_queue_count) as 'RequestWaitingForThreads' ,
sum(current_workers_count) as 'AssociatedWorkers'
from
sys.dm_os_Schedulers where status='VISIBLE ONLINE'
Run Code Online (Sandbox Code Playgroud)
通过以下查询,我可以看到哪些工作人员正在哪个 CPU(核心)上运行:
SELECT *
FROM sys.dm_os_Schedulers s --> Prozessoren Kerne
JOIN sys.dm_os_workers w ON w.scheduler_address = s.scheduler_address
JOIN sys.dm_os_tasks t ON t.task_address = w.task_address
WHERE s.status = 'VISIBLE ONLINE'
AND s.cpu_id = 2
Run Code Online (Sandbox Code Playgroud)
有什么方法可以找到哪个 …
我正在尝试监控无法使用 PerformanceMonitor 跟踪的实时性能数据和使用情况。在生产实时 OLTP 数据库中读取 DMV 的后果是什么?: 例如:sys.dm_tran_locks、sys.dm_os_waiting_tasks、sys.dm_os_performance_counters、sys.dm_exec_connections、sys.dm_io_virtual_file_stats、sys.dm_exec_sql_text 等
我应该在查询 Dmvs 时使用 WITH (NOLOCK) 吗?这会解决许多资源问题吗?在 DMV 中是否有诸如脏读回滚之类的东西。我知道它可以存在于应用程序表中,例如有人提交订单然后取消等。此外,使用 NOLOCK,是否有更高的机会在高容量环境中永远继续,因为我没有锁定行、页面,事情将继续添加到 DMV TableView 中?
谢谢,
我正在尝试批量重新输入列。这意味着首先删除并重新创建它们所属的任何约束。
我发现这些约束引用的列
但我找不到计算列。
我已经研究过INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE
,但它不包括计算列。
还有sys.computed_columns
which 显示定义,但不以可搜索的方式列出列。
我还有其他地方可以看吗?如果 SQL Server 可以弄清楚依赖关系,我想我也可以。
我目前正在查询sys.dm_db_log_info()
DMV 以从数据库检索 VLF,以确定何时可以收缩、重组和减少 TLOG 文件中的碎片量(10 MB VLF)。
原因是,如果事务位于 TLOG 文件末尾并导致活动 VLF,则无法收缩 TLOG 文件。类似的情况,如果活动事务驻留在 TLOG 文件的中间,那么您就无法缩小到超过该 VLF。
我目前有这个语句来检索MAX(vlf_begin_offset)
记录、MIN(vlf_begin_offset)
记录和任何具有 active 的记录vlf_active = 1
:
SELECT ddli.vlf_begin_offset,
ddli.vlf_sequence_number,
ddli.vlf_active,
ddli.vlf_status,
ddli.vlf_first_lsn
FROM sys.dm_db_log_info(DB_ID()) AS ddli
WHERE ddli.vlf_begin_offset = (
SELECT MIN(ddli2.vlf_begin_offset)
FROM sys.dm_db_log_info(DB_ID()) AS ddli2
)
OR ddli.vlf_active = 1
OR ddli.vlf_begin_offset = (
SELECT MAX(ddli3.vlf_begin_offset)
FROM sys.dm_db_log_info(DB_ID()) AS ddli3
)
ORDER BY
ddli.vlf_begin_offset ASC
Run Code Online (Sandbox Code Playgroud)
当所有记录都返回时,结果集如下所示:
+------------------+---------------------+------------+------------+------------------------+
| vlf_begin_offset | vlf_sequence_number | vlf_active | vlf_status …
Run Code Online (Sandbox Code Playgroud)