我的生产环境中有一个查询需要很长时间才能执行。我没有写这个查询,但我必须找到一种方法来加快它的速度,因为它现在导致了一个很大的性能问题。我需要用Left Join替换NOT IN但不知道如何重写它。现在看起来像是跟随
SELECT TOP 1 IT.ITEMID
FROM (SELECT CAST(ITEMID AS NUMERIC) + 1 ITEMID
FROM Items
WHERE ISNUMERIC(ITEMID) = 1
AND CAST(ITEMID AS NUMERIC) >= 50000) IT
WHERE IT.ITEMID NOT IN (SELECT CAST(ITEMID AS NUMERIC) ITEMID
FROM Items
WHERE ISNUMERIC(ITEMID) = 1)
ORDER BY IT.ITEMID
请建议我如何使用Left Join重写它以获得更好的性能。非常感谢任何帮助/指导。
答案 0 :(得分:6)
试试这个 -
;WITH cte AS
(
SELECT DISTINCT ITEMID =
CASE WHEN ISNUMERIC(ITEMID) = 1
THEN ITEMID
END
FROM Items
)
SELECT TOP 1 ITEMID = ITEMID + 1
FROM cte t
WHERE ITEMID >= 50000
AND NOT EXISTS(
SELECT 1
FROM cte t2
WHERE t.ITEMID + 1 = t2.ITEMID
)
ORDER BY t.ITEMID
答案 1 :(得分:5)
正如评论中所提到的,SQLServer中查询的NOT EXISTS版本通常比LEFT JOIN更快 - 为了完整性,这里有两个版本:
现有查询的左连接变体:
with cte as
(SELECT CAST(it.ITEMID AS NUMERIC) ITEMID
FROM Items
WHERE ISNUMERIC(ITEMID) = 1)
select top 1 i.ITEMID + 1 ITEMID
FROM cte i
LEFT JOIN cte ni ON i.ITEMID + 1 = ni.ITEMID
WHERE i.ITEMID >= 50000 AND ni.ITEMID IS NULL
不存在现有查询的变体:
with cte as
(SELECT CAST(it.ITEMID AS NUMERIC) ITEMID
FROM Items
WHERE ISNUMERIC(ITEMID) = 1)
select top 1 i.ITEMID + 1 ITEMID
FROM cte i
WHERE i.ITEMID >= 50000 AND NOT EXISTS
(SELECT NULL
FROM cte ni
WHERE i.ITEMID + 1 = ni.ITEMID)
答案 2 :(得分:4)
正如@gbn所指出的那样,CAST和谓词上的函数无论如何都会使索引无效,因此将此转换为NOT IN
到LEFT JOIN / IS NULL
或NOT EXISTS
没有意义。 NOT EXISTS
通常在SQL-Server中的性能优于LEFT NULL
。
NOT IN
。
并且ISNUMERIC()
并不总是按照你的想法行事(正如@ Damien_The_Unbeliever在另一条评论中所说的那样。)有些情况下,IsNumeric结果为1但是演员表失败。
因此,理所当然的事情是 - 在我看来 - 在表中添加另一列并将(可以转换的值)转换为数字并将它们存储在该列中。然后你可以在不进行强制转换的情况下编写查询,并且可以使用该列的索引。
如果您无法以任何方式更改表格(通过添加新列或物化视图),那么您可以尝试测试其他答案提供的各种重写。
答案 3 :(得分:4)
我同意@ypercube,理所当然的事情是修复你的架构。
如果由于某种原因这不是一个选项,那么在运行时将整个事物实现到索引的临时表中可能会最好地完成一项糟糕的工作。
CREATE TABLE #T
(
ITEMID NUMERIC(18,0) PRIMARY KEY
WITH ( IGNORE_DUP_KEY = ON)
)
INSERT INTO #T
SELECT CASE WHEN ISNUMERIC(ITEMID) = 1 THEN ITEMID END
FROM Items
WHERE CASE WHEN ISNUMERIC(ITEMID) = 1 THEN ITEMID END >= 50000
SELECT TOP 1 ITEMID+1
FROM #T T1
WHERE NOT EXISTS (SELECT * FROM #T T2 WHERE T2.ITEMID = T1.ITEMID +1)
ORDER BY ITEMID