2012-08-22 42 views
0
 
    TABLE T1     TABLE T2 
    +----+------------+   +----+------------+ 
    | Id | Name  |   | Id | Some_Data | 
    +----+------------+   +----+------------+ 
    | |   |   | |   | 

查询1:哪个查询更合适?

SELECT * FROM T1 JOIN T2 ON T1.Id=T2.Id WHERE T1.Id=1001 

QUERY2:

SELECT * FROM T1 JOIN T2 ON T1.Id=T2.Id WHERE T2.Id=1001 

如果T2为10万行,其中只有100具有编号= 1001,上述查询的这是更合适的一个使用?或者,这并不重要,因为SQL Server足够聪明,知道该做什么最好?

谢谢。

+8

这可能取决于表上的索引。另外,你有没有看过2个查询的执行计划?他们展示了什么? –

回答

2

如果指数上都可用的ID列联接将使用散列的一些变种和表的顺序是不相关

如果Index不可用的话很有道理有左边的where子句(我有一种感觉,根据参与表的统计数据,MSSQLSERVER将智能地自行交换订单)

1

什么:

SELECT * FROM T1 JOIN T2 ON (T1.Id=T2.Id AND T2.Id=1001) 

他们说把T2.Id=1001将过滤,然后选择行,但把它放在Where T2.Id=1001会首先选择条件T1.Id=T2.Id所有行,然后应用T2.Id=1001

+0

as @astander评论了很多性能取决于索引 – TheVillageIdiot

+2

在考虑WHERE子句之前,几乎可以肯定所有行都会被连接。优化器将能够将'WHERE'子句谓词向下推送到表/索引seek/scan,只有匹配该谓词的行才会进入连接运算符。 –

+0

@Damien_The_Unbeliever它看起来很明显,优化器不会允许这个愚蠢的事情。但我直到现在才将它看成是一种表面价值,但认为这是一种很好的做法,并且会在我能够尽早在链条中设定标准时坚持下去。 – TheVillageIdiot

1

按照我QUERY2是更合适。

SELECT * FROM T1 JOIN T2 ON T1.Id=T2.Id WHERE T2.Id=1001 

这将限制返回的行所以这将是更有效,仍可以检查the docs

1

我想你需要有非聚集索引两个id列,然后使用上述查询中的任何一个来快速获得结果。否则,我认为您无法在上述任何查询中更快地处理查询。索引必须在这种情况下进行。

1

我认为这里的问题是,连接数以百万计的行总是第一个,只有在这之后才会出现where子句。 试试这个,而不是你的表格,看看在消息选项卡中的时间戳:

declare @t1 table (id int, name nvarchar(100)); 
declare @t2 table (id int, name nvarchar(100)); 

insert into @t1 (id, name) values (1, 'a') 
insert into @t1 (id, name) values (2, 'b') 
insert into @t1 (id, name) values (3, 'c') 
insert into @t1 (id, name) values (4, 'd') 
insert into @t1 (id, name) values (5, 'e') 

insert into @t2 (id, name) values (5, 'e') 
insert into @t2 (id, name) values (5, 'f') 
insert into @t2 (id, name) values (5, 'g') 
insert into @t2 (id, name) values (5, 'h') 
insert into @t2 (id, name) values (5, 'i') 
insert into @t2 (id, name) values (6, 'j') 
insert into @t2 (id, name) values (7, 'k') 
insert into @t2 (id, name) values (8, 'l') 

print getdate() 
-- this is your select statement 
select * from @t1 t1 inner join @t2 t2 on t1.id = t2.id where t1.id = 5; 
print getdate() 
-- this is your select statement 
select * from @t1 t1 inner join @t2 t2 on t1.id = t2.id where t2.id = 5; 
print getdate() 
-- this is done with a WITH to do the filtering beforehand 
-- of course, indices will affect the performance a lot 
with w2 (id, name) as (select * from @t2 where id = 5) 
select * from w2 inner join @t1 t1 on w2.id = t1.id 
print getdate() 

当然,无视我的样本数据和WITH子句中使用你的表像。

+0

查询引擎实际上并不需要按照它的编写顺序执行查询 – AakashM

+0

很明显,这是优化程序的用途。但我有点惊讶:我发誓我在某处读到连接具有更高的优先级,然后服务器首先创建连接,然后过滤结果。现在我看看我的代码的执行计划,对于最后3条语句而言,无论是否带有WITH,都是一样的。再次,我感到困惑。并且必须找到信息来源... –

1

怎么样先过滤,然后加入

SELECT * FROM T1 
JOIN (SELECT Id FROM T2 WHERE T2.Id=1001) T2 
ON T1.Id=T2.Id 
0

首先,这是我现在面临一个真正的问题,而数据库是由第三方软件产品,在那里我有只读访问产生一些报道。

从所有非常有帮助的回答者,我认为没有直截了当的答案。我从帖子中得出结论:首先确保键控列被编入索引,然后让SQL Server负责优化。

感谢所有。