2

複合 (2 列) の主キーを使用して 2 つのテーブルを結合すると、クエリ プランで不適切なカーディナリティの見積もりが得られます。例:

CREATE TABLE t1 AS SELECT x, x*2 AS x2 FROM generate_series(0, 1000) AS x;
ALTER TABLE t1 ADD PRIMARY KEY(x, x2);
ANALYZE t1;

CREATE TABLE t2 AS SELECT x, x*2 AS x2 FROM generate_series(0, 1000) AS x;
ALTER TABLE t2 ADD FOREIGN KEY (x, x2) REFERENCES t1(x,x2);
ANALYZE t2;

EXPLAIN ANALYZE
SELECT *
FROM t1 JOIN t2 USING (x, x2)

 QUERY PLAN                                                                                                    
 ------------------------------------------------------------------------------------------------------------- 
 Hash Join  (cost=30.02..52.55 rows=1 width=8) (actual time=0.660..1.551 rows=1001 loops=1)                    
   Hash Cond: ((t1.x = t2.x) AND (t1.x2 = t2.x2))                                                              
   ->  Seq Scan on t1  (cost=0.00..15.01 rows=1001 width=8) (actual time=0.021..0.260 rows=1001 loops=1)       
   ->  Hash  (cost=15.01..15.01 rows=1001 width=8) (actual time=0.620..0.620 rows=1001 loops=1)                
         Buckets: 1024  Batches: 1  Memory Usage: 40kB                                                         
         ->  Seq Scan on t2  (cost=0.00..15.01 rows=1001 width=8) (actual time=0.019..0.230 rows=1001 loops=1) 
 Total runtime: 1.679 ms    

プランでは 1 行が返されることを想定していますが、実際には 1001 行が返されます。これは単純なクエリでは問題になりませんが、複雑なクエリを実行すると、クエリ プランが非常に遅くなります。クエリ オプティマイザーのパフォーマンスを向上させるにはどうすればよいですか?

4

2 に答える 2

1

1 つの列が他の列に完全に依存している複合主キーを使用することは、「興味深い」設計です。

いずれにせよ、PostgreSQLは現在、各列の選択性が互いに独立していると想定しているため、それらを乗算します(同じインデックスにあるかどうかに関係なく、主キーインデックスであっても)、私は知りませんそれを回避する良い方法です。

この迂回を使用して、真の選択度に近づけることができます。

EXPLAIN ANALYZE
SELECT *
FROM t1 JOIN t2 on (t1.x=t2.x and t1.x2 between t2.x2 and t2.x2);
于 2013-09-26T16:17:43.623 に答える