性能:两个查询之间有什么区别

时间:2014-02-21 05:42:09

标签: sql sql-server-2008

我原本写过以下内容

SELECT t1.TransactionNumber
FROM t1
    JOIN
    (
          SELECT MAX(id) id
          FROM t1
          WHERE Period BETWEEN '01-11-2013' and '01-12-2014'
          GROUP BY AccountNumber
    ) t2
        on t1.id= t2.id

但它太慢了。花了大约20秒,所以作为测试,我将其更改为以下

 SELECT MAX(id) AS id
 INTO #t2
 FROM t1
 WHERE Period BETWEEN '01-11-2013' and '01-12-2014'
 GROUP BY AccountNumber

 SELECT t1.id 
 FROM t1
    JOIN #t2 t2
        ON t1.id= t2.id

第二个查询只需1秒即可运行。第二个查询使用PK密钥执行索引查找,而第一个密钥执行扫描。

注意:id是聚集在t1表上的主键。

7 个答案:

答案 0 :(得分:1)

这是猜测,但可能是因为主键上的统计信息不适合您。如果查询优化器认为您只是从内部联接返回10条记录,而是返回100,则它会溢出内存缓冲区,然后最终必须将子查询的结果写入磁盘。如果您发布查询执行计划结果,它应该变得非常明显。

答案 1 :(得分:0)

你不能把所有的条件都放在ON部分吗?

SELECT t1.id
FROM t1
    JOIN
    (
          SELECT id
          FROM t1
          WHERE <condition>
    ) t2
        on t1.id = t2.id;

转化为

SELECT t1.id
FROM t1
     JOIN t1 as t2
        ON t1.id = t2.id AND <condition>

更新:

Retrieving the last record in each group 该链接显示如何检索组中的最后一条记录。 SQL正在关注

SELECT m1.*
FROM messages m1 LEFT JOIN messages m2
 ON (m1.name = m2.name AND m1.id < m2.id)
WHERE m2.id IS NULL;

您可以使用此而不是group by

答案 2 :(得分:0)

这两个查询之间的主要区别在于第二个查询是严格查询索引!!!

SELECT t1.TransactionNumber
FROM t1
JOIN
(
      SELECT MAX(id) id
      FROM t1
      WHERE Period BETWEEN '01-11-2013' and '01-12-2014'
      GROUP BY AccountNumber
) t2
    on t1.id= t2.id

查询transactionNumber列因此无法使用表上的undex,第二个查询仅使用ID。这将使世界变得与众不同。

答案 3 :(得分:0)

连接消耗大量资源,计算结果需要再次与表重新连接,因此需要很长时间。当您使用临时表时,结果已经存储在临时表中,因此连接条件比子查询运行得更快。

答案 4 :(得分:0)

试试这个:

SELECT t1.TransactionNumber t1 WHERE t1.id = (SELECT MAX(id) id FROM t1 WHERE Period BETWEEN '01-11-2013' and '01-12-2014' GROUP BY AccountNumber)

答案 5 :(得分:0)

通常,性能(尽管需要更多代码)更好地显式声明列和数据类型而不是SELECT..INTO。这可能会更快:

CREATE TABLE #t2
    (
    id INT
    );
INSERT INTO #t2(id)
VALUES
    (
    SELECT MAX(id)
    FROM t1
    WHERE Period <= '01-11-2013' 
    AND Period > '01-12-2014'
    GROUP BY AccountNumber
    );
 SELECT t1.id 
 FROM t1
    JOIN #t2 t2
        ON t1.id= t2.id

答案 6 :(得分:0)

不同之处在于,在第一个查询中,引擎不知道t2中的结果数(我假设与t1计数相比数量相对较小,但SQL服务器事先并不知道)。 因此执行计划以t1开头(循环大量行)。 但是在第二个查询中,t2已经有X个记录,这些记录在执行查询的第二部分之前对于引擎是已知的。 因此在该查询中,SQL引擎将使用t2开始执行(SCAN t2因为它很小),并且对于t2中的每个键,它将在t1中执行索引搜索。