我正在构建一个整理大量数据的报告,报告的数据已形成为一个在大约2到9秒内运行的视图(这是可以接受的)。我还有一个函数返回一组需要过滤视图的id:
select *
from vw_report
where employee_id in (select id from dbo.fnc_security(@personRanAsID))
安全功能本身在不到一秒的时间内运行。但是当我将上述两者结合起来时,查询需要15分钟。
视图和安全功能都做了相当多的工作,所以最初我认为它可能是锁定,我没有尝试锁定安全功能,但它没有任何区别。
关于我可能出错的地方的任何提示或技巧?
值得注意的是,当我将函数的结果复制到声明的部分内容时:
select *
from vw_report
where employee_id in (123, 456, 789)
速度增加回到2到9秒。
答案 0 :(得分:2)
首先,任何额外的背景都会有帮助...
- 你有视图和功能的代码吗?
- 您是否可以指定用于引用的表的模式和索引?
如果没有这些,建议变得困难,但我会有刺...
1)。您可以将IN子句更改为Join 2)。您可以在视图上指定WITH(NOEXPAND)。
SELECT
*
FROM
vw_report WITH (NOEXPAND)
INNER JOIN
(select id from dbo.fnc_security(@personRanAsID)) AS security
ON security.id = vw_report.employee_id
注意:我先尝试没有NOEXPAND。
另一种选择是,索引的组合和视图的制定使得优化者很难创建一个好的执行计划。根据我上面提到的额外信息,这个可能可以改进。
答案 1 :(得分:0)
由于从vw_report为每一行执行子选择查询而第二个查询没有执行,因此需要花费很多时间。你应该使用类似的东西:
select *
from vw_report r, (select id from dbo.fnc_security(@personRanAsID)) v
where r.employee_id = v.id
答案 2 :(得分:0)
我最终将安全功能的结果转储到临时表中,并在主查询中使用临时表。事实证明这是最快的方法。
e.g:
create table #tempTable (id bigint)
select id
into #tempTable
from dbo.fnc_security(@personRanAsID)
select *
from vw_report
where id in (select id from #tempTable)