0

PostgreSQL 7.4 (はいアップグレード)

だから私のWHERE条件で私はこれを持っています

AND CASE
    WHEN "substring"(t."FieldID"::text, 0, 3) = '01'::text 
        OR "substring"(t."FieldID"::text, 0, 4) = '123'::text 
        OR "substring"(t."FieldID"::text, 0, 5) = '5555'::text 
        OR "substring"(t."FieldID"::text, 0, 6) = '44444'::text 
        OR "substring"(t."FieldID"::text, 0, 3) = '99'::text 
    THEN 1
    ELSE 0
END = 1

代替構文ですが、コストに変更はありません

AND CASE
    WHEN "substring"(t."FieldID"::text, 0, 3) = '01'::text THEN 1
    WHEN "substring"(t."FieldID"::text, 0, 4) = '123'::text THEN 1
    WHEN "substring"(t."FieldID"::text, 0, 5) = '5555'::text THEN 1
    WHEN "substring"(t."FieldID"::text, 0, 6) = '44444'::text THEN 1
    WHEN "substring"(t."FieldID"::text, 0, 3) = '99'::text THEN 1    
    ELSE 0
END = 1

文字列の開始によって結果を制限する費用対効果の高い方法を探しています。したがって、文字列が 01、123、5555、44444、または 99 で始まる場合は、それを結果セットに追加します。

何かご意見は?

注: FieldID にはインデックスが付けられます。Explain データを表示してクエリのボトルネックを確認します。上記のコードを追加すると、Sort のコストが大幅に上昇し、データ セット/結果の戻りが遅くなります。

Explain からの出力:

Sort (cost=88716.84..88719.89 rows=822 width=64)

クエリが複雑であるため、さらに多くのコードがありますが、コードの一部を削除すると、並べ替えのコストが大幅に削減されます

4

4 に答える 4

2

開始文字だけでフィルタリングしている場合はlike、問題なく使用でき、インデックスのみを使用します。

AND (t."FieldID"::text LIKE '01%' OR 
     t."FieldID"::text LIKE '123%' OR 
     t."FieldID"::text LIKE '5555%' OR
     t."FieldID"::text LIKE '44444%' OR
     t."FieldID"::text LIKE '99%')
于 2011-09-13T21:30:40.770 に答える
1

クエリに一致する式インデックスを定義することで、ある程度のトラクションが得られる場合があります。何かのようなもの

CREATE INDEX t_fieldid_prefix_3 ON t (("substring"("FieldID"::text, 0, 3)))
CREATE INDEX t_fieldid_prefix_4 ON t (("substring"("FieldID"::text, 0, 4)))
CREATE INDEX t_fieldid_prefix_5 ON t (("substring"("FieldID"::text, 0, 5)))
CREATE INDEX t_fieldid_prefix_6 ON t (("substring"("FieldID"::text, 0, 6)))

常に同じプレフィックスを探している場合は、すべてをインデックスに含めます。

CREATE INDEX t_fieldid_prefix ON t((CASE
    WHEN "substring"("FieldID"::text, 0, 3) = '01'::text 
        OR "substring"("FieldID"::text, 0, 4) = '123'::text 
        OR "substring"("FieldID"::text, 0, 5) = '5555'::text 
        OR "substring"("FieldID"::text, 0, 6) = '44444'::text 
        OR "substring"("FieldID"::text, 0, 3) = '99'::text 
    THEN 1
    ELSE 0
END))
于 2011-09-13T21:20:34.830 に答える
1

これが古いバージョンでサポートされているかどうかはわかりませんが、並べ替え式に​​インデックスを作成して、クエリが改善されるかどうかを確認できます。

CREATE INDEX idx_case ON the_table (
  (CASE
      WHEN substring("FieldID", 0, 3) = '01' THEN 1
      WHEN substring("FieldID", 0, 4) = '123' THEN 1
      WHEN substring("FieldID", 0, 5) = '5555' THEN 1
      WHEN substring("FieldID", 0, 6) = '44444' THEN 1
      WHEN substring("FieldID", 0, 3) = '99' THEN 1    
      ELSE 0
  END));

現在のバージョンでは、これを使用して ORDER BY ステップを改善できると確信しています

于 2011-09-13T21:21:15.363 に答える
0

この種のクエリが実行される頻度と、存在するデータの量に応じて、クエリの外部でこの一部を計算し、インデックスとしてのみ使用する列を追加することを検討できます。データ ウェアハウスが非正規化してレポート クエリを高速化するのと同じ方法です。

于 2011-09-13T21:12:33.877 に答える