Modul PHP untuk bekerja dengan data hierarkis di InterSystems IRIS

gambar Sejak awal masanya, PHP telah terkenal (dan dikritik) karena mendukung integrasi dengan banyak perpustakaan, serta dengan hampir semua DBMS di pasar. Namun, karena beberapa alasan aneh, itu tidak mendukung database hierarkis tentang global.

Global adalah struktur untuk menyimpan informasi hierarkis. Mereka agak mengingatkan pada database "kunci -> nilai", dengan satu-satunya perbedaan adalah bahwa kuncinya bisa multi-level:

Set ^inn("1234567890", "city") = "Moscow" Set ^inn("1234567890", "city", "street") = "Req Square" Set ^inn("1234567890", "city", "street", "house") = 1 Set ^inn("1234567890", "year") = 1970 Set ^inn("1234567890", "name", "first") = "Vladimir" Set ^inn("1234567890", "name", "last") = "Ivanov" 

Dalam contoh ini, bahasa ObjectScript bawaan di global ^ inn , yang disimpan pada hard disk (ditunjukkan oleh ikon ^ di depan nama global), menyimpan informasi multilevel.

Secara alami, untuk bekerja dengan global dari PHP kita akan membutuhkan fungsi baru yang akan ditambahkan oleh modul PHP, yang akan dibahas di bawah ini.

Global mendukung banyak fungsi untuk bekerja dengan hierarki: mem-bypass kunci di setiap level secara terpisah, menghapus, menyalin, dan menempelkan seluruh pohon dan masing-masing node. Yah, dan juga basis data transaksi ACID yang bagus. Semua ini terjadi sangat cepat (sekitar 10 5 -10 6 operasi insert per detik pada perangkat keras biasa), karena dua alasan:

  1. Global adalah abstraksi level yang lebih rendah dari SQL,
  2. Basis global telah berproduksi selama beberapa dekade dan selama ini mereka berhasil menjilat kode mereka dan mengoptimalkannya secara menyeluruh.

Lebih lanjut tentang global dalam seri artikel “Global - Pedang-Mason untuk Penyimpanan Data”:

Pohon-pohon. Bagian 1
Pohon-pohon. Bagian 2
Array yang jarang. Bagian 3

Di dunia ini, global telah menemukan tempat aplikasi utama mereka dalam sistem penyimpanan informasi yang terstruktur rendah dan jarang seperti: medis, data pribadi, perbankan, dll.

Saya suka PHP (dan mengembangkannya) dan ingin bermain-main dengan global. Tidak ada modul jadi. Saya menulis kepada InterSystems meminta saya untuk membuatnya. Penantian tidak menghasilkan apa-apa, dan pada akhirnya kami (saya, bersama dengan mahasiswa pascasarjana saya) membuat modul sendiri. InterSystems mensponsori pengembangan sebagai bagian dari hibah pendidikan.

Secara umum, InterSystems IRIS adalah DBMS multi-model, jadi dari PHP Anda dapat bekerja dengannya melalui ODBC menggunakan SQL, tapi saya tertarik pada global, dan tidak ada konektor seperti itu.

Jadi, modul ini tersedia untuk PHP 7.x (diuji di bawah 7.0-7.2). Saat ini, itu hanya dapat bekerja dengan InterSystems IRIS dan Caché yang diinstal pada host yang sama.

Halaman modul pada OpenExchange (katalog proyek dan add-on untuk pengembang di InterSystems IRIS dan Caché).

Ada bagian DISKUS yang berguna di mana orang berbagi pengalaman penggunaannya.

Unduh di sini:
https://github.com/intersystems-community/php_ext_iris
Unduh repositori dari baris perintah:

 git clone https://github.com/intersystems-community/php_ext_iris 

Petunjuk untuk menginstal modul dalam bahasa Inggris dan Rusia.

Fungsi modul:
Fungsi phpDeskripsi
Bekerja dengan data
iris_set ($ node, value)
Situs instalasi.
  1. iris_set ($ global, $ subscript1, ..., $ subscriptN, $ value);
    iris_set ($ global, $ value);

    Pengembalian: benar atau salah (kesalahan).
    Semua parameter fungsi adalah string atau angka. Yang pertama adalah nama global, lalu indeksnya, parameter terakhir adalah nilainya.

     iris_set('^time',1); iris_set('^time', 'tree', 1, 1, 'value'); 

    Analog pada ObjectScript

     Set ^time = 1 Set ^time("tree", 1, 1) = "value" 
  2. iris_set ($ arrayGlobal, $ value);
    Hanya 2 parameter: yang pertama adalah array di mana nama global dan semua indeksnya disimpan; yang kedua adalah makna.

     $node = ['^time', 'tree', 1, 1]; iris_set($node,'value'); 

iris_get ($ node)
Baca simpul
Pengembalian: nilai (angka atau string), NULL (nilai tidak ditentukan) atau FALSE (kesalahan).

  1. iris_get ($ global, $ subscript1, ..., $ subscriptN);
    iris_get ($ global);
    Semua parameter fungsi adalah string atau angka. Yang pertama adalah nama global, lalu indeksnya. Global mungkin tidak memiliki indeks.

     $res = iris_get('^time'); $res1 = iris_get('^time', 'tree', 1, 1); 
  2. iris_get ($ arrayGlobal);
    Satu-satunya parameter adalah array di mana nama global dan semua indeksnya disimpan.

     $node = ['^time', 'tree', 1, 1]; $res = iris_get($node); 

iris_zkill ($ node)
Menghapus nilai simpul.
Pengembalian: BENAR atau SALAH - pada kesalahan.

Penting untuk dicatat bahwa fungsi ini hanya menghapus nilai dalam node dan tidak menyentuh cabang yang mendasarinya.

  1. iris_zkill ($ global, $ subscript1, ..., $ subscriptN);
    iris_zkill ($ global);
    Semua parameter fungsi adalah string atau angka. Yang pertama adalah nama global, lalu indeksnya. Global mungkin tidak memiliki indeks.

     $res = iris_zkill('^time'); //    . $res1 = iris_zkill('^time', 'tree', 1, 1); 
  2. iris_zkill ($ arrayGlobal);
    Satu-satunya parameter adalah array di mana nama global dan semua indeksnya disimpan.

     $a = ['^time', 'tree', 1, 1]; $res = iris_zkill($a); 

iris_kill ($ node)
Hapus node dan semua cabang turunan.
Pengembalian: BENAR atau SALAH - pada kesalahan.

  1. iris_kill ($ global, $ subscript1, ..., $ subscriptN);
    iris_kill ($ global);
    Semua parameter fungsi adalah string atau angka. Yang pertama adalah nama global, lalu indeksnya. Global mungkin tidak memiliki indeks, dalam hal ini dihapus sepenuhnya.

     $res1 = iris_kill('^example', 'subscript1', 'subscript2'); $res = iris_kill('^time'); //   . 
  2. iris_kill ($ arrayGlobal);
    Satu-satunya parameter adalah array di mana nama global dan semua indeksnya disimpan.

     $a = ['^time', 'tree', 1, 1]; $res = iris_kill($a); 

iris_order ($ node)
Memotong cabang global pada tingkat tertentu
Returns: array yang berisi nama lengkap node global berikutnya atau FALSE (saat kesalahan).

  1. iris_order ($ global, $ subscript1, ..., $ subscriptN);
    Semua parameter fungsi adalah string atau angka. Yang pertama adalah nama global, lalu indeksnya.

    Formulir penggunaan PHP dan yang setara dengan ObjectScript:

     iris_order('^ccc','new2','res2'); // $Order(^ccc("new2", "res2")) 
  2. iris_order ($ arrayGlobal);
    Satu-satunya parameter adalah array di mana nama global dan indeks dari simpul awal disimpan.

     $node = ['^inn', '1234567890', 'city']; for (; $node !== NULL; $node = iris_order($node)) { echo join(', ', $node).'='.iris_get($node)."\n"; } 

    Akan memberi kita kesimpulan:

     ^inn, 1234567890, city=Moscow ^inn, 1234567890, year=1970 

iris_order_rev ($ node)
Memotong cabang global pada tingkat tertentu dalam urutan terbalik
Returns: sebuah array yang berisi nama lengkap dari node global sebelumnya pada level yang sama atau FALSE (jika terjadi kesalahan).

  1. iris_order_rev ($ global, $ subscript1, ..., $ subscriptN);

    Semua parameter fungsi adalah string atau angka. Yang pertama adalah nama global, lalu indeksnya.

    Formulir penggunaan PHP dan yang setara dengan ObjectScript:

     iris_order_rev('^ccc','new2','res2'); // $Order(^ccc("new2", "res2"), -1) 
  2. iris_order_rev ($ arrayGlobal);

    Satu-satunya parameter adalah array di mana nama global dan indeks dari simpul awal disimpan.

     $node = ['^inn', '1234567890', 'name', 'last']; for (; $node !== NULL; $node = iris_order_rev($node)) { echo join(', ', $node).'='.iris_get($node)."\n"; } 

    Akan memberi kita kesimpulan:

     ^inn, 1234567890, name, last=Ivanov ^inn, 1234567890, name, first=Vladimir 

iris_query ($ CmdLine)
Memotong cabang global dengan masuk ke level yang lebih rendah
Returns: array yang berisi nama lengkap dari node yang mendasarinya (jika ada) atau global node berikutnya (jika tidak ada nested node).

  1. iris_query ($ global, $ subscript1, ..., $ subscriptN);
    Semua parameter fungsi adalah string atau angka. Yang pertama adalah nama global, lalu indeksnya.

    Formulir penggunaan PHP dan yang setara dengan ObjectScript:

     iris_query('^ccc', 'new2', 'res2'); // $Query(^ccc("new2", "res2")) 
  2. iris_query ($ arrayGlobal);
    Satu-satunya parameter adalah array di mana nama global dan indeks dari simpul awal disimpan.

     $node = ['^inn', 'city']; for (; $node !== NULL; $node = iris_query($node)) { echo join(', ', $node).'='.iris_get($node)."\n"; } 

    Akan memberi kita kesimpulan:

     ^inn, 1234567890, city=Moscow ^inn, 1234567890, city, street=Req Square ^inn, 1234567890, city, street, house=1 ^inn, 1234567890, name, first=Vladimir ^inn, 1234567890, name, last=Ivanov ^inn, 1234567890, year=1970 

Urutan berbeda dari urutan yang kami atur, karena di global secara otomatis ketika Anda memasukkan semuanya diurutkan dalam urutan naik.
Fungsi Layanan
iris_set_dir ($ FullPath)
Pengaturan direktori dengan database
Pengembalian: BENAR atau SALAH - pada kesalahan.

 iris_set_dir('/InterSystems/Cache/mgr'); 

Itu harus diselesaikan sebelum menghubungkan ke database.
iris_exec ($ CmdLine)
Jalankan perintah DB
Pengembalian: BENAR atau SALAH - pada kesalahan.

 iris_exec('kill ^global(6)'); //   ObjectScript    

iris_connect ($ login, $ pass)Terhubung ke DB
iris_quit ()Putuskan koneksi ke database
iris_errno ()Dapatkan kode kesalahan
iris_error ()Dapatkan deskripsi teks tentang kesalahan tersebut

Jika Anda ingin bermain sendiri dengan modul, maka:

Khusus untuk pengguna Habr, Dockerfile dibuat untuk membangun gambar.
 git clone https://github.com/intersystems-community/php_ext_iris cd php_ext_iris/iris docker-compose build docker-compose up -d 

Menguji halaman demo di localhost: 52080 di browser.

File PHP yang dapat diedit dan dimainkan dengan mereka berada di folder php / demo dan akan dipasang di dalam wadah.

Untuk menguji IRIS, gunakan admin nama pengguna, kata sandinya adalah SYS .

Untuk masuk ke pengaturan IRIS, gunakan URL berikut:
http: // localhost: 52773 / csp / sys / UtilHome.csp

Untuk memasuki konsol IRIS dari wadah ini, gunakan perintah:
 docker exec -it iris_iris_1 iris session IRIS 


Khusus untuk pengguna Habr dan InterSystems Caché virtualka dengan php-module diangkat.

Untuk pemasangan sendiri modul di bawah InterSystems Caché
  1. Memiliki Linux. Saya diuji di Ubuntu, di bawah Windows modul juga harus dibangun, tetapi saya tidak mengujinya.
  2. Unduh versi gratis:
  3. Instal modul cach.so dalam PHP sesuai dengan instruksi .

Dalam wadah buruh pelabuhan di komputer pribadi saya (AMD FX-9370 @ 4700Mhz 32GB, LVM, SSD SATA), untuk bersenang-senang, saya membuat dua tes primitif pada kecepatan memasukkan nilai-nilai baru ke dalam basis data.

  • Penyisipan 1 juta elemen baru ke global membutuhkan 1,81 detik atau 552K penyisipan per detik.
  • Memperbarui nilai dalam 1.000.000 kali global yang sama membutuhkan 1,98 detik atau 505K pembaruan per detik. Fakta yang menarik adalah bahwa penyisipan terjadi daripada pembaruan. Rupanya ini adalah konsekuensi dari optimasi database awal untuk penyisipan cepat.

Jelas bahwa tes-tes ini tidak dapat mengklaim akurat dan bermanfaat, karena bersifat primitif, dibuat dalam sebuah wadah. Pada perangkat keras yang lebih kuat dengan sistem disk PCIe SSD, puluhan juta insert per detik dapat dicapai.

Apa yang bisa diselesaikan dan keadaan saat ini


  1. Anda dapat menambahkan fungsi yang berguna untuk bekerja dengan transaksi (Anda masih dapat menggunakannya melalui iris_exec).
  2. Fungsi mengembalikan seluruh struktur global tidak diterapkan sehingga PHP tidak memotong global.
  3. Fungsi menyimpan array PHP sebagai subtree tidak diterapkan.
  4. Akses ke variabel basis data lokal tidak diterapkan. Hanya melalui iris_exec, meskipun lebih baik melalui iris_set.
  5. Tidak diimplementasikan dengan melewati global secara mendalam di arah yang berlawanan.
  6. Akses ke database melalui objek menggunakan metode (mirip dengan fungsi saat ini) tidak diterapkan.

Modul saat ini mungkin belum siap untuk diproduksi: tidak ada tes untuk beban tinggi dan kebocoran memori. Namun, jika seseorang membutuhkannya, maka hubungi saya (Sergey Kamenev updates@mail.ru).

Kesimpulan


Untuk waktu yang lama, dunia PHP dan basis hierarkis global secara praktis tidak berpotongan, meskipun global menyediakan fungsionalitas yang kuat dan cepat pada tipe data tertentu (medis, pribadi).

Saya berharap bahwa modul ini akan berfungsi sebagai pendorong untuk eksperimen oleh pemrogram PHP dengan pemrogram global dan ObjectScript untuk pengembangan sederhana antarmuka web dalam PHP.

PS Terima kasih atas perhatian Anda!

Source: https://habr.com/ru/post/id443440/


All Articles