2013-10-17 47 views
0

需要運行查詢以查看至少存在一條記錄的位置。所以這個問題: 「什麼是更有效」:PERFORM * vs PERFORM 1

PERFORM * FROM table 

PERFORM 1 FROM table 

爲什麼呢?

回答

2

需要注意的是,首先,PERFORM不是SQL指令,它是plpgsql關鍵字,它指示解釋器運行等效的SELECT,然後丟棄結果。

每文檔(Executing a Command With No Result):

PERFORM查詢;
這將執行查詢並丟棄結果。以與編寫SQL SELECT命令相同的方式編寫查詢 ,但用PERFORM替換關鍵字SELECT的初始 。對於WITH查詢,請使用PERFORM,然後使用 將查詢放在括號中。 (在這種情況下,只有 查詢返回一行)。PL/pgSQL變量將替換爲查詢 ,就像不返回結果的命令一樣,並且計劃以相同方式緩存在 中。此外,特殊的變量FOUND設置爲true,如果 查詢產生至少一行,還是假的,如果沒有生成行

所以現在的問題是一樣的:你是怎麼SELECT * FROM tableSELECT 1 FROM table比較檢查桌子上至少有一排?但問題在於,它們在性能方面都不夠好,而且如果桌子上有很多排,實際上它們顯得很不合適。

讓我們在一個真實的例子測試了最新的PostgreSQL 9.3有兩個大表:

  • words(int,text)(3。4000000線和文本列總是很小)
  • inverted_word_index(int,int,bytea,int)(約10萬線,所述BYTEA是平均寬和2kB的最大400個字節)

查詢重複幾個連續次數與予保持只有最快的執行與psql的\timing on

測試1的第一個表

從字上執行1:

 
mlists=> do $$ begin perform 1 from words; end; $$; 
DO 
Time: 521,379 ms 

執行*從文字:

 
mlists=> do $$ begin perform * from words; end; $$; 
DO 
Time: 442,800 ms 

結果1:此表上,perform *似乎一直有點快於perform 1

測試2與第2臺

PERFORM 1從inverted_word_index:

 
mlists=> do $$ begin perform 1 from inverted_word_index ; end; $$; 
DO 
Time: 2206,230 ms 

執行*從inverted_word_index:

 
mlists=> do $$ begin perform * from inverted_word_index ; end; $$; 
DO 
Time: 16848,971 ms 

結果2:此表的最執行perform *比最好的執行者慢得多perform 1,所以這與之前的結果相反。

結論:沒有一般的贏家,它似乎取決於表內容。

但真正有趣的一點是,兩種方法全面掃描表而不是停在第一行,所以它們都太慢了。

相當快的方法

 
mlists=> do $$ begin perform 1 from words limit 1; end; $$; 
DO 
Time: 0,330 ms 

mlists=> do $$ begin perform * from words limit 1; end; $$; 
DO 
Time: 0,405 ms 

mlists=> do $$ begin perform 1 from inverted_word_index limit 1; end; $$; 
DO 
Time: 0,333 ms 

mlists=> do $$ begin perform * from inverted_word_index limit 1; end; $$; 
DO 
Time: 0,314 ms 

重複執行表明,這兩種結構的持續時間0.3毫秒,0.4毫秒,沒有勝者之間變化。速度差很小,以至於不相關的動態因素。

+0

你也可以看看測試'PERFORM FROM'。如果你打算使用特殊變量FOUND,不需要'*'或'1'。 – Daniel

+0

@Daniel:沒有列的'SELECT'或'PERFORM'是PostgreSQL 9.5之前的語法錯誤 –

0

我不知道爲什麼你想放棄結果。

個人我最好使用沿的線的東西:

select count(*) 
into rows_exist 
from (select * from my_table limit 1) t; 

單行用的0或1的值是保證被返回,並且僅在表中的單個行中的順序被讀出要做到這一點。

至於「1」與「*」 - 我的直覺是說優化器足夠智能,只讀取所需的列以回答查詢。

但是,如果您運行explain with (verbose true)它表明所有列都從子查詢投影。如果是這種情況,那麼使用「select *」的效率會更低,特別是如果從表的開頭刪除了大量的行,並且使用「select *」會導致許多塊被全部讀取發現第一個之前的表掃描。我歡迎來自PostgreSQL內部專家的意見,看看這是否是對計劃的正確解釋。

+0

這不完全是我的問題。有你的例子,我會問,是否SELECT *優於SELECT 1? – Macchiatow