وحدة PHP للعمل مع البيانات التسلسلية في InterSystems IRIS

الصورة منذ بداية وقتها ، اشتهرت PHP (وانتقدت) لدعم التكامل مع مجموعة من المكتبات ، وكذلك مع جميع نظم إدارة قواعد البيانات في السوق. ومع ذلك ، نظرًا لبعض الأسباب الغريبة ، لم تدعم قواعد البيانات الهرمية على العالم.

Globals هي هياكل لتخزين المعلومات الهرمية. إنها تذكرنا إلى حد ما بقاعدة البيانات "key -> value" ، والفرق الوحيد هو أن المفتاح يمكن أن يكون متعدد المستويات:

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" 

في هذا المثال ، تخزن لغة ObjectScript المدمجة في ^ ^ inn ، والتي يتم تخزينها على القرص الثابت (المشار إليها بواسطة أيقونة ^ أمام الاسم العمومي) ، معلومات متعددة المستويات.

بطبيعة الحال ، للعمل مع globals من PHP ، سنحتاج إلى وظائف جديدة ستضاف بواسطة وحدة PHP ، والتي ستتم مناقشتها أدناه.

تدعم Globals العديد من الوظائف للعمل مع التسلسل الهرمي: تجاوز المفاتيح في كل مستوى على حدة ، وحذف ونسخ ولصق الأشجار والعقد الفردية بأكملها. حسنا ، وكذلك أي قاعدة بيانات المعاملات ACID جيدة. كل هذا يحدث بسرعة كبيرة (حوالي 10 5 -10 6 عمليات إدراج في الثانية على الأجهزة العادية) ، لسببين:

  1. Globals هي مستوى تجريد أقل من SQL ،
  2. لقد تم إنتاج القواعد العالمية منذ عقود وخلال هذه الفترة تمكنت من لعق الكود وتحسينه تمامًا.

المزيد عن globals في سلسلة مقالات "Globals - Swords-Masons for Data Storage":

الأشجار. الجزء 1
الأشجار. الجزء 2
صفائف متفرق. الجزء 3

في هذا العالم ، وجدت globals مكانها الرئيسي للتطبيق في أنظمة التخزين الخاصة بالمعلومات ذات التنظيم المنخفض والمتفرق مثل: البيانات الطبية والبيانات الشخصية والخدمات المصرفية وما إلى ذلك.

أحب PHP (وأطوره) وأردت أن ألعب حول العالم. لم يكن هناك وحدة الانتهاء. كتبت إلى InterSystems تطلب مني إنشائها. لم يؤد الانتظار إلى أي شيء ، وفي النهاية قمنا (أنا ، مع طالب الدراسات العليا) بتكوين الوحدة بأنفسنا. قامت InterSystems برعاية التطوير كجزء من منحة تعليمية.

بشكل عام ، InterSystems IRIS عبارة عن نظم إدارة قواعد بيانات متعددة النماذج ، لذلك من PHP يمكنك التعامل معها من خلال ODBC باستخدام SQL ، لكنني كنت مهتمًا بالعالم ، ولم يكن هناك مثل هذا الرابط.

لذلك ، تتوفر الوحدة النمطية لـ PHP 7.x (تم اختباره تحت 7.0-7.2). حاليًا ، يمكنه العمل فقط مع InterSystems IRIS و Caché المثبتة على نفس المضيف.

صفحة الوحدة النمطية على OpenExchange (كتالوج للمشاريع والإضافات للمطورين على InterSystems IRIS و Caché).

يوجد قسم DISCUSS مفيد يشارك فيه الأشخاص تجارب استخدامهم.

تحميل هنا:
https://github.com/intersystems-community/php_ext_iris
قم بتنزيل المستودع من سطر الأوامر:

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

تعليمات لتثبيت الوحدة باللغة الإنجليزية والروسية.

وظائف الوحدة:
وظيفة phpوصف
العمل مع البيانات
iris_set ($ $ ، قيمة)
موقع التثبيت.
  1. iris_set ($ global ، $ subscript1 ، ... ، $ subscriptN ، $ value) ؛
    iris_set ($ global ، $ value) ؛

    العوائد: صواب أو خطأ (على خطأ).
    جميع المعلمات وظيفة هي سلاسل أو أرقام. الأول هو اسم العمومي ، ثم المؤشرات ، والمعلمة الأخيرة هي القيمة.

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

    التناظرية على ObjectScript

     Set ^time = 1 Set ^time("tree", 1, 1) = "value" 
  2. iris_set ($ arrayGlobal ، $ value) ؛
    معلمتان فقط: الأولى عبارة عن صفيف يتم فيه تخزين اسم المؤشر العمومي وجميع مؤشراته ؛ والثاني هو المعنى.

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

iris_get ($ العقدة)
قراءة العقدة.
العوائد: القيمة (الرقم أو السلسلة) ، NULL (القيمة غير محددة) أو FALSE (خطأ).

  1. iris_get ($ global، $ subscript1، ...، $ subscriptN)؛
    iris_get ($ global) ؛
    جميع المعلمات وظيفة هي سلاسل أو أرقام. الأول هو اسم العالمية ، ثم المؤشرات. قد لا تحتوي الفهارس العالمية.

     $res = iris_get('^time'); $res1 = iris_get('^time', 'tree', 1, 1); 
  2. iris_get ($ arrayGlobal) ؛
    المعلمة الوحيدة هي المصفوفة التي يتم فيها تخزين اسم العموم وجميع مؤشراته.

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

iris_zkill ($ العقدة)
حذف قيمة العقدة.
العوائد: صحيح أو خطأ - على خطأ.

من المهم ملاحظة أن هذه الوظيفة تحذف فقط القيمة في العقدة ولا تلمس الفروع الأساسية.

  1. iris_zkill ($ global، $ subscript1، ...، $ subscriptN)؛
    iris_zkill ($ global) ؛
    جميع المعلمات وظيفة هي سلاسل أو أرقام. الأول هو اسم العالمية ، ثم المؤشرات. قد لا تحتوي الفهارس العالمية.

     $res = iris_zkill('^time'); //    . $res1 = iris_zkill('^time', 'tree', 1, 1); 
  2. iris_zkill ($ arrayGlobal)؛
    المعلمة الوحيدة هي المصفوفة التي يتم فيها تخزين اسم العموم وجميع مؤشراته.

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

iris_kill ($ العقدة)
حذف عقدة وجميع الفروع سليل.
العوائد: صحيح أو خطأ - على خطأ.

  1. iris_kill ($ global، $ subscript1، ...، $ subscriptN)؛
    iris_kill ($ global) ؛
    جميع المعلمات وظيفة هي سلاسل أو أرقام. الأول هو اسم العالمية ، ثم المؤشرات. قد لا تحتوي الفهارس العالمية ، وفي هذه الحالة يتم حذفها بالكامل.

     $res1 = iris_kill('^example', 'subscript1', 'subscript2'); $res = iris_kill('^time'); //   . 
  2. iris_kill ($ arrayGlobal)؛
    المعلمة الوحيدة هي المصفوفة التي يتم فيها تخزين اسم العموم وجميع مؤشراته.

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

iris_order ($ عقدة)
تجاوز الفروع العالمية في مستوى معين
إرجاع: صفيف يحتوي على الاسم الكامل للعقدة العمومية التالية أو FALSE (على خطأ).

  1. iris_order ($ global، $ subscript1، ...، $ subscriptN)؛
    جميع المعلمات وظيفة هي سلاسل أو أرقام. الأول هو اسم العالمية ، ثم المؤشرات.

    نموذج استخدام PHP ومكافئ ObjectScript:

     iris_order('^ccc','new2','res2'); // $Order(^ccc("new2", "res2")) 
  2. iris_order ($ arrayGlobal)؛
    المعلمة الوحيدة هي الصفيف الذي يتم فيه تخزين الاسم العام والفهارس لعقدة البدء.

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

    سوف تعطينا الاستنتاج:

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

iris_order_rev ($ العقدة)
تجاوز الفروع العالمية عند مستوى معين بترتيب عكسي
إرجاع: صفيف يحتوي على الاسم الكامل للعقدة العمومية السابقة في نفس المستوى أو FALSE (في حالة حدوث خطأ).

  1. iris_order_rev ($ global، $ subscript1، ...، $ subscriptN)؛

    جميع المعلمات وظيفة هي سلاسل أو أرقام. الأول هو اسم العالمية ، ثم المؤشرات.

    نموذج استخدام PHP ومكافئ ObjectScript:

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

    المعلمة الوحيدة هي الصفيف الذي يتم فيه تخزين الاسم العام والفهارس لعقدة البدء.

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

    سوف تعطينا الاستنتاج:

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

iris_query ($ CmdLine)
تجاوز الفروع العالمية مع الدخول إلى المستويات الأدنى
إرجاع: صفيف يحتوي على الاسم الكامل للعقدة الأساسية (إن وجدت) أو العقدة العالمية التالية (إذا لم يكن هناك عقدة متداخلة).

  1. iris_query ($ global، $ subscript1، ...، $ subscriptN)؛
    جميع المعلمات وظيفة هي سلاسل أو أرقام. الأول هو اسم العالمية ، ثم المؤشرات.

    نموذج استخدام PHP ومكافئ ObjectScript:

     iris_query('^ccc', 'new2', 'res2'); // $Query(^ccc("new2", "res2")) 
  2. iris_query ($ arrayGlobal)؛
    المعلمة الوحيدة هي الصفيف الذي يتم فيه تخزين الاسم العام والفهارس لعقدة البدء.

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

    سوف تعطينا الاستنتاج:

     ^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 

يختلف الترتيب عن الترتيب الذي وضعناه فيه ، لأنه في الترتيب العام تلقائيًا عند إدراج كل شيء يتم فرزه بترتيب تصاعدي.
وظائف الخدمة
iris_set_dir ($ FullPath)
وضع دليل مع قاعدة بيانات
العوائد: صحيح أو خطأ - على خطأ.

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

يجب إكماله قبل الاتصال بقاعدة البيانات.
iris_exec ($ CmdLine)
قم بتشغيل أمر DB
العوائد: صحيح أو خطأ - على خطأ.

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

iris_connect (تسجيل الدخول $ ، تمرير $)الاتصال DB
iris_quit ()قطع الاتصال بقاعدة البيانات
iris_errno ()الحصول على رمز الخطأ
iris_error ()الحصول على وصف نصي للخطأ

إذا كنت تريد اللعب مع الوحدة بنفسك ، فقم بما يلي:

خاصة بالنسبة لمستخدمي Habr ، تم إنشاء Dockerfile لإنشاء الصورة.
 git clone https://github.com/intersystems-community/php_ext_iris cd php_ext_iris/iris docker-compose build docker-compose up -d 

اختبار الصفحة التجريبية على المضيف المحلي: 52080 في المتصفح.

توجد ملفات PHP التي يمكن تحريرها وتشغيلها معهم في مجلد php / demo وسيتم تحميلها داخل الحاوية.

لاختبار IRIS ، استخدم مسؤول اسم المستخدم ، وكلمة المرور هي SYS .

لإدخال إعدادات IRIS ، استخدم عنوان URL التالي:
http: // localhost: 52773 / csp / sys / UtilHome.csp

لإدخال وحدة التحكم IRIS في هذه الحاوية ، استخدم الأمر:
 docker exec -it iris_iris_1 iris session IRIS 


خاصة لمستخدمي Habr و InterSystems Caché ، تم رفع virtualka مع php-module.

للتثبيت الذاتي للوحدة النمطية تحت InterSystems Caché
  1. لديك لينكس. اختبرت تحت Ubuntu ، تحت ويندوز أيضا ينبغي أن تكون وحدة بنيت ، لكنني لم اختباره.
  2. تحميل نسخة مجانية:
  3. تثبيت وحدة cach.so في PHP وفقا للتعليمات .

في حاوية الإرساء على جهاز الكمبيوتر الشخصي الخاص بي (AMD FX-9370 @ 4700Mhz 32GB ، LVM ، SATA SSD) ، من أجل المتعة ، قمت بإجراء اختبارين بدائيين على سرعة إدخال قيم جديدة في قاعدة البيانات.

  • استغرق إدخال مليون عنصر جديد في المجموعة 1.81 ثانية أو 552 ألف إدخال في الثانية.
  • استغرق تحديث قيمة في نفس الوقت العالمي 1،000،000 مرة 1.98 ثانية أو 505 ألف تحديثات في الثانية. حقيقة مثيرة للاهتمام هو أن يحدث الإدراج من التحديث. يبدو أن هذا نتيجة لتحسين قاعدة البيانات الأولية للإدخال السريع.

من الواضح أن هذه الاختبارات لا يمكن أن تدعي أنها دقيقة ومفيدة ، لأنها بدائية ، مصنوعة في حاوية. على أجهزة أكثر قوة مع نظام قرص PCIe SSD ، يمكن تحقيق عشرات الملايين من الإدخالات في الثانية.

ما يمكن أن تكتمل والحالة الحالية


  1. يمكنك إضافة وظائف مفيدة للتعامل مع المعاملات (لا يزال بإمكانك استخدامها من خلال iris_exec).
  2. لا يتم تنفيذ وظيفة إرجاع الهيكل العام بالكامل بحيث لا يتجاهل PHP العمومي.
  3. لم يتم تنفيذ وظيفة حفظ مجموعة PHP كشجرة فرعية.
  4. لم يتم تطبيق الوصول إلى متغيرات قاعدة البيانات المحلية. فقط من خلال iris_exec ، على الرغم من أنه أفضل من خلال iris_set.
  5. لم تنفذ تجاوز العالمية في العمق في الاتجاه المعاكس.
  6. لا يتم تطبيق الوصول إلى قاعدة البيانات من خلال الكائن باستخدام أساليب (مشابهة للوظائف الحالية).

من المحتمل ألا تكون الوحدة الحالية جاهزة للإنتاج: لم تكن هناك اختبارات للأحمال الكبيرة وتسريبات الذاكرة. ومع ذلك ، إذا كان هناك من يحتاج إليها ، فاتصل بي (سيرجي كامينيف update@mail.ru).

الخاتمة


لفترة طويلة ، لم تتقاطع عوالم PHP والقواعد الهرمية على العالم ، على الرغم من أن globals توفر وظائف قوية وسريعة على أنواع بيانات محددة (طبية ، شخصية).

آمل أن تكون هذه الوحدة بمثابة حافز للتجارب من قبل مبرمجي PHP مع مبرمجين عالميين ومبرمجي ObjectScript لتطوير بسيط لواجهات الويب في PHP.

سكرتير خاص شكرا لاهتمامكم!

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


All Articles