2012-07-12 145 views
1

我有两个表,我想加入,他们都有索引我想加入的列。是否仍然有效?

QUERY 1

SELECT * FROM [A] INNER JOIN [B] ON [A].F = [B].F; 

QUERY 2

SELECT * FROM (SELECT * FROM [A]) [A1] INNER JOIN (SELECT * FROM B) [B1] ON [A1].F=[B1].F 

所述第一查询清楚地将利用索引,关于什么第二个? 在括号中的两个选择语句执行后,然后加入会发生,但我的猜测是索引无助于加快查询,因为它几乎是一个新表..

+2

实际上,两个查询都返回相同的结果。 两者都应该使用索引(检查查询计划) 真正的问题是为什么你会想要使用query2? – Jimbo 2012-07-12 20:09:11

+0

“FROM [A]”和“FROM(SELECT * FROM [A])As [A]”是一回事。 – RBarryYoung 2012-07-12 20:23:17

+0

@Jimbo,我将它抽象为一个更简单的例子。因为这两个子查询是在不同阶段构建的,然后组合起来形成一个更大的查询,这就是为什么我有查询2而不是查询1 – y62wang 2012-07-12 21:28:20

回答

5

不执行查询这么彻底为你的建议,其中内查询第一,那么他们的执行结果与外部查询结合使用。优化器会接受您的查询,并会查看许多可能的方式,通过各种连接命令,索引用法等获取数据,并提出一个感觉足够优化的计划。

如果你执行两个查询并查看它们各自的执行计划,我想你会发现它们使用完全相同的执行计划。

下面是一个简单的相同概念的例子。我创建了我的模式,如下所示:

CREATE TABLE A (id int, value int) 
CREATE TABLE B (id int, value int) 

INSERT INTO A (id, value) 
VALUES (1,900),(2,800),(3,700),(4,600) 

INSERT INTO B (id, value) 
VALUES (2,800),(3,700),(4,600),(5,500) 

CREATE CLUSTERED INDEX IX_A ON A (id) 
CREATE CLUSTERED INDEX IX_B ON B (id) 

然后运行您提供的查询。

SELECT * FROM A INNER JOIN B ON A.id = B.id 
SELECT * FROM (SELECT * FROM A) A1 INNER JOIN (SELECT * FROM B) B1 ON A1.id = B1.id 

中生成的计划是这样的:

enter image description here

其中,你可以看到,无论是利用指数。

+0

这是更复杂查询的情况吗?如果我有两个复杂的子查询与他们内部的联合/条件,当我对这两个子查询执行连接时,我不太确定它是否会给出使用索引的相同执行计划。所以我只能依靠优化器来做出这个决定? – y62wang 2012-07-12 21:33:03

+0

是的,无论查询有多复杂,它都由优化器决定如何获取数据。除非您决定使用提示,但通常不推荐用于生产环境。 – 2012-07-13 12:28:22

4

机会很高, SQL Server查询优化器将能够检测到查询2实际上与查询1相同并使用相同的索引方法。

是否发生这种情况取决于很多因素:您的表格设计,表格统计信息,查询的复杂程度等。如果您想确切地知道,请让SQL Server查询分析器向您显示执行计划 。这里有一些链接,以帮助您入门:

2

SQL Server使用predicate pushing(又名谓词下推)将查询条件尽可能移向源表。它不会按照你加括号的顺序来做任何事情。优化器使用复杂规则 - 本质上是一种几何 - 确定查询的,并根据需要重新调整对数据的访问权限,以获得最佳性能,同时仍返回相同的最终集合您的查询逻辑需要的数据。

当查询变得越来越复杂时,就是这一点,优化程序无法详尽搜索所有可能的执行计划,最终可能会导致次优。然而,你几乎可以假设像你这样简单的案例总是要被“透视”并优化掉。

所以答案是,仿佛两个查询合并你应该得到同样出色的表现。现在,如果你是加盟的值是复合材料,这是他们的计算或级联的结果,那么你几乎可以肯定不会让你想,这将使该指数有用的谓语推,因为服务器将不会或不能根据部分字符串或执行反向算术或其他操作之后进行查找。

我建议,今后,问这样的问题在这里之前,你只需检查执行计划为自己验证它使用的指标?你可以通过一些实验来回答你自己的问题。如果你仍然有问题,然后来邮寄,但同时尝试做一些自己的研究,作为尊重正在帮助你的人的一种信号。

要查看执行计划,请在SQL Server Management Studio(2005或更高版本)或SQL查询分析器(SQL 2000)中单击菜单栏上的“显示执行计划”按钮,运行查询并切换到底部的选项卡显示执行计划的图形版本。有些小玩意儿将鼠标悬停在各个部分上会很快显示哪些索引正在哪些表上使用。

但是,如果事情并不像你期望的那样,不会自动认为服务器是犯了一个错误。它可能会决定不使用索引扫描主表的成本更低 - 并且它几乎总是正确的。有很多原因可以使得扫描成本更低,其中一个是非常小的表格,另一个是服务器统计推测它将不得不返回的行数超过表格的很大一部分。

0

这两个查询相同。第二个查询将在转换过程中与第一个查询相同。

不过,如果你有特殊的要求,我会建议你把整个code.Then这将是很容易回答你的问题。