2017-09-13 36 views
0

當在子SELECT中出現鎖定子句時,鎖定的行是那些由子查詢返回到外部查詢的行。由於來自外部查詢的條件可能被用於優化子查詢的執行,所以這可能涉及比檢查單獨的子查詢更少的行。例如,無法理解PostgreSQL有關FOR UPDATE行鎖定的文檔

SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss WHERE col1 = 5; 將僅鎖定col1 = 5的行,即使該條件在文本上並不在子查詢中。

有人可以幫我瞭解了一句「這可能涉及比子查詢的檢查獨自建議更少的行,因爲從外部查詢條件可能會被用來優化子查詢的執行」?

我的理解是,「鎖定的行是那些通過子查詢返回到外部查詢」,所以無論子查詢返回(在本例中爲所有行),那些行必須鎖定?爲什麼只有co1 = 5被鎖定

回答

1

如果子查詢實際運行,子查詢只鎖定行。

有時PostgreSQL可能會注意到它可以跳過執行外部查詢的某些部分以節省時間,而不影響查詢返回的行。

對於一個過於簡單的例子,如果你寫

SELECT * FROM my_table WHERE (SELECT ... FROM othertable WHERE ... FOR UPDATE) = 1 AND FALSE; 

的PostgreSQL將可以自由地從othertable鎖零行,因爲它可以證明,跳繩子查詢的執行不會影響查詢結果。

在該文檔的例子中,問題是,如果有行與COL1 = 4中,col1 = 6,等等,那些行可以不被鎖定,因爲PostgreSQL可以檢查條件col1 = 5並決定行在它執行子查詢之前不匹配。但推論是,如果PostgreSQL決定首先執行子查詢,他們也可以鎖定,可能

我強烈建議你做顯式行鎖定作爲CTE或類似的一部分,它完全清楚什麼會被執行,哪些不會被執行。

+0

謝謝!我不會想出這個隱式優化,我還可以如何顯式鎖定行?我不想做表鎖 – Zanko

+0

@Zanko你可以這樣做,沒關係。您只需瞭解關於哪些行被鎖定的含義。有時候使用CTE('WITH' query)將它分成可以控制執行的步驟是很有用的。 –