【问题标题】:Adding ORDER BY clause makes query take longer time to complete添加 ORDER BY 子句使查询需要更长的时间才能完成
【发布时间】:2015-10-07 05:51:42
【问题描述】:

如果不添加ORDER BY RenewalDate,则需要 1 秒。在添加 ORDER BY 子句时,它需要 2.22 分钟。我在这个列上做了索引,但没有提高性能。Pindex(Non-Unique,Non-Clustered)

如何在不降低性能的情况下使用ORDER BY 子句。

RenewalDate (date, null) - 这个带有ORDER BY 的列导致了问题

查询:

select 
    LinkId,
    LinkName,
    CategoryId,
    ReportLinks
    SubmissionStatus,
    convert(nvarchar(18), LnkSubmsnDate) as LnkSubmsnDate,
    convert(nvarchar(18), LnkUpdateDate) as LnkUpdateDate,
    LnkSubmtdBy,
    K.KeyWord,
    RenewalDate
from tbl_Link L
left join Tbl_keywords K 
    on L.KeywordID = K.KeywordID
where 
    (SubmissionStatus = 'Approved' or SubmissionStatus = 'Waiting for Approval')
    and  LnkSubmtdBy ='swapna'
    and Convert(Char(4), LnkSubmsnDate, 100) in (
        select Convert(Char(4), LnkSubmsnDate, 100) 
        from tbl_Link
    )
order by 
    case when RenewalDate is null then 1 else 0 end,
    RenewalDate

【问题讨论】:

  • 这可能会有所帮助:stackoverflow.com/questions/2139980/…
  • RenewalDate 列中有索引吗?
  • 没有。但是刚刚完成索引,让我们看看会发生什么,CREATE INDEX PIndex ON tbl_Link (RenewalDate)
  • 我已经完成索引但没有效果,Pindex(Non-Unique,Non-Clustered) 但性能没有提高,同样是 2.22 min@JapzDivino
  • 你能发布两个查询的执行计划,有和没有排序吗?另外,这个条款到底是什么——Convert(Char(4), LnkSubmsnDate, 100) in (select Convert(Char(4), LnkSubmsnDate, 100) from tbl_Link)——应该做什么? tbl_Link.LnkSubmsnDate 中的任何值怎么可能不满足这个标准?您正在检查同一张表中的同一列。

标签: sql sql-server


【解决方案1】:

你有这个问题,因为它正在逐行检查RenewalDate,如果你想使用它,也许你可以在你的RenewalDate列中放置一个索引。

    case when RenewalDate is null then 1 else 0 end,
    RenewalDate

【讨论】:

  • 我删除了 - RenewalDate 为 null 然后 1 否则 0 结束的情况,并按续订日期添加简单的订单,仍然需要 2.22 分钟。它的订单问题不是 case@japz
【解决方案2】:

而不是这个:

and Convert(Char(4), LnkSubmsnDate, 100) in (
        select Convert(Char(4), LnkSubmsnDate, 100) 
        from tbl_Link

使用这个:

and exists(
        select  (1)
        from tbl_Link TL
            where Convert(Char(4), TL.LnkSubmsnDate, 100) = Convert(Char(4), L.LnkSubmsnDate, 100))     

【讨论】:

  • EXISTSIN 在以这种方式编写时会以完全相同的方式进行优化,因此这不会有任何区别。此外,它当然不能解释为什么添加ORDER BY 会使查询变慢,而没有它,查询会明显更快。
  • 抱歉订单没有引起问题。 Convert(Char(4),LnkSubmsnDate,100) in (select Convert(Char(4),LnkSubmsnDate,100) from tbl_Link ) 这部分导致问题,这使得缓慢
【解决方案3】:

您需要的是两个表上的唯一聚集索引(在创建任何非聚集索引之前创建)。也许tbl_Link.LinkIdTbl_keywords.KeywordID 分别是唯一聚集索引的候选者作为您的主键。

一见钟情的非聚集索引: tbl_Link.KeywordID 上的一个会是个好主意 - 因为它是您的 JOIN 列,是您与表 Tbl_keywords 的连接。

进一步考虑索引列:

  • SubmissionStatus
  • LnkSubmtdBy
  • LnkSubmsnDate
  • RenewalDate

请记住:非聚类索引只有在在聚类索引之后创建

时才会表现良好

【讨论】:

  • 声明“只有在集群索引之后创建非集群索引才能正常运行” 是不正确的。如果没有聚集索引(堆表),那么非聚集索引指向的每一行(RowID)仍然有一个唯一标识符,如果有什么比聚集索引更好,当然不会更差。
  • 如果表是堆表 -> 数据分散在磁盘上的任何地方!与具有主键/唯一聚集索引的表相比,您永远不会获得良好的性能。非聚集索引会很快碎片化并且“无用”....
  • 虽然我不提倡使用堆表并且总是推荐使用聚集索引,但我也不提倡错误信息。数据不会分散在磁盘上的任何地方,它仍然以与聚集索引相同的方式存储在页面中,只是没有预定义的数据顺序,因为查找每一行都需要这样的 rowid。 This answer on dba.stackexchange 对堆表和聚集表上的非聚集索引进行了一些相当广泛的测试,并且在除了更新堆表之外的每个操作中都表现得更好。
  • 非聚集索引在两个表上的工作方式几乎完全相同,不同之处在于堆表上,而不是存储用于查找的聚集键,它使用文件 id 、页码的组合和堆中的槽号。所以碎片化当然不是问题。事实上,因为它存储了有问题的行的确切页面位置,所以速度更快,因为有了聚簇键,仍然需要遍历聚簇索引才能找到正确的数据页。
  • “dba.stackexchange 上的这个答案”对我说:选择是可比较的,所有其他操作都更快拥有聚集索引!?!?!?
猜你喜欢
  • 2020-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-27
  • 1970-01-01
  • 1970-01-01
  • 2021-01-09
相关资源
最近更新 更多