0

私は2つのテーブルを持っています:

CREATE TABLE soils (
    sample_id       TEXT PRIMARY KEY, 
    project_id      TEXT, 
    technician_id   TEXT
);
CREATE INDEX soils_idx
ON soils
USING btree
(sample_id COLLATE pg_catalog."default");

CREATE TABLE assays (
    sample_id   TEXT PRIMARY KEY, 
    mo_ppm      NUMERIC
    );
CREATE INDEX assays_idx
ON assays
USING btree
(sample_id COLLATE pg_catalog."default");

各テーブルには、約50万のレコードが含まれ、実際には、タイプTEXTの各約20の追加列が含まれています(ここで時間を節約するために、上記のDDLでは省略されています)。

クエリを実行すると:

EXPLAIN SELECT
   s.sample_id, s.project_id, s.technician_id, a.mo_ppm
FROM
   soils AS s INNER JOIN assays AS a ON s.sample_id = a.sample_id

インデックスへのルックアップではなく、2つのSEQSCANを取得します。それは期待される動作ですか?

4

2 に答える 2

4

条件がないのでWHERE、表全体を効果的に読むことができます。シーケンシャルスキャンを実行し、インデックスをまったく含まない方が安価です。

試す:

EXPLAIN
SELECT s.sample_id, s.project_id, s.technician_id, a.mo_ppm
FROM   soils s
JOIN   assays a USING (sample_id)
WHERE  <some condition that returns few rows>;

WHERE...そして条件に一致するインデックスを使用する必要があります。

PRIMARY KEY列にインデックスを定義する必要はありません。PK制約は、一意のインデックスを使用して自動的に実装されます。追加のインデックスは冗長であり、役に立ちません。

外部キー列のインデックスは良い考えですが、あなたの例には奇妙に見えるインデックスがありません。2つのテーブルを1つに組み合わせることができるように。おそらく、テストケースを単純化しすぎているのでしょう。

最後に、大きなテーブルの場合、おそらく列integerの代わりに単純な主キーを使用することを検討します。これは通常、より高速です。textserial

于 2012-12-13T08:11:38.220 に答える
1

はい、それは予想される動作です。一方、それはあなたのrandom_page_costseq_page_costおよびeffective_cache_size設定に依存します。クエリにはWHERE句がないため、すべてを順番に読み取る方が速い場合があります。シーケンシャル スキャンにペナルティを課すことができます。

set enable_seqscan = off;
explain analyse <your query>;

次に、プラン/コスト/IO 待機を比較します (seq-scan を無効にすることはできませんが、コストが非常に高くなります -- ~1e7 (または 1e8))。

クエリにSSD とWHERE節がある場合は、 random_page_cost を 1.5..2.5 に下げて、PG にインデックスを使用させることができます。

于 2012-12-13T22:57:55.870 に答える