2

更新:がらくた!整数ではなく、文字が変化します(10)

このようにクエリを実行すると、インデックスが使用されます

SELECT t."FieldID"
FROM table t
WHERE t."FieldID" = '0123456789'

しかし、これを実行するとインデックスは使用されません

SELECT t."FieldID"
FROM table t
WHERE t."FieldID" LIKE '01%'

またはこれ

SELECT t."FieldID"
FROM table t
WHERE "substring"(t."FieldID", 0, 3) = '01'

これも

SELECT t."FieldID"
FROM table t
WHERE t."FieldID" ~ '^01'

私のインデックスは次のようになります

CREATE UNIQUE INDEX fieldid_index
  ON "table"
  USING btree
  ("FieldID");

PostgreSQL 7.4 の実行 (はい、アップグレード中です)

クエリを最適化しているのですが、ステートメントの SELECT または WHERE 句で 3 種類の式のいずれかを使用すると、パフォーマンスが向上するかどうかを知りたいと思っていました。

注: これらのスタイルの制約で実行されるクエリは、約 200,000 レコードを返します

例 データは文字が変化します(10) :0123456789また、インデックスも作成されます

1. (部分文字列)

SELECT CASE
    WHEN "substring"(t."FieldID"::text, 0, 3) = '01'::text         
    THEN 'Found Match'::text
    ELSE NULL::text
END AS matching_group

2. (いいね)

SELECT CASE
    WHEN t."FieldID"::text LIKE '01%'         
    THEN 'Found Match'::text
    ELSE NULL::text
END AS matching_group

3. (正規表現)

SELECT CASE
    WHEN t."FieldID" ~ '^01'         
    THEN 'Found Match'::text
    ELSE NULL::text
END AS matching_group

また、WHERE 句で一方を他方よりも使用すると、パフォーマンス上の利点がありますか?

1. (部分文字列)

WHERE CASE
    WHEN "substring"(t."FieldID"::text, 0, 3) = '01'::text         
    THEN 1
    ELSE 0
END = 1

2. (いいね)

WHERE CASE
    WHEN t."FieldID"::text LIKE '01%'         
    THEN 1
    ELSE 0
END = 1

3. (正規表現)

WHERE CASE
    WHEN t."FieldID" ~ '^01'         
    THEN 1
    ELSE 0
END = 1

SELECT で 1 つのオプションを使用し、WHERE 句で別のオプションを使用すると、パフォーマンスが向上しますか?

4

4 に答える 4

3

個人的には、こういう問題を起こす人に「パフォーマンス」という言葉を使ってはいけないと思います。数値フィールド (おそらくキーフィールド) のコンテンツのテキスト表現に対する制限 (WHERE 句の制限など) は、設計が悪いことを示しています。

これが私のデータである場合、クエリ xyz で必要かどうかを示すフラグフィールドをレコードに追加します。別のテーブルに入れることもできます。GW-basic-substring ゴミに基づいてインデックス全体を作成するよりも、(冗長な?) 列を追加することを好みます。

于 2011-09-14T14:10:09.053 に答える
3

最も効果的な 2 つのことは、インデックス作成と検索可能性です。Sargabilityとは、インデックスを利用できる式を使用することを意味します。を使用して効果を測定します。

ANALYZE your_first_table;
-- ANALYZE other tables used in this query.
EXPLAIN ANALYZE
SELECT ...

Examining index usageのドキュメントを参照してください。

式のインデックスまたは部分インデックスを利用できる場合があります。PostgreSQL 7.4 は、式のインデックスと部分インデックスの両方をサポートしています。テストのために、特定の種類のクエリ プランを思いとどまらせることができます。(7.4 にもあります。)

あなたのために働くかもしれない式ベースのインデックス:

create index firsttwochars
on your-table-name (substring(your-column-name from 1 for 2));

ただし、クエリをテストして、実際にインデックスが使用されているかどうかを確認する必要があります。(それらがsargableであるかどうか。) これはうまくいくかもしれません。

select your-column-name 
from your-table-name 
where substring(your-column-name from 1 for 2) = '01'

最初の 2 文字にインデックスがないクエリ プラン。(私のテスト テーブルではランダムなテキストのみのユーザー名を使用しているため、「01」ではなく「ab」で検索しました。)

Seq Scan on substring  (cost=0.00..205.00 rows=50 width=11) (actual time=0.315..4.377 rows=14 loops=1)
  Filter: (substring((username)::text, 1, 2) = 'ab'::text)
Total runtime: 4.414 ms

最初の 2 文字にインデックスを持つクエリ プラン。

Bitmap Heap Scan on substring  (cost=4.36..37.61 rows=14 width=11) (actual time=0.036..0.056 rows=14 loops=1)
  Recheck Cond: (substring((username)::text, 1, 2) = 'ab'::text)
  ->  Bitmap Index Scan on firsttwochars  (cost=0.00..4.36 rows=14 width=0) (actual time=0.028..0.028 rows=14 loops=1)
        Index Cond: (substring((username)::text, 1, 2) = 'ab'::text)
Total runtime: 0.098 ms
于 2011-09-14T14:15:10.980 に答える
1

SQL Serverでは、バージョンはLIKE '01%'sargableになります。実際には、LIKEワイルドカードを範囲クエリに導くことなく、これらのクエリを変換します。

実行プランは、YourCol >= '01' AND YourCol < '02'おそらく同様の種類の書き換えがPostgresqlで役立つ可能性があるため、seek述語を示していますか?

于 2011-09-14T16:24:05.277 に答える
1

選択リストでは、おそらく3つの式の間に大きな違いはありません。それはすべてCPU時間です。

句にはWHERE、次のような式インデックスを追加できます。

CREATE INDEX foo ON sometable ((
CASE
    WHEN "substring"("FieldID"::text, 0, 3) = '01'::text         
    THEN 1
    ELSE 0
END
));

しかし、そのようなブールインデックスの選択性は、プランナーに興味を示さないほど悪い可能性があります。WHERE条項を次のように書き直したほうがよいでしょう

WHERE "substring"("FieldID"::text, 0, 3) = '01'::text

次に、そのインデックスを作成します。

LIKEおよび正規表現の場合は、インデックスも検討できますtext_pattern_opsドキュメントを参照してください。

全体として、そのクエリに対して実行するクリーンアップ作業があると思います。

于 2011-09-14T14:21:12.633 に答える