3

查询一:

SELECT au_lname, au_fname, title 
FROM (SELECT au_lname, au_fname, id FROM pubs.dbo.authors WHERE state = 'CA') as a 
JOIN pubs.dbo.titleauthor ta on a.au_id=ta.au_id 
JOIN pubs.dbo.titles t on ta.title_id = t.title_id

查询 2:

DECLARE @DATASET TABLE ( au_lname VARCHAR(10), au_fname VARCHAR(10), id INT );

INSERT @DATASET SELECT au_lname, au_fname, id FROM pubs.dbo.authors WHERE state = 'CA';

SELECT au_lname, au_fname, title 
FROM @DATASET DATASET as a 
JOIN pubs.dbo.titleauthor ta on a.au_id=ta.au_id 
JOIN pubs.dbo.titles t on ta.title_id = t.title_id

我的假设是,从性能的角度来看,这两个查询彼此并没有太大的不同。查询 2 是否比查询 1 有所改进?

作为旁注,我知道这个例子中的子查询甚至不需要在那里。这是一个简化版本——我正在处理的实际查询要复杂得多。

4

3 回答 3

5

如果您有几行以上的数据,则查询 2 很可能查询 1 差。

  • 您正在SELECT输入数据两次 - 一次进入表变量,再次返回它
  • 表变量通常表现不佳 - 它们没有统计信息或索引,并且与普遍看法相反仍然写入 tempdb 和日志

如果是我,我会在没有派生表的情况下重写第一个查询,这确实是不必要的:

SELECT 
    au_lname
    ,au_fname
    ,title 
FROM 
    pubs.dbo.authors a 
INNER JOIN 
    pubs.dbo.titleauthor ta 
        on a.au_id=ta.au_id 
INNER JOIN 
    pubs.dbo.titles t 
        on  ta.title_id = t.title_id
WHERE 
    a.state = 'CA'

注意 有关表变量和临时表的更多信息,请参阅 Martin Smith 的这个史诗般的答案。

于 2013-06-07T14:50:53.833 回答
1

不,让优化器做它的事。通过引入您自己的临时表/变量,您将带走原本可用的选项。通过准确地告诉它您想要什么(即普通查询),它可以做到最好。通过尝试再次猜测它,您正在将其分解为通常不必要的步骤。

于 2013-06-07T14:53:40.260 回答
1

Query 2 给您带来的唯一好处是能够在表变量中存储额外的数据(例如,如果您的过程生成额外的元数据来支持其目的)。它所付出的代价是能够使用物理表上的任何索引。

于 2013-06-07T14:45:40.513 回答