1

我在使用垂直分區優化表的性能方面很努力。下面的SELECT語句應該從postgre恕我直言,更加優化:postgresql:垂直分區不會帶來性能改進

SELECT 
    "ProductView".name, 
    "ProductView".price, 
    "ProductView".pid 
FROM 
    "DefaultSchema"."ProductView"; 

我的模式是這樣的:

tables: 
ProductA(**pid**, name, price) 
ProductB(**pid**, desc) 
view: 
Product(**pid**,name, price, desc) 

的SQL:

CREATE TABLE "DefaultSchema"."ProductA" 
(
    pid integer NOT NULL, 
    price integer, 
    name text, 
    CONSTRAINT pk_pa PRIMARY KEY (pid) 
) 

CREATE TABLE "DefaultSchema"."ProductB" 
(
    pid integer NOT NULL, 
    "desc" text, 
    CONSTRAINT "PK_PB" PRIMARY KEY (pid), 
    CONSTRAINT "FK_PID" FOREIGN KEY (pid) 
     REFERENCES "DefaultSchema"."ProductA" (pid) MATCH SIMPLE 
     ON UPDATE CASCADE ON DELETE CASCADE 
) 

CREATE OR REPLACE VIEW "DefaultSchema"."ProductView" AS 
SELECT p1.pid, 
    p1.price, 
    p1.name, 
    p2."desc" 
    FROM "DefaultSchema"."ProductA" p1 
    JOIN "DefaultSchema"."ProductB" p2 ON p1.pid = p2.pid; 

所以你可能會承認,我真的不需要ProductB作爲選擇查詢。儘管如此,它在執行過程中加入進來,正如你在這裏看到的那樣。

"Hash Join (cost=36.10..74.61 rows=1160 width=40) (actual time=0.090..0.105 rows=7 loops=1)" 
" Hash Cond: (p2.pid = p1.pid)" 
" -> Seq Scan on "ProductB" p2 (cost=0.00..22.30 rows=1230 width=4) (actual time=0.022..0.027 rows=7 loops=1)" 
" -> Hash (cost=21.60..21.60 rows=1160 width=40) (actual time=0.030..0.030 rows=7 loops=1)" 
"  Buckets: 1024 Batches: 1 Memory Usage: 1kB" 
"  -> Seq Scan on "ProductA" p1 (cost=0.00..21.60 rows=1160 width=40) (actual time=0.010..0.017 rows=7 loops=1)" 
"Total runtime: 0.299 ms" 

我的問題是我如何強制postgre只掃描ProductA?我是否需要添加約束,編輯配置文件還是不可能通過在Postgre中進行垂直分區來獲得性能優勢?提前致謝。 :)

+1

「總運行時間:0.299毫秒」,它應該快多少?這幾乎沒有什麼,很難改善。 1毫秒很快,但0.299毫秒,這真的很快,比我們大多數人可以用我們的眼睛快速閃爍... – 2014-11-05 15:53:49

+0

總的時間是不相關的,因爲在這個測試場景中,我只有7個記錄。有趣的一點是DBMS如何以語義的方式優化查詢。如果我想象我擁有一百萬條記錄,那麼如果我只掃描一張表或者掃描兩張表並加入它們,它會產生巨大的差異。 – Zephro 2014-11-06 10:45:34

回答

1

PostgreSQL的查詢計劃程序尚未加入刪除內部聯接。

您可以單獨查詢「ProductA」,也可以重寫視圖以使用左外部聯接。 PostgreSQL 9.0+ 確實在左外部連接上加入刪除。

CREATE OR REPLACE VIEW "DefaultSchema"."ProductView" AS 
SELECT p1.pid, 
    p1.price, 
    p1.name, 
    p2."desc" 
    FROM "DefaultSchema"."ProductA" p1 
    LEFT JOIN "DefaultSchema"."ProductB" p2 ON p1.pid = p2.pid; 

explain analyze 
SELECT "ProductView".name, "ProductView".price, "ProductView".pid 
FROM "ProductView"; 
 
QUERY PLAN 
-- 
Seq Scan on "ProductA" p1 (cost=0.00..20.00 rows=1000 width=41) (actual time=0.008..0.225 rows=1000 loops=1) 

重寫使用左外連接不應用安全的,但我認爲這是爲您的特定問題的安全。

+0

非常感謝Mike, 絕對是您的重點!這種現在有道理。 我不認爲應該可以優化一個內部連接而不需要觸摸表格。從邏輯的角度來看,我不確定內部連接的結果,所以我無法優化它。 – Zephro 2014-11-06 10:40:41