2011-12-01 95 views
0

我正在構建一個整理大量數據的報告,報告的數據已成形爲一個視圖,該視圖在大約2到9秒內運行(這是可以接受的)。我還有一個函數返回一組需要過濾視圖的ID:SQL查詢速度

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

這很難回答,如果我們不知道你正在使用(Oracle,MySQL等,SQL服務器和PostgreSQL,SQLite的...)和什麼RDBMS的版本是什麼RDBMS。它們的SQL實現有所不同,有些功能可以用來提高查詢效率。 – Benoit

回答

0

我最終將安全功能的結果轉儲到臨時表中,並在我的主查詢中使用臨時表。被證明是最快的方法。

例如爲:

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) 
0

由於從vw_report中爲每一行執行子選擇查詢,而第二個查詢不執行,所以需要很多時間。你應該使用類似:

select * 
from vw_report r, (select id from dbo.fnc_security(@personRanAsID)) v 
where r.employee_id = v.id 
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第一。

另一種選擇是,索引和視圖組合的組合使優化器很難創建一個良好的執行計劃。隨着我所要求的額外信息,這可能是可以改進的。

+0

注意:NOEXPAND部分是MS SQL Server。其他RDBMS可能有類似的選項。 – MatBailie