【发布时间】:2015-01-14 19:17:34
【问题描述】:
当结果集为空时,我的查询运行缓慢。有东西要还,快如闪电。
;with tree(NodeId,CategoryId,ParentId) as (
select ct.NodeId, ct.CategoryId, ct.ParentId
from dbo.CategoryTree as ct
where ct.ParentId = 6
union all
select t.NodeId, t.CategoryId, t.ParentId from dbo.CategoryTree as t
inner join tree as t2 on t.ParentId = t2.NodeId
), branch(NodeId,CategoryId,ParentId) as
(
select NodeId, CategoryId, ParentId from dbo.CategoryTree as t
where t.NodeId = 6
union all
select NodeId, CategoryId, ParentId
from tree as t
),facil(FacilityId) as(
select distinct fct.FacilityId
from dbo.FacilitiesCategoryTree as fct
inner join branch b on b.NodeId = fct.CategoryNodeId
)
select top 51 f.Id, f.CityId, f.NameGEO,
f.NameENG, f.NameRUS, f.DescrGEO, f.DescrENG,
f.DescrRUS, f.MoneyMin, f.MoneyAvg, f.Lat, f.Lng, f.SortIndex,
f.FrontImgUrl from dbo.Facilities f
inner join facil t2 on t2.FacilityId = f.Id
and f.EnabledUntil > 'Jan 14 2015 10:23PM'
order by f.SortIndex
主要表是: 设施表保存设施,256k 记录。 CategoryTree 用于对层次结构中的类别进行分组。
NodeId int,
CategoryId int,
ParentId int
FacilitiesCategoryTree 用于将 CategoryTree 链接到设施。
给定 NodeId,第二个 CTE 返回给定节点的所有后代节点,包括它自己。然后是第三个 CTE,它返回属于这些节点的设施 ID。
最后,最后一个 CTE 加入到实际设施表中。结果由 SortIndex 排序,用于手动指示设施的顺序。
即使我包含更多谓词(包括全文搜索和其他),当有要返回的内容时,此查询也会运行得非常快,但是当给定分支没有任何设施时,此查询大约需要 .运行 2 秒。
如果我排除 order by 子句,查询再次运行得非常快。所有这些表都已编入索引,查询优化器并未提出任何改进建议。
您认为问题出在哪里,可以采取哪些措施来提高空结果查询的性能?
谢谢。
更新1: 我正在添加执行计划。
http://www.filedropper.com/withorderby
http://www.filedropper.com/withoutorderby
更新 2: 我查看了 oryol 的建议,并尝试将设施 ID 从树保存到表变量中,并将其与设施表连接起来,并按 SortIndex 排序。它消除了空结果的问题,但将结果集的查询的执行时间从 250 毫秒增加到了 950 毫秒。
我还将查询更改为从设施中选择并加入设施并添加选项(强制订单)。结果和上面一样。
最后,我对设施/类别映射表进行了非规范化,以在该表中包含 SortIndex。它将普通查询的执行时间从 250 毫秒略微增加到 300 毫秒,但它解决了空结果集的问题。我想,我会坚持这个方法。
【问题讨论】:
-
ORDER BY一定给查询优化器提供了错误的提示,比如使用了低效的索引。您可以发布带有和不带有ORDER BY的执行计划吗? -
我在更新后的帖子中添加了两个执行计划。
标签: sql sql-server