返回首页


讨论如何加入显著优于子查询,以及如何时或条件,这是更为明显。
SQL查询,可以书面方式和功能上等同,但显著不同的速度明智的。一个很好的例子是填充数字表的使用。交叉联接,被设定为基础的,是更为有效。在这个岗位后插入报表依赖于一个表的存在??代码>数字??这是用来代替学生表。在这里,这AOS代码从十字架上拉加入后[这只需几秒钟,而不是一分多钟,像运行while循环 - 交叉连接有一个SQL开发]??

CREATE TABLE numbers (num INT)

 

----- Use a table variable 

DECLARE @numbers TABLE

(

      num INT

) 

 

----- Populate a table with numbers 0 to 9

DECLARE @counter INT

SET @counter = 0

 

While @counter < 10

BEGIN

      INSERT INTO @numbers VALUES(@counter)

      SET @counter = @counter + 1

END

 

INSERT INTO numbers (num)

SELECT 

(

      n100000place.num*100000 +

      n10000place.num*10000 +

      n1000place.num*1000 +

      n100place.num*100 + 

      n10place.num*10 + 

      n1place.num

) AS 'number'

FROM @numbers n1place 

CROSS JOIN @numbers n10place

CROSS JOIN @numbers n100place

CROSS JOIN @numbers n1000place

CROSS JOIN @numbers n10000place

CROSS JOIN @numbers n100000place

WHERE n100000place.num < 8 -----  < 800000

ORDER BY NUMBER

今天,我想谈谈子查询和或在SQL语句中条件,AOD。在讨论特定的查询,让AOS成立与一些虚拟的数据测试表。对于这一点,我AOM向表中插入一个显著的行数[400万],使任何性能问题变得更加明显,他们会比琐碎的数据量。{C}
此表是我们在波士顿公立学校学生的测试结果存储到一个表的结​​构和规模相似。使用StudentTestData表,让AOS说,我们需要编写一个查询来获取符合下列条件的学生名单:
  Got over a 10 on test FFFBBBDD AND over a 20 on test FFFRRRDD

    AND

  Got over a 16 on test CCCMMMDD AND over a 30 on test AAABBBCC

    AND

  Got over a 25 on test AAABBBDD

在这种情况下,所有5个测试成绩要求必须得到满足。
这里有两个查询返回结果,就加入第一和第二子查询。我Äôve使用左侧稍作修改,因为我,AOM会后作出的要求,在后?加入以下查询,内部联接做工精细。
-- Join-based query.  3 seconds the first time, < 1 seconds after that.  

-- SQL Server was able to determine a good execution plan to speed up the query. 

SELECT DISTINCT Numbers.num FROM Numbers

LEFT JOIN StudentTestData TestAAABBBCC 

ON TestAAABBBCC.StudentNumber = Numbers.num AND TestAAABBBCC.testid = 'AAABBBCC'

LEFT JOIN StudentTestData TestFFFBBBDD 

ON TestFFFBBBDD.StudentNumber = Numbers.num AND TestFFFBBBDD.testid = 'FFFBBBDD'

LEFT JOIN StudentTestData TestFFFRRRDD 

ON TestFFFRRRDD.StudentNumber = Numbers.num AND TestFFFRRRDD.testid = 'FFFRRRDD'

LEFT JOIN StudentTestData TestCCCMMMDD 

ON TestCCCMMMDD.StudentNumber = Numbers.num AND TestCCCMMMDD.testid = 'CCCMMMDD'

LEFT JOIN StudentTestData TestAAABBBDD 

ON TestAAABBBDD.StudentNumber = Numbers.num AND TestAAABBBDD.testid = 'AAABBBDD'

WHERE

-- Condition 1

(

	(TestFFFBBBDD.TestScore > 10 AND TestFFFRRRDD.TestScore > 20)

	AND

	(TestCCCMMMDD.TestScore > 16 AND TestAAABBBCC.TestScore > 30)

)

-- Condition 2

AND

(

	TestAAABBBDD.TestScore > 25

)

 

-- Here's a query that returns the same result but uses subqueries instead of joins:

-- 5 seconds the first time, 5 seconds after that. 

-- No apparent improvement can be made from the execution plan.

SELECT DISTINCT Numbers.num FROM Numbers

WHERE 

(

     (

	num IN (SELECT studentNumber FROM StudentTestData _

		WHERE TestScore > 10 AND testid = 'FFFBBBDD')

	AND num IN(SELECT studentNumber FROM StudentTestData _

		WHERE TestScore > 20 AND testid = 'FFFRRRDD')

     )

     AND

     (

	num IN (SELECT studentNumber FROM StudentTestData _

		WHERE TestScore > 16 AND testid = 'CCCMMMDD')

	AND num IN(SELECT studentNumber FROM StudentTestData _

		WHERE TestScore > 30 AND testid = 'AAABBBCC')

     )

)

AND

(

              num IN (SELECT studentNumber FROM StudentTestData _

		WHERE TestScore > 25 AND testid = 'AAABBBDD')

)

正如我暗示将{A1},赞成加入为基础的查询结果清楚的情况下。虽然速度差wasn,AOT为第一次运行的查询太显著[5秒3秒]相比,差成为后续查询运行的重要得多。 SQL Server中出现节能比子查询基于查询的加入为基础的查询执行计划要好得多。
,AOS说,我们把几个或进入要求的条件。 OR条件将真正说明为什么加入为基础的版本是优于的。这里的新要求:
学生人数符合以下两个条件之一的学生提供了一个清单:
Condition 1:

  Got over a 10 on test FFFBBBDD OR over a 20 on test FFFRRRDD

    AND

  Got over a 16 on test CCCMMMDD OR over a 30 on test AAABBBCC

Condition 2:

  Got over a 25 on test AAABBBDD

从SQL查询的角度看,,查询以上的几乎是相同的的,只是我们需要改变或在少数情况下,添加括号在需要的时候,所以优先级规则相匹配的要求。此外,左连接的情况下使用一些学生didn,AOT测试[使用内部联接,从结果中删除的学生,如果他们不采取所有5个测试]。
,只要加入"或"条件的要求,暴涨的加入为基础的查询和子查询版本之间的时间差。虽然加入为基础的查询速度稍慢,子查询版本没,AOT完成。其中一晚,我Äôll让子查询的版本上运行的通宵需要多长时间。

回答

评论会员:理查德布雷特 时间:2012/01/27
什么索引StudentTestData表上吗?如果你有一个"StudentNumber"字段的索引,然后尝试一个相关子查询子查询的方法,而不是和测试方法#3的性能。正如其他人指出,不同的SQL引擎优化程序将处理不同的查询,所以这是非常MS - SQL的具体
评论会员:。oggenok 时间:2012/01/27
你的结论与子查询的连接MS SQL Server的唯一有效的。我复制你的例子有4万记录在Oracle数据库上,它的乐趣,Firebird数据库。既不遭受有辱人格的表现,你经历与SQL Server。

一遍又一遍,我已经看到了这种说法:"使用,而不是子查询联接,因为他们的规模更好"。在一般情况下,它的垃圾。事实是,微软有一个相当马虎的执行子查询。
  ;
让我建议从标题中的变化"的子查询的效率... ..." "在MS SQL Server中的子查询Defeciency ... ..."


关于
顺便说一句
StudentTestData.TestScore为VARCHAR(3)的声明似乎是一个奇怪的选择。什么错误的INT
评论会员:?安德鲁Zwicker 时间:2012/01/27
感谢你的反馈,oggenok。

波士顿公立学校使用的MS SQL Server,所以我看到的东西,通过该镜头,通过更加的ANSI标准的SQL镜头。熟悉自己在某一点上,我将更好地与各种数据库产品之间的差异,如果我是永远移动到Oracle环境中[例如],我可能采取子查询的使用在一定程度上

此外,在波士顿公立学校,我们已经从大型机时代的一些数据类型怪癖。其中之一是使用的varchar和char等领域的其他数据类型可能更合适。对于这个特定的表,我们有一些字母为基础的测试分数会至少有一小部分的测试
多年