Postgresql
條件子查詢
我有以下查詢:
SELECT id, email, first_name as "firstName", last_name as "lastName", is_active as "isActive", password, access, CASE WHEN access < 3 THEN ( SELECT CASE WHEN count(*) = 1 THEN true ELSE false END FROM user_rating_entity ure WHERE ure.user_id = u.id AND ure.rating_entity_id = :re_id ) ELSE true END as "isResponsible" FROM users u WHERE u.id = :id
如果
access > 3
是,則欄位“isResponsible”應直接設置為true,不執行子查詢。>=
我對訪問和<
訪問3的兩種情況都使用了解釋分析,但我得到了相同的輸出。為什麼呢?
在這裡閱讀查詢計劃有三個重要部分,
- 跑了嗎。如果是這樣的話,
- 多少次?
- 是否相關?
樣本數據
您沒有提供任何範例數據,所以讓我們創建一些。
CREATE TABLE foo AS SELECT x FROM generate_series(1,100) AS x;
而且,現在讓我們在可能的執行範圍之外執行一個帶有子查詢的基本查詢。
EXPLAIN ANALYZE SELECT x, (CASE WHEN x>200 THEN (SELECT sum(x) FROM foo) END) FROM foo;
該計劃將顯示該案件是伴隨的,但從未執行。
Seq Scan on foo (cost=2.26..4.51 rows=100 width=4) (actual time=0.017..0.047 rows=100 loops=1) InitPlan 1 (returns $0) -> Aggregate (cost=2.25..2.26 rows=1 width=4) (never executed) -> Seq Scan on foo foo_1 (cost=0.00..2.00 rows=100 width=4) (never executed) Planning time: 0.101 ms Execution time: 0.118 ms (6 rows)
你可以看到**(從不執行)**就
Aggregate
行了。但是,如果我們將其設置為類似的內容,CASE WHEN x>20 THEN (SELECT sum(x) FROM foo
您會看到更多Seq Scan on foo (cost=2.26..4.51 rows=100 width=4) (actual time=0.020..0.095 rows=100 loops=1) InitPlan 1 (returns $0) -> Aggregate (cost=2.25..2.26 rows=1 width=4) (actual time=0.043..0.043 rows=1 loops=1) -> Seq Scan on foo foo_1 (cost=0.00..2.00 rows=100 width=4) (actual time=0.006..0.019 rows=100 loops=1) Planning time: 0.092 ms Execution time: 0.158 ms (6 rows)
在這裡我們可以看到 Aggregate 在
loops=1
時間上是循環的。PostgreSQL 意識到它不是一個相關的子查詢,它只是將其簡化為文字(本質上)。現在讓我們確保它是相關的。EXPLAIN ANALYZE SELECT x, (CASE WHEN x>20 THEN (SELECT sum(f2.x)+f1.x FROM foo AS f2) END) FROM foo AS f1;
現在你會看到這個計劃
Seq Scan on foo f1 (cost=0.00..228.50 rows=100 width=4) (actual time=0.020..3.210 rows=100 loops=1) SubPlan 1 -> Aggregate (cost=2.25..2.26 rows=1 width=4) (actual time=0.038..0.038 rows=1 loops=80) -> Seq Scan on foo f2 (cost=0.00..2.00 rows=100 width=4) (actual time=0.005..0.017 rows=100 loops=80) Planning time: 0.104 ms Execution time: 3.272 ms
這裡的關鍵是聚合
loops=80
本身需要loops=80
seq 掃描。這都是一般性的,但如果沒有您的範例數據或查詢計劃,我只能給出這些。