2

2つのテーブルがあります。ここでは詳細は重要ではない1つの変更ログテーブル。販売者情報を保持し、最も重要な2つの列を持つ別のテーブル:

  • プライマリID
  • ident(=実世界ID)と呼ばれるID。

売り手が変更されると、新しいエントリが作成され、IDは同じままですが、新しいエントリは新しいIDになります。IDにプライマリインデックスがあり、(ident、-id)に別のインデックスがあるので、現在のデータをすばやく取得できます。

偶然にも、私は次の奇妙な行動を見つけました:

これは、完了するのに非常に長い時間がかかります。

SELECT DISTINCT ON (ident) sellers.* FROM changelog, sellers ORDER BY ident,id DESC;

                                  QUERY PLAN                                    
---------------------------------------------------------------------------------
 Unique  (cost=741675.98..760122.47 rows=10 width=30)
   ->  Sort  (cost=741675.98..750899.22 rows=3689298 width=30)
         Sort Key: sellers.ident, sellers.id
         ->  Nested Loop  (cost=3.07..74457.37 rows=3689298 width=30)
               ->  Seq Scan on changelog  (cost=0.00..668.34 rows=38034 width=0)
               ->  Materialize  (cost=3.07..4.04 rows=97 width=30)
                     ->  Seq Scan on sellers  (cost=0.00..2.97 rows=97 width=30)

DESCを-IDに置き換えると高速ですが、同じ結果が得られます。

SELECT DISTINCT ON (ident) sellers.* FROM changelog, sellers ORDER BY ident,-id;

                                         QUERY PLAN                                        
------------------------------------------------------------------------------------------
 Unique  (cost=706.37..92956.53 rows=10 width=30)
   ->  Nested Loop  (cost=706.37..83733.28 rows=3689298 width=30)
         ->  Index Scan using idx_sellers on sellers  (cost=0.00..17.70 rows=97 width=30)
         ->  Materialize  (cost=706.37..1086.71 rows=38034 width=0)
               ->  Seq Scan on changelog  (cost=0.00..668.34 rows=38034 width=0)

FROMから「changelog」を削除すると、ORDERBY-idとDESCは同じクエリプランをすばやく実行します。

SELECT DISTINCT ON (ident) sellers.* FROM sellers ORDER BY ident,id, DESC   

                             QUERY PLAN                              
---------------------------------------------------------------------
 Unique  (cost=6.17..6.66 rows=10 width=30)
   ->  Sort  (cost=6.17..6.41 rows=97 width=30)
         Sort Key: ident, id
         ->  Seq Scan on sellers  (cost=0.00..2.97 rows=97 width=30)

私の質問:

  • FROMに未使用のテーブルを含めるとクエリにまったく影響するのはなぜですか?
  • ORDER BY ident、-idがORDER BY ident、id DESCと同じプランを使用しないのはなぜですか?

編集:私の実際のクエリには、もちろん2つのテーブルを結合するためのWHERE句があります。

4

1 に答える 1

9

クエリには未使用のテーブルなどありません。

SELECT DISTINCT ON (ident) sellers.* 
FROM changelog, sellers ORDER BY ident,id DESC

元のクエリはクロス結合を作成していました (changelog のすべてのレコードが、sellers のすべてのレコードに結合されていました)。これが、20 年前に明示的な構文に置き換えられた暗黙の結合構文の使用を避ける必要がある理由の 1 つです。

于 2012-05-02T20:52:30.793 に答える