【问题标题】:SQL Server : why is this query so slow?SQL Server:为什么这个查询这么慢?
【发布时间】:2015-03-18 23:51:58
【问题描述】:

我有一条 SQL 语句来提取记录。某些员工可以访问某些记录。人员安全都在一个单独的过程中完成,并附加到搜索 SQL 子句的 where 子句中。

简化示例:

select 
    o.id, o.staff.id 
from 
    Orders o
where 
    staffid = 100 
    or orderid in (select orderid from schedule where staffid = 5)

对

select 
    o.id, o.staff.id 
from 
    Orders o
where 
    staffid = 100 or orderid in (1, 2, 3, 4, 5, 6, 7, 8)

嵌套的 sql select orderid from schedule where teamid = 5 运行时间为 1 秒。如果将结果粘贴到其位置,则主查询将在 2 秒内运行。如果您运行顶级 SQL,则需要一分钟多的时间才能运行。出于某种原因,您如何告诉 SQL 先运行嵌套选择而不将其分解为临时表?

来自您所有建议的更多信息:

我的 SQL 也有OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY。删除后,查询速度很快。它可以在 1 秒内返回 1800 条记录,但请求 10 条记录需要 40 秒。

如果我将订单更改为staffid,它也会运行得很快。 order by 和 fetch next 的组合导致 SQL 运行不同的执行计划。由于Where 子句位于软件的单独部分中,我无法更改order by,它正在扼杀性能。

【问题讨论】:

  • teamid = 5 或 staffid = 5 在子查询中?
  • 在“实际执行计划”开启的情况下运行查询,看看它是否建议任何索引。此外,通过简化示例而不共享架构,您可能隐藏了问题的实际原因。
  • 执行计划没有显示索引提示。查询成本分为 35/65,这很奇怪,因为运行时间是 2 秒 vs 45 秒。
  • Tanner,很好,我开始删除我的 SQL 的某些方面,看看它是否运行得更快。发生 OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;导致它变慢。如果我删除这两个查询都很快。

标签: sql sql-server optimization


【解决方案1】:
with    scheduleOrders as 
        (select orderid from schedule where staffid = 5)
select  o.id, o.staff.id
from    Orders o
where   o.staffId = 100
union
select  o.id, o.staff.id
from    Orders o join scheduleOrders so on o.orderId = so.orderId

【讨论】:

  • 我无法更改主 SQL,我必须更改 where 子句的安全部分。 where 子句是安全会话的一部分,它被附加到我们应用程序中的许多报告 SQL 中。
【解决方案2】:

尝试使用Exists

Select o.id, o.staff.id 
from Orders o
Where staffid = 100 or EXISTS (select 1 from schedule s where staffid = 5 and s.orderid=o.orderid)

使用In,它会尝试检索所有内部查询结果,而使用Exists,它只会检查该行是否存在

【讨论】:

  • 这不适用于较新版本的 SQL。 (即 SQL2008 优化器足够聪明,可以将 IN 视为 EXISTS)
【解决方案3】:
SELECT o.id, o.staffId 
FROM Orders o
WHERE o.staffid = 100 
OR EXISTS ( SELECT 'a'
            FROM schedule s
            WHERE s.staffId = 5
            AND s.orderId = o.orderId
           )

编辑... 加入版更快?

SELECT DISTINCT o.*
FROM Orders o JOIN schedule s ON s.orderId = o.orderId
WHERE o.staffid = 100 
OR s.staffId = 5

你的表有多少行?

【讨论】:

  • 每条记录超过一百万条。
猜你喜欢
  • 2014-03-12
  • 2011-03-11
  • 2020-03-19
  • 2011-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多