我从查询存储开始,它有问题:-( 没有生成 Top Resource Consuming Queries 的报告。它只是一直说“等待”几个小时和几个小时。后台查询(请参见下面的示例)不是能够完成并消耗大量 CPU。无论我如何更改配置选项,它一直在等待和等待(甚至最后一小时报告)。这是查询存储的现实吗?听起来是一个很棒的工具,但完全是实际无法使用?
我的查询存储大小约为 1.7 GB。我正在以 1 小时的间隔和自动捕获模式收集 7 天的数据 - 所以对我来说这似乎是合理的设置。
这是一个从未完成的后台查询示例:
SELECT TOP (@results_row_count)
p.query_id query_id,
q.object_id object_id,
ISNULL(OBJECT_NAME(q.object_id),'') object_name,
qt.query_sql_text query_sql_text,
ROUND(CONVERT(float, SUM(rs.avg_duration*rs.count_executions))*0.001,2) total_duration,
SUM(rs.count_executions) count_executions,
COUNT(distinct p.plan_id) num_plans
FROM sys.query_store_runtime_stats rs
JOIN sys.query_store_plan p ON p.plan_id = rs.plan_id
JOIN sys.query_store_query q ON q.query_id = p.query_id
JOIN sys.query_store_query_text qt ON q.query_text_id = qt.query_text_id
WHERE NOT (rs.first_execution_time > @interval_end_time OR rs.last_execution_time < @interval_start_time)
GROUP BY p.query_id, qt.query_sql_text, q.object_id
HAVING COUNT(distinct p.plan_id) >= 1 …Run Code Online (Sandbox Code Playgroud) 我刚刚将我们的数据仓库升级到 SQL 2016。我在查询存储中看到了一些非常有趣的图表(我喜欢这个功能!)。下面是我见过的最奇怪的例子。同一查询的 22 个计划。
这让我开始考虑 ETL 过程的性能调优、临时表的优缺点以及如何影响执行计划行为。
我的 ETL 过程使用了许多存储过程,这些过程混合使用标准和临时 #tables 作为临时表。#tables 通常使用一次然后删除。有些只有几千行。有些是数百万。SSMS 建议缺少索引,但是在较小的表上,它们是否会产生足够的差异以值得添加它们?更好的统计数据就足够了吗?
我刚刚阅读了有关临时表统计信息的Brent Ozar 博客文章,以及 Paul White 关于存储过程中的临时表的文章
它说统计信息是在查询#table 时自动创建的,然后大概由优化器使用。
我的问题是:在#table 上创建索引是否有很多意义或好处。和/或:在查询中使用统计信息之前,是否值得显式更新统计信息作为存储过程中的一个步骤,因为它们只使用一次。
额外的步骤和开销是否值得?它会导致明显更好或不同的执行计划吗?
sql-server index-tuning temporary-tables sql-server-2016 query-store
这解释起来有点复杂,但很容易重现。
对于大约 10%-30% 的查询(按计数),大量的查询存储数据不可用。我查看了 SQL 2016 和 SQL 2017,其中查询存储已经运行了数周以上,数据库上有活动。
下面的查询将返回两组数据,顶部集没有 值query_store_query.last_execution_time,而底部集在字段中有数据。“没有”也缺少大多数运行时统计数据。
EXEC sp_query_store_flush_db; --Same results without this, but just to rule it out in the examples.
go
Select * from sys.query_store_query
where query_store_query.last_execution_time is null -- there are bunch of these, also missing other data, why?
Select * from sys.query_store_query
where query_store_query.last_execution_time is not null
Run Code Online (Sandbox Code Playgroud)
我最初使用导出的查询存储数据发现了这一点我的数据在 Excel 工作表中,我进行了排序和比较,但没有发现任何将“拥有”与“没有”分开的共同因素
为了排除数据导出问题,我使用上面的代码直接从系统数据视图中获取数据。结果与导出数据中的结果相似。
为了排除系统数据视图,我使用“跟踪查询”从根数据报告。(查询存储 > 跟踪查询 > 配置)
3.A. 对于“拥有”,查询计划等会显示出来,正如您所期望的
3.B. 对于“没有”,没有查询计划和指标
我发现的唯一范围限制因素是,在非常活跃的数据库上,“没有”仅限于最后几个小时。但是在慢速数据库上,“没有”可能有可以追溯到几周前的 initial_compile_start_time。(我怀疑“没有”正在被清除,然后在下次运行“以前从未见过,新”查询时重新创建)
“没有”可以有任何范围的编译计数、计划数量等。
我试图找出上周遇到的一种情况,为了临时修复事件期间的计划回归,我使用查询存储强制执行计划,但发现它没有按预期工作。我已经阅读了安德鲁凯利关于如何被迫并不总是意味着被迫的文章,并认为这可能是我所看到的,但我希望对它有更深入的了解,因为在我的情况下,计划与我不同” d 期待。我还查看了有关计划强制的查询存储文档的计划强制限制部分,但我认为此处不适用任何限制。
查询存储中的视图如下所示 - 大约 8:30 出现了一个成本更高的新计划(2.14178 vs 0.894238),我强制执行了之前使用的计划。从图中可以看出,尽管我强制执行了旧计划,但从此时起,新计划将针对查询的指标显示:
查看 sys.query_store_plan,我可以看到旧计划显示为强制的并且没有任何反对意见,表明强制执行失败:
奇怪的是,当我后来查看计划缓存时,这些计划都没有使用,尽管使用中的计划确实具有与上面显示的计划 13449 相同的查询计划哈希值,尽管它们完全不同。实际使用的计划的估计成本要高得多,为 72.6743。
我从这些计划中的每一个中获取了编译值,并运行了对其中三个计划的查询,以了解计划的实际指标是什么样的,并且这些值与估计值大不相同。值得注意的是,我从缓存中获取的计划产生了大约 400 MB 的内存授予,因为它使用不同的索引并且必须对数据进行排序,而其他 2 个计划中的 8 MB 内存授予没有排序。三个计划的估计成本更接近一些,但查询存储中的 2 个计划的估计成本比查询存储中显示的计划高得多。
这是发生的查询:
(
@id_group int,
@create_date datetime,
@rows_per_page int,
@page_number int
)
SELECT *
FROM ts_customer
WHERE
id_group = @id_group
AND enabled = 'Y'
AND (create_date >= @create_date)
ORDER BY
full_name,
id_customer desc
offset
((@page_number - 1) * @rows_per_page) rows
fetch next @rows_per_page rows only
Run Code Online (Sandbox Code Playgroud)
谁能帮助我理解为什么不强制执行该计划,以及为什么正在使用的计划要贵得多?
我知道这select *会导致大内存授予,因为它是一个宽表,但我主要是想了解这里看到的查询存储行为,以及在较小程度上,为什么在使用而不是强制的计划中计划它使用不同的索引并且必须进行排序。 …
performance sql-server azure-sql-database query-store query-performance
最近,我们将一台生产服务器从 SQL Server 2016 升级到 SQL Server 2019 (CU 15)。这对我来说是一个在我们的主应用程序数据库上启用查询存储的绝佳机会。它已经运行了几天,这是总体资源消耗报告显示的内容:
在屏幕截图中,我精心挑选了一些看起来很疯狂的数字(查询存储启用的第一天),并将它们标准化为更容易讨论的度量单位。诸如逻辑读取消耗约 183 TB的数据,或内存消耗约 5 TB的数据之类的事情,在这台服务器上似乎几乎是不可能的。
该数据库是数据库中的 John Smith,数据文件大小仅为100 GB ,日志文件大小为200 GB 。全天最多可能有 100 个不同的用户连接到它,并且一天内不会创建大量交易。服务器本身仅为其配置了32 GB内存。要消耗5 TB内存,一天中分配的内存需要被填满150 多次。
我可以考虑添加的唯一其他可能相关的信息是升级后,我们立即将此数据库的“兼容性级别”设置为 150 (SQL Server 2019) 并保留“旧基数估计”设置。我知道这并不理想,最好在收集基线指标时让尘埃落定,但升级的部分原因是为了解决一些紧急的性能问题,从我们的测试来看,这些设置组合实际上最有效(并且仍然看起来)工作得很好)。
我们之前遇到的一些性能问题是由于疯狂的基数估计造成的,如果查询存储使用估计数据点,那么我实际上可以看到此报告的数字是相关的,但我不得不想象该报告是使用实际数据点?不过,如果这是我的生产服务器/数据库在我不断征服基数估计问题时的配置方式存在根本错误的另一个迹象,那将会很有趣。
我是否读错了这些数字,查询存储是否出问题了,或者我的服务器是否正常?
是否有任何选项可以在查询存储中查看已终止的会话?
我这么问是因为我们有一个附加工具,如果会话运行时间超过 30 分钟(KILL命令),它就会终止会话。
我想检查查询存储中已终止查询的执行计划。我在查询存储中找不到被这个附加应用程序杀死的会话/查询。
使用 SSMS 2016 查询存储,几周前我强制特定查询使用特定计划。现在我时不时地会遇到错误:
由于此查询中定义的提示,查询处理器无法生成查询计划。重新提交查询而不指定任何提示且不使用 SET FORCEPLAN
我假设SET FORCEPLAN是自动传递的,因为执行该查询的代码不会自动传递。所以我想重新审视我的强制计划,也许取消它。但我在查询存储中找不到该查询了。
因此我的问题是:有没有一种方法可以列出所有强制查询计划,然后如何取消一个?
今天早上,收到了以下电子邮件警报:
日期/时间:2/28/2018 9:26:42 AM
描述:尝试在数据库 9 中获取逻辑页 (1:3948712) 失败。它属于分配单元 72057594045857792 不属于 72059184917512192。
评论:(无)
作业运行:SQL Sentry 2.0 警报陷阱
查看辅助副本的事件日志,同一消息出现了 3 次:
源 spid138
消息 尝试获取数据库 9 中的逻辑页 (1:3948712) 失败。它属于分配单元 72057594045857792 不属于 72059184917512192。
在辅助副本(2 节点同步可用性组)上运行以下内容:
DBCC TRACEON(3604)
dbcc page (9, 1,3948712,3)
go
DBCC TRACEOff(3604)
Run Code Online (Sandbox Code Playgroud)
任一副本的结果片段:
Page @0x00000070DAB8C000
m_pageId = (1:3948712) m_headerVersion = 1
m_type = 3 m_typeFlagBits = 0x0 m_level = 0
m_flagBits = 0x8200 m_objId (AllocUnitId.idObj) = 129 m_indexId
(AllocUnitId.idInd) = 256 Metadata: AllocUnitId = 72057594046382080
Metadata: PartitionId = 72057594040811520
Metadata: …Run Code Online (Sandbox Code Playgroud) 可以在模型数据库上启用查询存储,并确保每个新数据库都具有与模型数据库相同的设置。
缺少 GUI 选项
但可以使用 TSQL 启用它
ALTER DATABASE model
SET QUERY_STORE = ON (OPERATION_MODE = READ_WRITE);
Run Code Online (Sandbox Code Playgroud)
由于没有 GUI,我无法检查那里的默认设置。
再次使用TSQL
USE model;
select * from sys.database_query_store_options;
Run Code Online (Sandbox Code Playgroud)
返回空结果
当我创建一个新数据库(使用模型作为模板并查询设置时,它会显示结果)
create database TestQs;
go
use TestQs;
select * from sys.database_query_store_options;
Run Code Online (Sandbox Code Playgroud)
此外,设置必须保存在某处,因为当我更改查询存储选项时,更改会传播到新数据库
ALTER DATABASE model
SET QUERY_STORE (INTERVAL_LENGTH_MINUTES = 22);
Run Code Online (Sandbox Code Playgroud)
我尝试过使用 SMO 来找到这些选项,但没有成功。
$SqlServer = New-Object Microsoft.SqlServer.Management.Smo.Server -ArgumentList 'localhost'
$sqlServer.Databases['TestQs'].QueryStoreOptions
Run Code Online (Sandbox Code Playgroud)
但对模型数据库进行相同的查询不会产生任何结果
$SqlServer = New-Object Microsoft.SqlServer.Management.Smo.Server -ArgumentList 'localhost'
$sqlServer.Databases['model'].QueryStoreOptions
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以检查模型数据库上的查询存储设置,而无需创建新数据库并在那里进行检查?
我有一个查询,我在查询存储中强制执行一个计划(该计划是为此查询编译的 SQL Server)如果我在强制执行该计划后立即运行该查询,NO_PLAN尽管数据库没有发生任何更改,但我会得到last_force_failure_reason_desc。我可以成功地对同一查询强制执行不同的计划
这个问题可以用下图来说明:
创建我们的测试数据库
USE [master]
CREATE DATABASE NO_PLAN
ALTER DATABASE [NO_PLAN] SET QUERY_STORE = ON
ALTER DATABASE [NO_PLAN] SET QUERY_STORE (OPERATION_MODE = READ_WRITE, QUERY_CAPTURE_MODE = ALL)
GO
USE NO_PLAN
GO
IF EXISTS (SELECT 1 FROM sys.tables WHERE name = 'MyTableA') DROP TABLE MyTableA
IF EXISTS (SELECT 1 FROM sys.tables WHERE name = 'MyTableB') DROP TABLE MyTableB
/* create our tables */
CREATE TABLE [dbo].[MyTableA](
[Column1] VARCHAR(50) NULL ,
[Column2] VARCHAR(255) NULL ,
[Column3] INT NULL , …Run Code Online (Sandbox Code Playgroud) query-store ×10
sql-server ×9
performance ×3
corruption ×1
hints ×1
index-tuning ×1
kill ×1
smo ×1
ssms ×1
upgrade ×1