SELECT TOP 1会损害查询性能;有没有dba可访问的方法来克服这个问题?


13

在生产应用程序(C#与SQL Server 2014 Standard对话)中,下面是一个查询,如下所示。大多数情况下,它以毫秒为单位运行。但是有时(对于的某些值@Id)会变得很疯狂,并且需要一分钟左右的时间。这比应用程序超时时间长,因此该应用程序对用户而言将失败。

在“疯狂”的情况下,返回的结果集正确地为空,就像在许多但并非所有其他情况下一样。

幸运的是,这在生产和开发环境中都是可重现的。

开发人员说,从查询中删除“ TOP 1”,然后确保应用消耗了结果集的多余行,从而清除了性能问题。

查询计划程序建议不存在索引TOP 1。(在dev中)。

正在进行更改查询和修复应用程序。推出需要一段时间。

我的问题:在采用新查询的应用程序更改推出之前,是否有任何DBA可访问的方法来调整或调整生产SQL Server实例以克服此问题?

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg ON apg.person_id = bi.person_id
  JOIN pplan ON pplan.plan_id = sub.plan_id
  JOIN product ON product.product_id = [plan].product_id 
  JOIN product_attribute ON product_attribute.product_id = product.product_id 
 WHERE apg.group_id = @Id
   AND apg.start_date < GETDATE()
   AND (apg.end_date IS NULL OR apg.end_date > GETDATE()) 
   AND (sub.end_date IS NULL OR sub.end_date > GETDATE()) 
   AND product_attribute.attribute_type = 'special feature' 
   AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;

您是否尝试过将其作为子查询?例如,从中选择前1个subscription_id(选择[您的其余查询,但不包含top1]
SeanR '16

也许一些“正常”的查询调整会起作用?如果索引足够吸引人,扫描就会消失。这比计划指南的侵入性小。
usr

那么,@ID 始终具有相同的值会使它“发疯”吗?如果是这样,则使用这些值之一进行测试并捕获实际的查询计划。这将告诉您出了什么问题。如果“坏”值不一致,则可能是由于参数嗅探(有关解决方案,请参见@MartinSmith的答案),也可能是涉及客户端实际如何请求和使用结果集的锁定问题。
RBarryYoung '16

Answers:


12

如果您无法更改查询,则可以使用计划指南。

使用来测试查询的性能OPTION (QUERYTRACEON 4138)(需要具有sysadmin权限的人员才能尝试此操作)。

如果可以产生令人满意的性能,则可以将其与计划指南一起应用。如果它不能产生令人满意的性能,请尝试找到一个提示。问题可能OPTION (HASH JOIN, MERGE JOIN)是不合适的嵌套循环。您可能需要求助于USE PLAN N'...'提示。

知道所需的提示后,您可以使用此处的信息应用它们。


OPTION (QUERYTRACEON 4138)做到了。谢谢。现在开始整理计划指南。
O. Jones,

0

对于咧嘴一笑,尝试将
`>更改为> =,所以查询不完全相同

SELECT TOP 1
       subscription_id 
  FROM subscription AS sub
  JOIN billing_info AS bi 
        ON bi.billing_info_id = sub.billing_info_id   
  JOIN person_group AS apg 
        ON apg.person_id = bi.person_id 
       AND apg.group_id = @Id
       AND apg.start_date < GETDATE()
       AND isnnull(apg.end_date, GETDATE()) >= GETDATE()             
  JOIN pplan 
        ON pplan.plan_id = sub.plan_id
       AND isnnull(sub.end_date, GETDATE()) >= GETDATE()
  JOIN product 
        ON product.product_id = [plan].product_id 
  JOIN product_attribute 
        ON product_attribute.product_id = product.product_id 
       AND product_attribute.attribute_type = 'special feature' 
       AND product_attribute.attribute_data = '1' 
 ORDER BY sub.start_date ASC;

“更改查询并修复应用程序正在进行中。推出需要一段时间。” OP正在寻找“按原样”修复性能的解决方案。
马丁·史密斯

@MartinSmith当他们确实推出修复程序时,这可能是一个更好的解决方案。使应用程序占用多余的行将是其他程序更改。
狗仔队
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.