“或”会降低查询性能,因为优化程序必须同时评估这两种情况。在复杂查询中,由于连接和繁重的表,评估两个条件变得非常昂贵。那么什么是“Or”运算符的替代品。我们每次都使用UNION吗?然后两次运行相同的复杂查询呢?相反,它也很昂贵。
修改
在下面的示例中,使用了六个表,它们每个都有超过100000个记录。 或运算符位于 ccm.cID = 1001 和(ma.coID = 2 AND ma.cID = 1001)之间。要获取记录,优化程序必须评估这两个条件。 :
SELECT dep.*
FROM dep with (NOLOCK)
JOIN ma with (NOLOCK) ON dep.mID = ma.mID
LEFT JOIN ccm with (NOLOCK) ON ccm.cID = dep.cID
LEFT JOIN ctm with (NOLOCK) ON ctm.cID = dep.cID
LEFT JOIN cptgm with (NOLOCK) ON cptgm.cID = dep.cID
WHERE ma.mtID = 3
AND dep.del = 0 AND dep.pub = 1
AND (ccm.cID = 1001 OR (ma.coID = 2 AND ma.cID = 1001))
AND ctm.tID = 2
AND cptgm.ptgID IN (SELECT ptgID FROM psptgm WHERE psID = 145214
AND ib = 1)
如果我们将查询分成两部分,一次只有一个条件,然后将其与 UNION 结合,则性能会因为两次执行而降低。
答案 0 :(得分:1)
在不了解或更改数据模型的情况下,您可以做很多事情
让我们一步一步地在这个例子中找到一个小优化:
首先将子查询拉出到连接,我相信这个更改会在某些版本的SQL上提供更好的性能。它也使查询更清晰。
SELECT dep.*
FROM dep with (NOLOCK)
JOIN ma with (NOLOCK) ON dep.mID = ma.mID
LEFT JOIN ccm with (NOLOCK) ON ccm.cID = dep.cID
LEFT JOIN ctm with (NOLOCK) ON ctm.cID = dep.cID
LEFT JOIN cptgm with (NOLOCK) ON cptgm.cID = dep.cID
JOIN psptgm with (NOLOCK) ON cptgm.ptgID = psptgm.ptgID and psptgm.ib = 1 and psptgm.psID = 145214
WHERE ma.mtID = 3
AND dep.del = 0
AND dep.pub = 1
AND (ccm.cID = 1001 OR (ma.coID = 2 AND ma.cID = 1001))
AND ctm.tID = 2
我也喜欢这样写(我认为更清楚):
SELECT dep.*
FROM dep with (NOLOCK)
JOIN ma with (NOLOCK) ON dep.mID = ma.mID and ma.mtID = 3
LEFT JOIN ccm with (NOLOCK) ON ccm.cID = dep.cID
LEFT JOIN ctm with (NOLOCK) ON ctm.cID = dep.cID AND ctm.tID = 2
LEFT JOIN cptgm with (NOLOCK) ON cptgm.cID = dep.cID
JOIN psptgm with (NOLOCK) ON cptgm.ptgID = psptgm.ptgID and psptgm.ib = 1 and psptgm.psID = 145214
WHERE dep.del = 0
AND dep.pub = 1
AND (ccm.cID = 1001 OR (ma.coID = 2 AND ma.cID = 1001))
这使得仅连接修饰符与where子句更清晰。
现在很容易看到主要选择中的常用部分并将其拉出(从而减少了或子句所做的检查次数并提高了性能):
WITH prequery AS
(
SELECT dep.*
FROM dep with (NOLOCK)
LEFT JOIN ctm with (NOLOCK) ON ctm.cID = dep.cID AND ctm.tID = 2
LEFT JOIN cptgm with (NOLOCK) ON cptgm.cID = dep.cID
JOIN psptgm with (NOLOCK) ON cptgm.ptgID = psptgm.ptgID and psptgm.ib = 1 and psptgm.psID = 145214
WHERE dep.del = 0 AND dep.pub = 1
)
SELECT dep.*
FROM prequery with (NOLOCK)
JOIN ma with (NOLOCK) ON dep.mID = ma.mID and ma.mtID = 3
LEFT JOIN ccm with (NOLOCK) ON ccm.cID = dep.cID
LEFT JOIN cptgm with (NOLOCK) ON cptgm.cID = dep.cID
WHERE ISNULL(ccm.cID,0) = 1001 OR (ma.coID = 2 AND ma.cID = 1001)