我遇到了一个我无法理解的问题。我们正在运行SQL Server 2012.我遇到了一对基本相同的查询,这些查询产生了不同的执行计划和执行的时间差异很大(1秒vs 40+秒)......他们甚至返回完全相同的记录。它们之间的唯一区别是记录被查询的类别。
此查询在1秒内运行:
SELECT P.idProduct, P.sku, P.description, P.price, P.listhidden, P.listprice, P.serviceSpec, P.bToBPrice, P.smallImageUrl,P.noprices,P.stock, P.noStock,P.pcprod_HideBTOPrice,P.pcProd_BackOrder,P.FormQuantity,P.pcProd_BTODefaultPrice,cast(P.sDesc as varchar(8000)) sDesc, 0, 0, P.pcprod_OrdInHome, P.sales, P.pcprod_EnteredOn, P.hotdeal, P.pcProd_SkipDetailsPage
FROM products P INNER JOIN categories_products CP ON P.idProduct = CP.idProduct
WHERE CP.idCategory=494 AND active=-1 AND configOnly=0 and removed=0 AND formQuantity=0
AND ((SELECT TOP 1 SP.stock FROM products SP WHERE SP.pcprod_ParentPrd = P.idProduct AND SP.description LIKE N'%(9-12 Months)' AND SP.removed=0) > 0)
ORDER BY P.description Asc
第二个运行40秒或更长时间,但唯一的区别是idCategory
查询:
SELECT P.idProduct, P.sku, P.description, P.price, P.listhidden, P.listprice, P.serviceSpec, P.bToBPrice, P.smallImageUrl,P.noprices,P.stock, P.noStock,P.pcprod_HideBTOPrice,P.pcProd_BackOrder,P.FormQuantity,P.pcProd_BTODefaultPrice,cast(P.sDesc as varchar(8000)) sDesc, 0, 0, P.pcprod_OrdInHome, P.sales, P.pcprod_EnteredOn, P.hotdeal, P.pcProd_SkipDetailsPage
FROM products P INNER JOIN categories_products CP ON P.idProduct = CP.idProduct
WHERE CP.idCategory=628 AND active=-1 AND configOnly=0 and removed=0 AND formQuantity=0
AND ((SELECT TOP 1 SP.stock FROM products SP WHERE SP.pcprod_ParentPrd = P.idProduct AND SP.description LIKE N'%(9-12 Months)' AND SP.removed=0) > 0)
ORDER BY P.description Asc
他们甚至以完全相同的顺序返回完全相同的记录。
[编辑]这里的计划是实际,而不是估计,执行计划。
categories_products
表是一个简单的查找表,只有两个字段idCategory
和idProduct
。即使返回的记录也完全相同(恰好是SP.description LIKE N'%(9-12 Months)'
的记录,相同的产品被分配到这两个类别)。两者之间唯一的另一个区别是CP.idCategory
628刚刚在今天早上创建(但我不知道可能会有什么不同)。
[编辑:但这正是确实产生了影响的因素]
这怎么可能?如何简单地更改此处查询的CP.idCategory
会产生不同的执行计划,更重要的是:如何执行需要40倍的执行时间?
最终,我不知道如何改善第二个查询的糟糕表现,因为我可以理解两者之间没有本质区别。
答案 0 :(得分:2)
[1]似乎两个不同的类别可能有不同的最佳执行计划。在这种情况下,SQL Server似乎认为最适合idCategory=494
的XP不是最佳idCategory=628
(WHERE CP.idCategory=494 / WHERE CP.idCategory=628
)。
此问题的根本原因似乎是dbo.products
表没有聚集索引。第一个测试就是创建一个CIX:
CREATE UNIQUE CLUSTERED INDEX IUC_products
ON dbo.products(UniqueColumn_ID)
如果在重复测试之后,两个查询的性能都很好我将用dbo.products
删除第一个以上索引的CLUSTERED PRIMARY KEY
替换AND ((SELECT TOP 1 SP.stock FROM products SP WHERE SP.pcprod_ParentPrd = P.idProduct AND SP.description LIKE N'%(9-12 Months)' AND SP.removed=0) > 0)
的NONCLUSTERED PRIMARY KEY(一个表不能有两个或更多个聚簇)索引)。
[2]我还会重写以下子查询
AND EXISTS(SELECT * FROM products SP WHERE SP.pcprod_ParentPrd = P.idProduct AND SP.description LIKE N'%(9-12 Months)' AND SP.removed=0 AND SP.stock > 0)
因此:
CREATE NONCLUSTERED INDEX IX_product_pcprod_ParentPrd_removed_stock
ON dbo.products (pcprod_ParentPrd, removed, stock)
INCLUDE (description)
对于这个子查询,我将创建以下非聚簇索引
[3]
GradientDrawable gradientDrawable=new GradientDrawable();
gradientDrawable.setShape(GradientDrawable.OVAL);
gradientDrawable.setColor(getResources().getColor(R.color.colorAccent));
gradientDrawable.setSize(200,200);
gradientDrawable.setCornerRadius(100);
答案 1 :(得分:0)
此问题是description
列。 idCategory [628]的description
长度比idCategory [494]长。因为您使用的是SP.description LIKE N'%(9-12 Months)'
。 description
的长度太长,然后你慢慢来。
您还在使用ORDER BY P.description Asc
。