【问题标题】:Why am I getting a query performance increase? [closed]为什么我的查询性能会提高? [关闭]
【发布时间】:2017-10-18 11:11:54
【问题描述】:

简介

简单的问题,我想了解是什么让查询更快。我目前被要求提高查询的性能,我有,但是,这是最好的部分,我不确定它如何或为什么更快,但它明显更快.

这对于解释为什么第二个查询如此之快并不是真正必要的,我只是在您想知道的情况下将其包含在内。基本上,我们最初希望找到大量数据,我的意思是每个有效的组合。因此,为什么我认为旧查询的 'top(1)' 部分实际上是无效的。


示例代码

原来的查询是这样运行的

SELECT 
 ... 
(SELECT TOP(1) v FROM pat pa WHERE pa.pc = p.c AND pa.ki = 64) AS pt, 
(SELECT TOP(1) v FROM pat pa2 WHERE pa2.pc = p.c AND pa2.ki = 17) AS col
...

所以这花费了惊人的时间,所以我把它改成了这样:

SELECT 
...
pt.v, col.v
...

INNER JOIN (
    SELECT DISTINCT v, pc
    FROM pat
    WHERE ki = 64
    GROUP BY v, pc
) AS pt
ON p.c = pt.pc

INNER JOIN (
    SELECT DISTINCT v, pc
    FROM pat
    WHERE ki = 17
    GROUP BY v, pc
) AS col
ON p.c = col.pc

评论

第一个查询会花费两倍的时间来执行,从字面上看,我的意思是性能提高了一倍多,实际上它也带回了更多的数据,这在这种情况下也是一件好事。

如果有人能解释为什么第二个速度这么快,我会很高兴? - 我已经计算出它需要原始查询的 20% 的时间,检索更多的记录,等等。


另外

在编写查询时,你能告诉我尽可能多的注意事项,以及做什么和不做什么的利弊吗? - 如何每次都能获得最佳性能?

我也刚刚编写了一个查询,并且以某种方式执行它会在性能方面产生 INSANE 差异。

第一个查询 - 慢查询

SELECT DISTINCT pa.v, pa.pc, pa.kid, ak.dn, ak.ID
FROM pat AS pa 
INNER JOIN akt AS ak 
ON pa.kid = ak.id

第二次查询 - 闪电般的快速

   WITH prodAts AS (
        SELECT DISTINCT v, pc, kid
        FROM pat
    ),

    aks AS (
        SELECT DISTINCT dn, ID
        FROM akt
    )

    SELECT DISTINCT *
    FROM prodAts 
    INNER JOIN aks 
    ON prodAts.kid = aks.ID

我的意思是用第一个查询生成 1 行,用第二个查询生成所有行需要相同的时间,我真的不知道这是怎么回事? - 请解释一下?

【问题讨论】:

  • 这是一个简单的问题,但它有无数的答案。图书馆已经写了关于这个主题的文章。我已经投票结束,因为范围太广。
  • 查看或阅读如何解释执行计划。所有的答案都在里面。
  • 我想执行计划听起来像是一个好的开始,我实际上没有访问服务器的权限,我只是编写查询,所以我什至不知道哪些表被索引,哪些表是不,等等。但我值得从它的声音中研究它吗?
  • 如果您无法访问服务器并且缺少有关服务器的重要信息,您将如何开展工作?这就像让法国机械师在不移动的情况下在英国修车!
  • 我真的不得不问高级开发人员,并做相当多的猜测工作......我知道疯了......它有时确实让我想拔头发......但是事实证明我现在已经变得非常擅长......我真的很喜欢你的比较,因为这就是一半的感觉!

标签: sql sql-server performance


【解决方案1】:

对于什么是最好的,并没有明确的答案,唯一的答案是“视情况而定”。在对系统进行性能调整时,需要考虑许多因素,包括表大小、索引、磁盘速度、cpu 速度和余量、并行量、语句顺序、可用内存。查询是否需要溢出到临时数据库中......这个列表还在继续。

正如 cmets 所说,我们只能真正推测为什么您的查询在您的示例中运行得更快,除非我们看到一些查询计划(它可以准确地告诉您每个查询实际上在做什么)。

对于第二个块,唯一想到的是基表上的索引不佳,CTE 将数据拉入内存,然后将它们连接在一起,因此可以全面了解数据的形式和结构正在操纵。直接连接方法可以快速扫描表/检查表的存储指标,并猜测将它们连接在一起的最佳方式(优化器可以使用多种内部连接方法)。 如果这些指标不好/不能代表当前存储的内容,那么优化器很可能会做出错误的决定。

根据您在问题中的评论,是的,可以访问服务器的状态和计划是最好的(计划至少他们会告诉您它正在使用哪些索引等)。否则你的性能调整只是在黑暗中刺痛,虽然你今天可能很幸运并取得了一些收益,但今晚可能会运行一个数据库维护任务,重组所有数据,导致你的新查询实际上是最不理想的选择(它可能发生) .

关于性能调优,我能给您的最好建议是找出“为什么当前的解决方案不好”而不是“为什么新的解决方案好”,这将指导您通过调优做出更好的调用。

【讨论】:

  • 老实说,我还是新手,所以即使是非常模糊的答案,如“取决于”,也比没有答案要好,尽管它会导致更多问题,但这不是重点。坦克你的输入! :) .... 是的,我的性能基准只是猜测如何获得相同的输出,只是更快地完成它,如何,这取决于运气/猜测工作......至于专业提示最后,我一定会牢记这一点,以备不时之需! :)
  • @joeevans996 在您的情况下,最好的办法是在内部推动,如果您可以访问查询计划,您的工作会简单得多。很高兴您目前看到自己的工作成果,但我确实认为制定计划会让您的输出更加一致。
  • 好吧,很有趣的事实,显然,当您删除 distinct 一词时,它将具有完全相同的执行计划。不过还是快很多,我请一位资深开发者看了一下,他说我脑子坏了,看来你的理论可能是对的?不知道?
  • 我原以为 distinct 会使用索引检查它们是否是唯一的,或者使用排序来识别区别。如果它正在使用索引(很可能如果他们有确切的查询计划)并且索引很糟糕,则需要更长的时间。尝试重建表上的索引并运行。原始查询。可能是表维护不佳的情况。如果您需要确保唯一性,我会推荐一个 group by 而不是 distinct
猜你喜欢
  • 2012-10-03
  • 1970-01-01
  • 2021-11-24
  • 2010-12-09
  • 1970-01-01
  • 2017-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多