缓慢而简单的查询,如何让它更快?

时间:2009-05-07 08:58:50

标签: sql sql-server database optimization

我有一个6GB大小的数据库,有大量的表,但是较小的查询似乎有最多的问题,并想知道可以做些什么来优化它们,例如有一个Stock,Items和Order Table 。
Stock表格是库存中的项目,其中包含大约100,000条记录,其中25个字段存储ProductCode,Price和其他特定于股票的数据。
Items表存储有超过2,000,000个项目的信息,超过50个字段存储项目名称和有关项目或产品的其他详细信息。
订单表存储库存物料的订单,这是订单下达的时间加上售出的价格,并且有大约50,000条记录。

以下是此数据库的查询:

SELECT Stock.SKU, Items.Name, Stock.ProductCode FROM Stock
INNER JOIN Order ON Order.OrderID = Stock.OrderID
INNER JOIN Items ON Stock.ProductCode = Items.ProductCode
WHERE (Stock.Status = 1 OR Stock.Status = 2) AND Order.Customer = 12345
ORDER BY Order.OrderDate DESC;

根据这里的信息可以做些什么来改进这个查询,还有其他类似的,有什么替代方案。然而,数据和数据库的性质无法进一步详细说明,因此如果给出一般的验光技巧和方法,这些将是正常的,或者通常适用于数据库的任何内容。
数据库是Windows Server 2003上的MS SQL 2000,每个都有最新的服务包。 DB Upgrade / OS Upgrade目前不是选项。


修改

指数是Stock.SKU,Items.ProductCode和Orders.OrderID上提到的表格。
查询的执行计划为13-16秒,比如75%的库存时间


感谢到目前为止的所有响应 - 索引似乎是问题,给出的所有不同示例都很有帮助 - 在查询中发现了一些错误,但这对我帮助很多,其中一些查询运行得更快但是结合索引建议我认为我现在可能正走在正确的道路上 - 感谢快速反应 - 真的帮助了我并让我考虑过之前我没想过或不知道的事情!


索引是我的问题在订单(客户)的Foriegn Key中添加了一个 通过将执行时间减半来提高性能! 看起来我有隧道视觉并专注于查询 - 我已经与DB一起工作了几年,但这非常有帮助。但是感谢所有的查询示例,我们没有考虑的组合和功能也可能有用!

9 个答案:

答案 0 :(得分:3)

你的代码是否正确?我确定你错过了什么

INNER JOIN Batch ON Order.OrderID = Orders.OrderID

你在代码中有a)...


您可以随时针对执行计划工具测试一些变体,例如

SELECT 
    s.SKU, i.Name, s.ProductCode 
FROM 
    Stock s, Orders o, Batch b, Items i
WHERE 
    b.OrderID = o.OrderID AND
    s.ProductCode = i.ProductCode AND
    s.Status IN (1, 2) AND 
    o.Customer = 12345
ORDER BY 
    o.OrderDate DESC;

并且你应该只返回一小部分,比如TOP 10 ......只需选择TOP 10就可以花费几毫秒,但是当你将它绑定到你的应用程序时,你将节省大量的时间。

答案 1 :(得分:2)

最重要的(如果尚未完成):定义表的主键(如果尚未定义),并为外键和在连接中使用的列添加索引。

答案 2 :(得分:2)

您是否指定了索引?上

  • Items.ProductCode
  • Stock.ProductCode
  • Orders.OrderID
  • Orders.Customer

有时,IN可能比OR快,但这并不像索引那么重要。

请参阅balexandre回答,查询看起来不对。

答案 3 :(得分:0)

一些通用指针

  • 您加入的所有字段都已编入索引吗?

  • ORDER BY是否必要?

  • 执行计划是什么样的?

顺便说一下,您似乎没有在问题查询示例中引用Order表。

答案 4 :(得分:0)

CătălinPitiş建议,表指数肯定会有所帮助。

另一个技巧是通过使用子选择或更极端使用临时表来减小连接行的大小。例如,不要在整个Orders表上加入,而是加入

(SELECT * FROM Orders WHERE Customer = 12345)

另外,不要直接加入Stock table join

(SELECT * FROM Stock WHERE Status = 1 OR Status = 2)

答案 5 :(得分:0)

在表格上设置正确的索引通常会对性能产生最大的影响。

在Management Studio(或早期版本的查询分析器)中,您可以选择在运行查询时查看查询的执行计划。在执行计划中,您可以看到数据库实际上正在做什么来获得结果,以及哪些部分最有效。有些东西需要查找,例如表扫描,这通常是查询中成本最高的部分。

表的主键通常有索引,但您应该验证它实际上是这样。然后,您可能需要在用于查找记录的字段上使用索引,以及用于排序的字段。

添加索引后,您可以重新运行查询,并在执行计划中查看它是否实际使用了索引。 (在创建索引之后,您可能需要等待一段时间才能构建索引,然后才能使用它。)

答案 6 :(得分:0)

你可以试一试吗?

SELECT Stock.SKU, Items.Name, Stock.ProductCode FROM Stock
INNER JOIN Order ON Order.OrderID = Stock.OrderID AND (Order.Customer = 12345) AND (Stock.Status = 1 OR Stock.Status = 2))
INNER JOIN Items ON Stock.ProductCode = Items.ProductCode
ORDER BY Order.OrderDate DESC;

答案 7 :(得分:0)

阐述CătălinPitiş已经说过的话:在你的查询中

SELECT Stock.SKU, Items.Name, Stock.ProductCode
    FROM Stock
      INNER JOIN Order ON Order.OrderID = Stock.OrderID
      INNER JOIN Items ON Stock.ProductCode = Items.ProductCode
  WHERE (Stock.Status = 1 OR Stock.Status = 2) AND Order.Customer = 12345
  ORDER BY Order.OrderDate DESC;

标准Order.Customer = 12345看起来非常具体,而(Stock.Status = 1或Stock.Status = 2)听起来不明确。如果这是正确的,则有效查询包含

1)首先查找属于特定客户的订单

2)然后找到相应的Stock行(具有相同的OrderID),过滤出状态为(1,2)的那些,

3)并最终在2)

中找到具有与Stock行相同的ProductCode的项目

对于1)你需要一个Customer表的订单索引,2)表Stock的OrderID索引和3)表Item的ProductCode索引。

只要您的查询不会变得复杂得多(比如在更大的查询中作为子查询,或者Stock,Order和Items只是视图,而不是表),查询优化器应该能够从中查找此计划您的查询。否则,你将不得不做kuoson建议的事情(但如果(1,2)中的状态不是非常具体和/或状态未在表状态上编入索引,则第二个建议没有帮助)。但是请记住,如果在表上进行许多插入/更新,保持索引的最新成本性能。

答案 8 :(得分:0)

为了缩短我2小时前给出的答案(当我的饼干关闭时):

您需要三个索引:表订单的客户,库存的订单ID和商品的ProductCode。

如果您错过了其中任何一项,则必须等待相应表格上的完整表扫描。