Sql 昂贵的左连接到空子查询?
这里的SQL新手试图更好地理解调度和高效的代码编写。我正在运行一个性能非常差的查询,我不明白为什么。我们正在使用SQL Server 2012 当我只运行子查询(别名为“te”)时,它运行不到一秒钟,返回零行(这是我所期望的)。但是当我运行完整的查询时,需要花费一分钟以上的时间。空集上的内部联接或左外部联接不总是返回空集吗?那么,当子查询不返回任何结果时,DB引擎不应该发现它不需要执行任何这些连接吗 有没有关于如何更好地优化的建议?将来编写SQL时,我应该记住哪些最佳实践Sql 昂贵的左连接到空子查询?,sql,sql-server,join,subquery,Sql,Sql Server,Join,Subquery,这里的SQL新手试图更好地理解调度和高效的代码编写。我正在运行一个性能非常差的查询,我不明白为什么。我们正在使用SQL Server 2012 当我只运行子查询(别名为“te”)时,它运行不到一秒钟,返回零行(这是我所期望的)。但是当我运行完整的查询时,需要花费一分钟以上的时间。空集上的内部联接或左外部联接不总是返回空集吗?那么,当子查询不返回任何结果时,DB引擎不应该发现它不需要执行任何这些连接吗 有没有关于如何更好地优化的建议?将来编写SQL时,我应该记住哪些最佳实践 INSERT INTO
INSERT INTO #target_events
SELECT p.polyname,
bp.PurposeAbbr,
s.schid,
s.ldate,
es.EvStrId,
es.evstrname,
e.evparent,
e.evid,
e.Lat / 1000000.0 AS 'Lat',
e.Lon / 1000000.0 AS 'Lon',
e.eta,
e.etd,
e.PassOn,
e.PassOnBoard,
e.Activity,
e.SchedStatus,
e.EvClass
FROM
(
SELECT te.*
FROM #target_events te
LEFT OUTER JOIN #target_events te2 ON te2.schid = te.schid
AND te2.EvStrId = te.EvStrId
AND te2.EvParent = te.EvParent
AND te2.Activity != te.Activity
WHERE te.Activity IN(0, 1)
AND te.SchedStatus = 3
AND te2.EvId IS NULL
) te -- This subquery runs in under 1 second and returns zero rows
INNER JOIN events e ON e.schid = te.schid
AND e.EvStrId = te.EvStrId
AND e.EvParent = te.EvParent
AND e.Activity != te.Activity
INNER JOIN eventstrings es ON es.evstrid = e.evstrid
AND es.schid = e.schid
INNER JOIN schedules s ON s.schid = e.schid
LEFT OUTER JOIN clients c ON c.clientid = e.clientid
LEFT OUTER JOIN address a ON a.addrid = c.clientid
AND a.AddrType = 'CH' -- Client Home addresses.
LEFT OUTER JOIN polygons p ON p.polyid = a.jurispolyid
LEFT OUTER JOIN booking b ON b.bookingid = e.bookingid
LEFT OUTER JOIN bookingpurpose bp ON bp.purposeid = b.purposeid; -- These joins take a long time...
只有当左表为空时,空集合上的左联接才为空。这是它的本质。当优化器构建一个执行计划时,它可能会以多种方式转换原始查询,包括更改连接的顺序。它无法确定查询的哪一部分此时将返回零行,因此在构建计划时无法考虑这一点。如果您需要解决性能问题,请学习阅读执行计划。这是b.purposeid索引吗?当您无法找出查询运行缓慢的原因时,您应该做的第一件事是查看执行计划。作为一个实验,尝试在te.*之前添加TOP 4000000000。它的行数比以往任何时候都多,TOP命令将强制SQL在尝试连接其他任何内容之前处理te和te2上的连接。由于临时文件的行估计可能有点冒险,所以这可能会神奇地欺骗SQL生成更好的计划。