这些查询中哪一个对性能最好?有时,我想知道短脚本是否真的是最好的关注对象。这些脚本执行相同的任务。使用左联接,我只需几行就可以实现我想要的结果。但后来我尝试了一个更长的脚本,使用工会。哪一种是最好的方法?两者之间:
SELECT p.productID, p.product, C.color, C.colorID, S.size, S.sizeID, q.qty From quantities q
INNER join products P ON p.productID = q.productID
LEFT JOIN colors C ON C.colorID = q.colorID
LEFT JOIN sizes S ON S.sizeID = q.sizeID
--WHERE q.productID = @productID
这是:
SELECT p.productID, p.product, C.color, C.colorID, S.size, S.sizeID, q.qty From quantities q
inner join products P ON p.productID = q.productID
INNER JOIN colors C ON C.colorID = q.colorID
INNER JOIN sizes S ON S.sizeID = q.sizeID
--WHERE q.productID = @productID
UNION
SELECT p.productID, p.product, NULL, NULL, S.size, S.sizeID, q.qty From quantities q
inner join products P ON p.productID = q.productID
INNER JOIN sizes S ON S.sizeID = q.sizeID
WHERE /* q.productID = @productID AND */ q.sizeID IS NOT NULL AND q.colorID IS NULL
UNION
SELECT p.productID, p.product, C.color, C.colorID, NULL, NULL, q.qty From quantities q
inner join products P ON p.productID = q.productID
INNER JOIN colors C ON C.colorID = q.colorID
WHERE /* q.productID = @productID AND */ q.colorID IS NOT NULL AND q.sizeID IS NULL
UNION
SELECT p.productID, p.product, NULL, NULL, NULL, NULL, q.qty From quantities q
inner join products P ON p.productID = q.productID
WHERE /* q.productID = @productID AND */ q.colorID IS NULL AND q.sizeID IS NULL
编辑:
Server解析和编译时间: CPU时间= 32 ms,运行时间= 65 ms。(10排(S)受影响)表“尺寸”。扫描计数1,逻辑读取21,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0.桌子的颜色。扫描计数1,逻辑读取21,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0.表“产品”。扫描计数0,逻辑读取20,物理读取1,先读0,lob逻辑读取0,lob物理读取0,lob预读读取0.表“数量”扫描计数1,逻辑读取2,物理读取1,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0.Server执行时间: CPU时间=0 ms,运行时间= 12 ms。(10排(S)受影响)表“产品”。扫描计数0,逻辑读取20,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0.表“数量”扫描计数4,逻辑读取8,物理读取0,先读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0.桌子‘工作表’扫描计数0,逻辑读取0,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0.桌子的尺寸。扫描计数0,逻辑读取18,物理读取0,先读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0.桌子的颜色。扫描计数0,逻辑读取12,物理读取0,先读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0.Server执行时间: CPU时间=0 ms,运行时间=0 ms。
在我看来,这是对性能最好的第二个查询,更大的联合查询。
你们中有人知道为什么会发生这样的事情吗?还是我必须提供更多的信息(表格信息之类的东西)?
执行计划:
谢谢!
发布于 2013-11-02 14:37:10
有时,我想知道短脚本是否真的是最好的关注对象。
脚本的大小与查询的执行效率无关。更紧凑的语句在编译方面可能会消耗更少的资源,但是(重新)编译在活动系统中通常是罕见的。
但是,更少的表访问通常是可取的,这确实会导致更紧凑的代码。
一般说来,较小的执行计划会产生更好的结果,而较低的估计成本则会产生更好的结果。尽管如此,这也是一种高度的情境化。在某些情况下,特别是费用估计数可能相差甚远。测量实际执行时间很重要,因为在一天结束时,这才是最重要的。
使用左联接,我只需几行就可以实现我想要的结果。但后来我尝试了一个更长的脚本,使用工会。哪一种是最好的方法?
首先,我们需要知道在真正的系统中这些表中有多少数据。现在,很少有人使用STATISTICS TIME
性能指标来确定赢家--返回的结果将由查询执行以外的其他因素主导。有了更多的数据,计划很可能会改变,因此这里的比较毫无意义。
话虽如此,从逻辑的角度来看查询计划,第一个是赢家。
您可以看到,quantities
的聚集索引扫描在第一个计划中显示一次,而在第二个计划中显示四次。第二个计划还包含了使用UNION
s的另一种昂贵的不同类型(这个操作符可以通过使用UNION ALL
s来消除,这不会改变结果)。
第一个查询也可能得到改进,方法是在colors
和sizes
表上获取索引查找,而不是进行表扫描。尝试哈希匹配计划也是值得的(当quantities
和products
更大时,您可能会看到这一点),但是对于这么小的表,启动成本可能会太高而没有好处。
我建议您运行每个要在循环中测试10,000+时间的语句,计算出平均执行时间,然后进行比较。
发布于 2013-11-01 16:58:00
没有了整个数据库,这是一个很难回答的问题。我能说的是:你可以测试你自己。
如果您使用“设置统计时间”,或者使用
DECLARE @StartTime DATETIME = GETDATE()
/Some Query Here/
SELECT 'Total Run Time Query 1: ' + CAST(DATEDIFF(MS,@StartTime,GETDATE())
SET @StartTime = GETDATE()
/Some Other Query Here/
SELECT 'Total Run Time Query 2: ' + CAST(DATEDIFF(MS,@StartTime,GETDATE())
您可以获得查询执行时间。
对于I/O,可以使用SET STATISTICS IO并运行查询。
另一种方法是启动分析器并捕获查询跟踪,这也会给出详细信息。
使用这些方法,您可以测试需要测试的任何东西,并且是我在调优查询时使用的方法。一旦得到结果,您就可以根据什么是重要的、总体运行时间、磁盘IO或cpu时间来决定哪个更快。在不同的系统中,我发现更快并不总是意味着时间。
发布于 2013-11-02 10:47:47
您不应该在第二个查询中使用UNION ALL
而不是UNION
吗?
结果集看起来是不同的。它可能会从第二个计划中删除一个或多个操作(可能是排序)。
关于这个问题:对于我来说,最基本的规则就是尽可能少地处理你所要处理的数据集。我倾向于避免外部加入这只是开始编写查询时的第一条经验规则,显然存在大量异常。。
我也同意..。您使用的测试数据太小了。
https://dba.stackexchange.com/questions/52668
复制相似问题