我有一个查询优化问题。假设有一张包含所有发票的表格。使用 TVP(表值参数)我想通过提供 1..n 个 id 来选择少数记录,或者通过提供值为 -1 的单个 id 返回所有记录。
DECLARE @InvoiceIdSet AS dbo.TBIGINT;
INSERT INTO @InvoiceIdSet VALUES (1),(2),(3),(4)
--INSERT INTO @InvoiceIdSet VALUES (-1)
SELECT TOP 100
I.Id ,
Number ,
DueDate ,
IssuedDate ,
Amount ,
Test3
FROM dbo.Invoices I
--WHERE EXISTS ( SELECT NULL
-- FROM @InvoiceIdSet
-- WHERE I.Id = ID
-- OR ID = -1 )
--CROSS APPLY @InvoiceIdSet s WHERE i.Id = s.ID OR s.ID = -1
JOIN @InvoiceIdSet S ON S.ID = I.Id OR S.ID=-1
无论我使用哪种选择方法,查询的执行效率都很高,直到我开始使用 OR 运算符,此时它开始需要很长时间才能返回少量记录,但所有记录的返回速度都非常快。
任何指示和建议将不胜感激。
第一个计划没有 OR,第二个计划有 OR。
更新: 在摆弄了不同的选项之后,无论参数数量如何,我都认为这个解决方案是性能最快的。
首先更改 UserDefinedTableType 以包含主键索引:
CREATE TYPE [dbo].[TBIGINT] AS TABLE(
[ID] [bigint] NOT NULL PRIMARY KEY CLUSTERED
)
select 语句现在看起来像这样:
SELECT TOP 100
I.Id ,
Number ,
DueDate ,
IssuedDate ,
Amount ,
Test3
FROM dbo.Invoices I
WHERE I.ID IN ( SELECT S.ID
FROM @InvoiceIdSet S
WHERE S.ID <> -1
UNION ALL
SELECT S.ID
FROM dbo.Invoices S
WHERE EXISTS ( SELECT NULL
FROM @InvoiceIdSet
WHERE ID = -1 ) )
计划变得更大,但性能几乎保持不变,在少数(第一个计划)和所有(第二个计划)记录之间。
正如您所看到的,这些计划现在是相同的,并且可以在不到一秒的时间内从 1M 行中返回所需的记录。
我很想听听社区对此解决方案的看法。
感谢大家的帮助。