为什么我必须使用这些层次结构查询强制排序/
Why do I have to Force Order with these hierarchy queries/
下面是我可能 运行 的查询示例,其中对于每个类别,我希望 NumberOfCourses 不仅代表该特定类别,还代表其下的所有子类别。我认为该查询相当不言自明。
select c.CategoryID, courses.MarketID, count(distinct courses.CourseID) NumberOfCourses
from Category c
join CategoryHierarchy tch on tch.HierarchyKey like '%~' + cast(c.CategoryID as varchar) + '~%'
join vLiveEvents courses on tch.CategoryID = courses.CategoryID
where courses.MarketID is not null
group by c.CategoryHumanID, courses.MarketID
当我运行按原样执行时,可能需要将近两分钟,但是如果我添加提示Option (Force Order)
,则只需几秒钟即可运行。所以我的问题是我是不是做错了什么导致 SQL 制定了一个糟糕的计划,或者 SQL 引擎实际上并不擅长像这样优化层次结构连接?
我尝试包括 sql 计划,但它太长了,所以不会让我有那么多角色。如果有人能告诉我如何分享,我很乐意分享它。
编辑:我想可能不是每个人都知道这些层次结构是如何工作的。它们的层次结构键类似于 ~1234~5678~9123~,其中 1234 是 5678 的父级,5678 是 9123 的父级。通过对 CategoryID 进行类似比较,我可以在结果中包含所有子类别。
从SQL Server 2016+开始,引入了查询存储功能来监控性能。它提供了对查询计划选择和性能的洞察。
It also provides an option to force plan.
它不是跟踪或扩展事件的完全替代品,但随着它从一个版本发展到另一个版本,我们可能会在未来的版本中从 SQL 服务器获得一个功能齐全的查询存储。
Query Store的主要流程
- SQL 服务器现有组件通过使用查询存储管理器与查询存储交互。
- 查询存储管理器确定应使用哪个存储,然后将执行传递给该存储(计划或运行时统计或查询等待统计)
- Plan Store - 保存执行计划信息
- Runtime Stats Store - 保存执行统计信息
- Query Wait Stats Store - 持久化等待统计信息。
- 计划、运行时统计和等待存储使用查询存储作为 SQL 服务器的扩展。
启用查询存储:查询存储在服务器上的数据库级别工作。
- 默认情况下,新数据库的查询存储不活动。
- 您不能为主数据库或
tempdb
数据库启用查询存储。
- 可用的 DMV
sys.database_query_store_options
(Transact-SQL)
在查询存储中收集信息:我们使用查询存储 DMV(数据管理视图)从三个存储中收集所有可用信息。
查询计划存储:
保留执行计划信息,并负责捕获与查询编译相关的所有信息。
sys.query_store_query
(Transact-SQL)
sys.query_store_plan
(Transact-SQL)
sys.query_store_query_text
(Transact-SQL)
运行时统计存储:
持久化执行统计信息,它可能是更新最频繁的存储。这些统计数据代表查询执行数据。
sys.query_store_runtime_stats
(Transact-SQL)
查询等待统计存储:
保存和捕获等待统计信息。
sys.query_store_wait_stats
(Transact-SQL)
注意: 查询等待统计存储仅在 SQL Server 2017+
中可用
下面是我可能 运行 的查询示例,其中对于每个类别,我希望 NumberOfCourses 不仅代表该特定类别,还代表其下的所有子类别。我认为该查询相当不言自明。
select c.CategoryID, courses.MarketID, count(distinct courses.CourseID) NumberOfCourses
from Category c
join CategoryHierarchy tch on tch.HierarchyKey like '%~' + cast(c.CategoryID as varchar) + '~%'
join vLiveEvents courses on tch.CategoryID = courses.CategoryID
where courses.MarketID is not null
group by c.CategoryHumanID, courses.MarketID
当我运行按原样执行时,可能需要将近两分钟,但是如果我添加提示Option (Force Order)
,则只需几秒钟即可运行。所以我的问题是我是不是做错了什么导致 SQL 制定了一个糟糕的计划,或者 SQL 引擎实际上并不擅长像这样优化层次结构连接?
我尝试包括 sql 计划,但它太长了,所以不会让我有那么多角色。如果有人能告诉我如何分享,我很乐意分享它。
编辑:我想可能不是每个人都知道这些层次结构是如何工作的。它们的层次结构键类似于 ~1234~5678~9123~,其中 1234 是 5678 的父级,5678 是 9123 的父级。通过对 CategoryID 进行类似比较,我可以在结果中包含所有子类别。
从SQL Server 2016+开始,引入了查询存储功能来监控性能。它提供了对查询计划选择和性能的洞察。
It also provides an option to force plan.
它不是跟踪或扩展事件的完全替代品,但随着它从一个版本发展到另一个版本,我们可能会在未来的版本中从 SQL 服务器获得一个功能齐全的查询存储。 Query Store的主要流程
- SQL 服务器现有组件通过使用查询存储管理器与查询存储交互。
- 查询存储管理器确定应使用哪个存储,然后将执行传递给该存储(计划或运行时统计或查询等待统计)
- Plan Store - 保存执行计划信息
- Runtime Stats Store - 保存执行统计信息
- Query Wait Stats Store - 持久化等待统计信息。
- 计划、运行时统计和等待存储使用查询存储作为 SQL 服务器的扩展。
启用查询存储:查询存储在服务器上的数据库级别工作。
- 默认情况下,新数据库的查询存储不活动。
- 您不能为主数据库或
tempdb
数据库启用查询存储。 - 可用的 DMV
sys.database_query_store_options
(Transact-SQL)
在查询存储中收集信息:我们使用查询存储 DMV(数据管理视图)从三个存储中收集所有可用信息。
查询计划存储: 保留执行计划信息,并负责捕获与查询编译相关的所有信息。
sys.query_store_query
(Transact-SQL)sys.query_store_plan
(Transact-SQL)sys.query_store_query_text
(Transact-SQL)运行时统计存储: 持久化执行统计信息,它可能是更新最频繁的存储。这些统计数据代表查询执行数据。
sys.query_store_runtime_stats
(Transact-SQL)查询等待统计存储: 保存和捕获等待统计信息。
sys.query_store_wait_stats
(Transact-SQL)
注意: 查询等待统计存储仅在 SQL Server 2017+
中可用