sql >> データベース >  >> RDS >> PostgreSQL

OracleからPostgreSQLへ—カーソルとltree

    PostgreSQLのカーソルに関する前回の記事では、ommonable xpressions(CTE)について説明しました。今日、PostgreSQLのあまり知られていない機能を使用して、カーソルの新しい代替手段を発見し続けています。

    前の記事(上記のリンク)でインポートしたデータを使用します。しばらくお待ちください。

    わかった?わかりました。

    データは自然界の分類図です。基本的な高校の生物学からの思い出として、そのデータはカール・リンネによって王国、門、クラス、目、家族、属、種に編成されています。もちろん、科学は過去250年間でわずかに進歩したため、分類図は21レベルの深さです。 (当然のことながら)itis.hierarchyというテーブルに階層ツリーがあります。 。

    この記事のトピックは、PostgreSQLでltreeを使用する方法です。具体的には、複雑なレコードセットを非常に効率的にトラバースするためにそれらを使用する方法。その意味で、カーソルの別の代理と見なすことができます。

    データは(残念ながら私たちにとっては)ltree形式でキュレートされていないため、記事のために少し変換します。

    まず、この記事をフォローするために使用しているデータベースにltreeをインストールする必要があります。もちろん、拡張機能をインストールするにはスーパーユーザーである必要があります。

    CREATE EXTENSION IF NOT EXISTS ltree;
    

    次に、この拡張機能を使用して、非常に効率的なルックアップを提供します。データをルックアップテーブルに変換する必要があります。この変換を実行するには、前回の記事で説明したCTE手法を使用します。途中で、ラテン語の名前と英語の名前を分類ツリーに追加します。これは、番号、ラテン語の名前、または英語の名前でアイテムを検索するのに役立ちます。

    <?prettify lang-sql linenums =1?>

    -- We need a little helper function to strip out illegal label names.
    CREATE OR REPLACE FUNCTION strip_label(thelabel text)
    RETURNS TEXT
    AS $$
        -- make sure all the characters in the label are legal
        SELECT SELECT 
            regexp_replace(
                regexp_replace(
                    regexp_replace(
                        regexp_replace(
                            -- strip anything not alnum (yes, this could be way more accurate)
                            thelabel, '[^[:alnum:]]', '_','g'),
                        -- consolidate underscores
                        '_+', '_', 'g'), 
                    -- strip leading/trailing underscores
                    '^_*', '', 'g'), 
            '_*$', '', 'g'); 
    $$
    LANGUAGE sql;
    
    CREATE MATERIALIZED VIEW itis.world_view AS
    WITH RECURSIVE world AS (
        -- Start with the basic kingdoms
        SELECT h1.tsn, h1.parent_tsn, h1.tsn::text numeric_taxonomy,
            -- There is no guarantee that there will be a textual name
            COALESCE(l1.completename,h1.tsn::text,'')::text latin_taxonomy, 
            -- and again no guarantee of a common english name
            COALESCE(v1.vernacular_name, lower(l1.completename),h1.tsn::text,'unk')::text english_taxonomy
        FROM itis.hierarchy h1
        LEFT JOIN itis.longnames l1
            ON h1.tsn = l1.tsn
        LEFT JOIN itis.vernaculars v1
            ON (h1.tsn, 'English') = (v1.tsn, v1.language)
        WHERE h1.parent_tsn = 0
        UNION ALL
        SELECT h1.tsn, h1.parent_tsn, w1.numeric_taxonomy || '.' || h1.tsn, 
            w1.latin_taxonomy || '.' || COALESCE(strip_label(l1.completename), h1.tsn::text,'unk'), 
            w1.english_taxonomy || '.' || strip_label(COALESCE(v1.vernacular_name, lower(l1.completename), h1.tsn::text, 'unk'))
        FROM itis.hierarchy h1
        JOIN world w1
        ON h1.parent_tsn = w1.tsn
        LEFT JOIN itis.longnames l1
            ON h1.tsn = l1.tsn
        LEFT JOIN -- just change this to "itis.vernaculars v1" to allow mulitples and all languages.  (Millions of records.)
            (SELECT tsn, min(vernacular_name) vernacular_name FROM itis.vernaculars WHERE language = 'English' GROUP BY tsn) v1
            ON (h1.tsn) = (v1.tsn)
        )
    SELECT w2.tsn, w2.parent_tsn, w2.numeric_taxonomy::ltree, w2.latin_taxonomy::ltree latin_taxonomy, w2.english_taxonomy::ltree english_taxonomy
    FROM world w2
    ORDER BY w2.numeric_taxonomy
    WITH NO DATA;
    

    ちょっと立ち止まって、このクエリで花の匂いを嗅ぎましょう。手始めに、データを入力せずに作成しました。これにより、多くの役に立たないデータを生成する前に、構文上の問題に対処する機会が得られます。共通テーブル式の反復性を使用して、ここでかなり深い構造をまとめています。また、言語テーブルにデータを追加することで、より多くの言語をカバーするように簡単に拡張できます。マテリアライズドビューには、いくつかの興味深いパフォーマンス特性もあります。 REFRESH MATERIALIZED VIEWが実行されるたびに、テーブルが切り捨てられて再構築されます。 と呼ばれます。

    次に行うことは、世界観を刷新することです。主にそれを時々行うのは健康的だからです。ただし、この場合、実際に行われるのは、マテリアライズドビューにitisからのデータを入力することです。 スキーマ。

    REFRESH MATERIALIZED VIEW itis.world_view;

    データから600K以上の行を作成するには、数分かかります。

    最初の数行は次のようになります:

    ┌────────────┬─────────┬───────────────────────────────────────────────────────────────────────────────┐
    │ parent_tsn │   tsn   │                               english_taxonomy                                │
    ├────────────┼─────────┼───────────────────────────────────────────────────────────────────────────────┤
    │     768374 │ 1009037 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
    │            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
    │            │         │….cicadakillers.crabroninae.larrini.gastrosericina.gastrosericus.gastrosericus…│
    │            │         │…_xanthophilus                                                                 │
    │     768374 │ 1009038 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
    │            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
    │            │         │….cicadakillers.crabroninae.larrini.gastrosericina.gastrosericus.gastrosericus…│
    │            │         │…_zoyphion                                                                     │
    │     768374 │ 1009039 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
    │            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
    │            │         │….cicadakillers.crabroninae.larrini.gastrosericina.gastrosericus.gastrosericus…│
    │            │         │…_zyx                                                                          │
    │     768216 │  768387 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
    │            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
    │            │         │….cicadakillers.crabroninae.larrini.gastrosericina.holotachysphex              │
    │     768387 │ 1009040 │ animals.bilateria.protostomia.ecdysozoa.arthropods.hexapods.insects.winged_in…│
    │            │         │…sects.modern_wing_folding_insects.holometabola.ants.ants.aculeata.apoid_wasps…│
    │            │         │….cicadakillers.crabroninae.larrini.gastrosericina.holotachysphex.holotachysph…│
    │            │         │…ex_holognathus                                                                │
    └────────────┴─────────┴───────────────────────────────────────────────────────────────────────────────┘

    分類法では、グラフは次のようになります。

    もちろん、実際には21レベルの深さで、合計60万件以上のレコードがあります。

    今、私たちは楽しい部分に着きます! ltreeは、階層に対して非常に複雑なクエリを実行する方法を提供します。そのためのヘルプはPostgreSQLのドキュメントにあるので、ここではあまり詳しく説明しません。 (非常に迅速に)理解するために、ltreeの各セグメントはラベルと呼ばれます。したがって、このltree kingdom.phylum.class.order.family.genus.species 7つのラベルがあります。

    ltreeに対するクエリでは、限定された形式の正規表現のような特殊な表記法が使用されます。

    簡単な例を次に示します。Animalia.*.Homo_sapiens

    したがって、世界で人類を見つけるためのクエリは次のようになります。

    SELECT tsn, parent_tsn, latin_taxonomy, english_taxonomy 
    FROM itis.world_view WHERE latin_taxonomy ~ 'Animalia.*.Homo_sapiens';

    期待される結果:

    ┌────────┬────────────┬────────────────────────────────────────────────┬─────────────────────────────────────────────┐
    │  tsn   │ parent_tsn │                 latin_taxonomy                 │              english_taxonomy               │
    ├────────┼────────────┼────────────────────────────────────────────────┼─────────────────────────────────────────────┤
    │ 180092 │     180091 │ Animalia.Bilateria.Deuterostomia.Chordata.Vert…│ animals.bilateria.deuterostomia.chordates.v…│
    │        │            │…ebrata.Gnathostomata.Tetrapoda.Mammalia.Theria…│…ertebrates.gnathostomata.tetrapoda.mammals.…│
    │        │            │….Eutheria.Primates.Haplorrhini.Simiiformes.Hom…│…theria.eutheria.primates.haplorrhini.simiif…│
    │        │            │…inoidea.Hominidae.Homininae.Homo.Homo_sapiens  │…ormes.hominoidea.Great_Apes.African_apes.ho…│
    │        │            │                                                │…minoids.Human                               │
    └────────┴────────────┴────────────────────────────────────────────────┴─────────────────────────────────────────────┘

    もちろん、PostgreSQLはこれをそのままにしておくことはありません。演算子、インデックス、変換、および例の広範なセットがあります。

    このテクニックが解き放つ膨大な数の機能を見てみましょう。

    ここで、この手法が、部品番号、車両識別番号、部品表構造、その他の分類システムなど、他の複雑なデータタイプに適用されることを想像してみてください。この構造を直接使用するには非常に複雑な学習曲線があるため、この構造をエンドユーザーに公開する必要はありません。しかし、このような非常に強力で実装の複雑さを隠す構造に基づいて「ルックアップ」画面を構築することは完全に可能です。

    シリーズの次の記事では、プラグイン言語の使用について説明します。 PostgreSQLでカーソルの代替を見つけるという文脈では、選択した言語を使用して、ニーズに最も適した方法でデータをモデル化します。またね!


    1. Pythonモジュールcx_Oracleモジュールが見つかりませんでした

    2. SQL Serverネットワークインターフェイス:接続文字列が無効です[87]

    3. WHEREIN句で使用する値の配列をOracleプロシージャに送信する

    4. SQL Serverで無効になっているすべての外部キー制約を返す方法(T-SQLの例)