PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Oracle ke PostgreSQL — Kursor dan pohon

Dalam artikel terakhir kami tentang kursor di PostgreSQL, kami berbicara tentang ommonable xpressions (CTE). Hari ini, kami terus menemukan alternatif baru untuk kursor dengan menggunakan fitur PostgreSQL yang kurang dikenal.

Kami akan menggunakan data yang kami impor di artikel sebelumnya (ditautkan di atas). Saya akan menunggu sebentar sampai Anda mengikuti prosedur di sana.

Mengerti? Oke.

Data tersebut merupakan bagan taksonomi alam. Sebagai pengingat dari biologi sekolah menengah dasar, data tersebut diatur oleh Carl Linnaeus menjadi Kingdom, Phylum, Class, Order, Family, Genus, dan Species. Tentu saja, sains telah bergerak maju sedikit dalam 250 tahun terakhir, sehingga grafik taksonominya memiliki kedalaman 21 level. Kami menemukan hierarki pohon dalam tabel yang (tidak mengejutkan) disebut itis.hierarchy .

Topik artikel ini adalah bagaimana menggunakan ltrees di PostgreSQL. Secara khusus, bagaimana menggunakannya untuk melintasi kumpulan rekaman yang kompleks dengan sangat efisien. Dalam hal ini, kita dapat menganggapnya sebagai pengganti kursor lainnya.

Data tidak dikuratori (sayangnya bagi kami) dalam format ltree, jadi kami akan mengubahnya sedikit demi artikel.

Pertama, Anda harus menginstal ltree di database yang Anda gunakan untuk mengikuti artikel ini. Tentu saja, Anda harus menjadi pengguna super untuk memasang ekstensi.

CREATE EXTENSION IF NOT EXISTS ltree;

Sekarang kita akan menggunakan ekstensi ini untuk memberikan beberapa pencarian yang sangat efisien. Kita perlu mengubah data menjadi tabel pencarian. Untuk melakukan transformasi ini, kita akan menggunakan teknik CTE yang telah kita bahas di artikel terakhir. Sepanjang jalan, kita akan menambahkan nama Latin dan nama Inggris ke pohon taksonomi. Ini akan membantu kami mencari item berdasarkan nomor, nama Latin, atau nama Inggris.

-- 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;

Mari kita berhenti sejenak dan mencium bunga-bunga dalam kueri ini. Sebagai permulaan, kami membuatnya tanpa mengisi data apa pun. Ini memberi kami kesempatan untuk menangani masalah sintaksis apa pun sebelum menghasilkan banyak data yang tidak berguna. Kami menggunakan sifat berulang dari ekspresi tabel umum untuk menyusun struktur yang cukup dalam di sini, dan kami dapat dengan mudah memperluasnya untuk mencakup lebih banyak bahasa dengan menambahkan data ke tabel vernakular. Tampilan yang terwujud juga memiliki beberapa karakteristik performa yang menarik. Ini akan memotong dan membangun kembali tabel setiap kali REFRESH MATERIALIZED VIEW disebut.

Apa yang akan kita lakukan selanjutnya adalah menyegarkan pandangan dunia kita. Sebagian besar karena itu sehat untuk dilakukan dari waktu ke waktu. Namun dalam kasus ini, yang sebenarnya dilakukan adalah mengisi tampilan yang terwujud dengan data dari itis skema.

REFRESH MATERIALIZED VIEW itis.world_view;

Ini akan memakan waktu beberapa menit untuk membuat 600 ribu+ baris dari data.

Beberapa baris pertama akan terlihat seperti ini:

┌────────────┬─────────┬───────────────────────────────────────────────────────────────────────────────┐
│ 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                                                                │
└────────────┴─────────┴───────────────────────────────────────────────────────────────────────────────┘

Dalam taksonomi, grafiknya akan terlihat seperti ini:

Tentu saja, kedalamannya akan mencapai 21 level, dan total 600 ribu+ catatan.

Sekarang kita masuk ke bagian yang menyenangkan! ltrees menyediakan cara untuk melakukan beberapa kueri yang sangat kompleks pada hierarki. Bantuan untuk itu ada di dokumentasi PostgreSQL, jadi kami tidak akan membahasnya terlalu dalam di sini. Untuk pemahaman (sangat cepat), setiap segmen dari ltree disebut label. Jadi, ltree kingdom.phylum.class.order.family.genus.species ini memiliki 7 label.

Kueri terhadap ltree menggunakan notasi khusus seperti ekspresi reguler dalam bentuk terbatas.

Berikut ini contoh sederhananya:Animalia.*.Homo_sapiens

Jadi kueri untuk menemukan kemanusiaan di dunia akan terlihat seperti ini:

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

Yang menghasilkan yang diharapkan:

┌────────┬────────────┬────────────────────────────────────────────────┬─────────────────────────────────────────────┐
│  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                               │
└────────┴────────────┴────────────────────────────────────────────────┴─────────────────────────────────────────────┘

Tentu saja, PostgreSQL tidak akan pernah berhenti begitu saja. Ada banyak operator, Indeks, Transformasi, dan Contoh.

Lihatlah beragam kemampuan yang dibuka oleh teknik ini.

Sekarang bayangkan teknik ini diterapkan pada tipe data kompleks lainnya seperti nomor bagian, nomor identifikasi kendaraan, struktur bill of material atau sistem klasifikasi lainnya. Tidak perlu memaparkan struktur ini kepada pengguna akhir karena kurva pembelajaran yang sangat rumit untuk menggunakannya secara langsung. Tetapi sangat mungkin untuk membuat layar "pencarian" berdasarkan struktur seperti ini yang sangat kuat dan menyembunyikan kerumitan implementasi.

Untuk artikel berikutnya dalam seri ini, kami akan mengeksplorasi penggunaan bahasa plug in. Dalam konteks menemukan alternatif untuk kursor di PostgreSQL, kita akan menggunakan bahasa pilihan kita untuk memodelkan data dengan cara yang paling tepat untuk kebutuhan kita. Sampai jumpa lagi!


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tidak dapat terhubung ke postgres dari host jarak jauh

  2. Postgresql SQL GROUP BY interval waktu dengan akurasi sewenang-wenang (hingga mili detik)

  3. Menentukan OID tabel di Postgres 9.1?

  4. Seberapa berbeda PostgreSQL dengan MySQL?

  5. Cara Melihat Versi Postgres Yang Sedang Berjalan