使用TSQL for SQL Server,有没有办法快速限制查询中涉及的行? (我并不是指返回的行)

时间:2014-05-14 20:37:33

标签: sql-server tsql

方案

想象一下,我有一个名为'Bob'的客户,他已经订购了过去几年的数百万件商品。我想知道每个订单的平均数量。但是,如果我扫描的行数超过X行,我只想停止处理。

示例

SELECT 
    customers.CustomerName, 
    AVG(orderItems.QuantityOrdered) AS AverageQuantityOrdered
FROM 
    dbo.Customers customers
INNER JOIN 
    dbo.Orders orders ON orders.CustomerID = customers.CustomerID
INNER JOIN 
    dbo.OrderItems orderItems ON orderItems.OrderID = orders.OrderID
WHERE 
    customers.CustomerID = 1234 --bob's customerid
GROUP BY 
    customers.CustomerName    

此结果集应返回1条记录。但我喜欢限制查询以使其停止运行,或者如果扫描的基础记录达到某个限制则会爆炸。

尝试

  • Count(*) Over()只返回1(或返回的记录数)
  • SUM(Count(*))不允许
  • Top X仅基于返回记录集(并且可能在cte中变得非常慢)

摘要

我真正期待的是让查询分析器说'嘿,你在这里需要大约1,000,000条记录,并在达到限制时将查询短路。

这个例子非常简单。我可以在5个表中搜索,我很想知道在聚合数据之前底层记录集的数量是多少。

谢谢!

3 个答案:

答案 0 :(得分:1)

这不完全是一些行,但请看一下Query Governer Cost Limit

  

指定查询可以运行的最长时间的数字或整数值...查询调控器不允许执行任何估计成本超过该值的查询。

请注意,这是基于估算的费用,这可能很棘手。您需要花些时间调整最终值,特别是随着数据库表的增长,同一查询的成本会随着时间的推移而增加。

答案 1 :(得分:1)

为什么?
你为什么要停止处理?
停在一定数量的开销可能高于处理

即使您正在加入五个子查询或交叉应用问题,索引也会丢失()

如果您遇到性能问题,我建议您发布实际查询 确保你有正确的索引并尽早过滤我的答案 查看查询计划
有了4个连接可能会发生的事情是查询优化器只是变得愚蠢并且进行所有循环连接

你不需要别名小写。
表名称不区分大小写

如果你有一个OrderDate,你现在只能回到目前为止 但如果OrderDate没有编入索引,请不要这样做

如果您将条件拉入联接,它可以帮助查询优化器提前过滤 如果你有orders.CustomerID和orderItems.OrderID的索引,这应该是一个非常有效的查询

SELECT customers.CustomerName, 
       AVG(orderItems.QuantityOrdered) AS AverageQuantityOrdered
  FROM Customers 
 INNER JOIN Orders  
    ON orders.CustomerID = customers.CustomerID 
   AND customers.CustomerID = 1234 
   AND orders.OrderDate >= '1/1/2010'
 INNER JOIN OrderItems  
    ON orderItems.OrderID = orders.OrderID 
 GROUP BY customers.CustomerID

答案 2 :(得分:0)

以下是使用APPLY的一种可能的解决方案(我最近决定我喜欢这些东西)。请注意,我将其编码为使用基于我假设将被称为OrderDate的字段的10个最新订单。

SELECT 
  customers.CustomerName, 
  AVG(orderItems.QuantityOrdered) AS AverageQuantityOrdered
FROM Customers customers
CROSS APPLY (
  SELECT TOP 10 * 
  FROM Orders o
  WHERE o.CustomerID = customers.CustomerID
  ORDER BY o.OrderDate DESC
)orders
INNER JOIN OrderItems orderItems ON orderItems.OrderID = orders.OrderID
WHERE customers.CustomerID = 1234 --bob's customerid
GROUP BY customers.CustomerName