2014-11-03 59 views
1

我有以下的功能,我想在SQL查詢中使用哪個(Postgres的9.3):糟糕的表現上存在子句在功能

SELECT * FROM test_table tt WHERE has_access(tt.id, tt.login) 

CREATE OR REPLACE FUNCTION has_access(integer, integer) 
RETURNS boolean AS 
$BODY$ 
SELECT 
    EXISTS (SELECT true 
      FROM test_read_access 
      WHERE id = $1 and login = $2 
) 
    AND 
    NOT EXISTS (SELECT true 
      FROM test_no_read_access 
      WHERE id = $1 and login = $2 
) 
$BODY$ 

這,只要我有工作細到只有關注關於功能的正確性。由於查詢分析器告訴我,必須對每行進行函數評估,因此EXISTS子句無法按預期進行優化。事實上,相比於以下查詢查詢是很慢(內聯EXISTS子句而不SELECT子句):

SELECT * FROM test_table tt WHERE 
    EXISTS (SELECT true 
      FROM test_read_access 
      WHERE id = tt.id and login = tt.login 
) 
    AND 
    NOT EXISTS (SELECT true 
      FROM test_no_read_access 
      WHERE id = tt.id and login = tt.login 
) 

功能has_access(ID,登錄)的目的是將一些訪問規則的函數,然後在不同的查詢中使用它。我的意思是,這是可以做到這樣的事情來獲得良好的性能:

SELECT * FROM test_table tt WHERE EXISTS (select has_access(tt.id, tt.login)) 

CREATE OR REPLACE FUNCTION has_access(integer, integer) 
RETURNS SETOF boolean AS 
$BODY$ 
SELECT true 
    FROM test_read_access 
WHERE id = $1 and login = $2 
$BODY$ 

但現在我只有在功能一個表一個子查詢,這是不是在我的情況非常有用。有關如何正確執行此操作以避免遇到性能問題的任何建議?

謝謝!

+0

EXISTS趨向於導致相關子查詢,這是數據庫管理系統,以優化硬;使用IN/NOT IN往往更有效率。 – okaram 2014-11-04 00:39:10

+0

@okaram:完全錯誤。請注意,在這種情況下,沒有相關的子查詢,因爲沒有主查詢。 – wildplasser 2014-11-04 00:52:19

+0

@wildplasser,該函數中的查詢是不相關的,但上面的是(但我沒有明白,當我發表評論時,問題是函數:) – okaram 2014-11-04 01:43:26

回答

0

好吧,我想我明白你的問題是什麼;函數調用不可優化,所以您需要在函數外執行查詢;像

SELECT * 
    FROM test_table 
WHERE (id,login) IN (SELECT id,login FROM test_read_access) 
    AND (id,login) NOT IN (SELECT id,login FROM test_no_read_access) 

檢查http://sqlfiddle.com/#!12/94a02/2

+1

沒有理由更喜歡'NOT IN(.. 。)'這裏; 「不存在(...)」工作得很好,或者甚至更好。 OQ中的性能問題在函數調用中,不能由優化器分解。 – wildplasser 2014-11-04 00:56:32

+0

@wildplasser我現在明白問題是函數調用;然而,通常在/不在查詢中更容易優化,對嗎? EXISTS傾向於做相關的子查詢(需要引用查詢中的外部行),這對優化器來說更難 – okaram 2014-11-04 01:41:53

+1

在過去的幾年裏,在我幾乎所有在Postgres的大量測試中,'NOT EXISTS'結果都比'NOT IN'。另外,'NOT IN'在NULL值方面表現出棘手的行爲。 [更多這裏。](http://stackoverflow.com/a/19364694/939860)。即將到來的第9.4版可能會有變化。不是說有,也沒有期待。只是沒有測試,但。 – 2014-11-04 22:17:03