في بعض الأحيان تنشأ المواقف عندما لا يتناسب حل مشكلة استرداد البيانات من قاعدة بيانات علائقية مع إمكانات ORM المستخدمة في المشروع ، على سبيل المثال ، إما بسبب السرعة غير الكافية لـ ORM نفسه ، أو ليس استعلامات SQL المثالية تمامًا الناتجة عن ذلك. في هذه الحالة ، عليك عادةً كتابة الاستعلامات يدويًا.المشكلة هي أن البيانات من قاعدة البيانات (بما في ذلك استجابة لطلب JOIN) يتم إرجاعها على هيئة صفيف ثنائي الأبعاد "مسطح" لا يعكس هيكل "الشجرة" المعقد لبيانات التطبيق. من غير الملائم للغاية العمل مع مثل هذا المصفوفة بشكل أكبر ، لذلك ، يلزم حل عالمي أكثر أو أقل لإحضار هذا المصفوفة إلى شكل أكثر ملاءمة وفقًا للنمط المحدد.تم العثور على الحل ، مريح وسريع بما فيه الكفاية.مدى السرعة
لتقييم سرعة المكتبة ، قمت بتجميع منصة اختبار صغيرة يتم فيها مقارنة سرعة مكتبتي مع سرعة Eloquent. للقياسات ، تم استخدام حزمة phpbench.من أجل نشر حامل في المنزل:git clone https://github.com/hrustbb2/env-arrayproc-bench.git
cd env-arrayproc-bench
./env
هنا استخدمت الأداة الموضحة في مقالتي السابقة .ثم في القائمة ، نختار: 1 تطوير ، ثم: 1 بناء ، ثم 2 نشر وأعلى ؛ثم شغّل الاختبارات 5. شغّل الاختباراتهناك 3000 كتاب في قاعدة البيانات. النتائج كما يلي:+-----------------+-----+------+------+-------------+--------------+
| subject | set | revs | iter | mem_peak | time_rev |
+-----------------+-----+------+------+-------------+--------------+
| benchEloquent | 0 | 1 | 0 | 76,442,912b | 12,781.612ms |
| benchEloquentId | 0 | 10 | 0 | 5,123,224b | 16.432ms |
| benchProc | 0 | 1 | 0 | 36,364,176b | 1,053.937ms |
| benchProcId | 0 | 10 | 0 | 4,462,696b | 7.684ms |
+-----------------+-----+------+------+-------------+--------------+
benchEloquent - تسحب جميع الكتب مع المؤلفين باستخدامEloquent benchEloquentId - تسحب كتابًا معينًا مع المؤلفين باستخدامEloquent (10 مرات) benchProc - تسحب جميع الكتب مع المؤلفين باستخدام مكتبةbenchProcId - تسحب كتابًا معينًا مع المؤلفين باستخدام المكتبة (10)للتفعيل الاختبارات ليست ممثلة بما فيه الكفاية ، ولكن الفرق ملحوظ ، سواء في وقت التشغيل أو في استهلاك الذاكرة.كيف تعمل
تثبيت:composer require hrustbb2/arrayproc:v1.0.0
علاوة على ذلك ، على سبيل المثال (بسيط للغاية) ، تخيل أن لدينا قاعدة بيانات من الكتب والمؤلفين بالهيكل التالي.
المهمة هي سحب كل الكتب مع مؤلفيها.سيبدو الطلب على النحو التالي:SELECT
books.id,
books.name,
authors.id,
authors.name
FROM
books
LEFT JOIN relations ON relations.books_id = books.id
LEFT JOIN authors ON authors.id = relations.authors_id
واستجابة لذلك ، نحصل على مثل هذه المجموعة من البيانات.الصفيف ثنائي الأبعاد ، بعض الحقول مكررة ، للراحة تحتاج إلى تحويله[
1 => [
'id' => 1,
'name' => 'book1',
'authors' => [
2 => [
'id' => 2,
'name' => 'author2'
],
4 => [
'id' => 4,
'name' => 'author4'
],
6 => [
'id' => 6,
'name' => 'author6'
],
]
],
2 => [
'id' => 2,
'name' => 'book2',
'authors' => [
2 => [
'id' => 2,
'name' => 'author2'
],
3 => [
'id' => 3,
'name' => 'author3'
],
6 => [
'id' => 6,
'name' => 'author6'
],
7 => [
'id' => 7,
'name' => 'author7'
],
]
],
]
للقيام بذلك ، قم بتعديل طلبنا قليلاً:
SELECT
books.id AS book_id,
books.name AS book_name,
authors.id AS author_id,
authors.name AS author_name
FROM
books
LEFT JOIN relations ON relations.books_id = books.id
LEFT JOIN authors ON authors.id = relations.authors_id
نقوم هنا بتعيين الأسماء المستعارة في قسم SELECT: للحقول التي تحتوي على بيانات حول الكتب ، والأسماء المستعارة بالبادئة "book_" ، والحقول التي تحتوي على معلومات حول المؤلفين بالبادئة "المؤلف".بعد ذلك ، نقوم بتحويل استجابة قاعدة البياناتuse hrustbb2\arrayproc\ArrayProcessor;
$arrayProcessor = new ArrayProcessor();
$config = [
'prefix' => 'book_',
'authors' => [
'prefix' => 'author_',
]
]
$booksData = $arrayProcessor->process($conf, $rows)->resultArray();
حيث:$ rows هو استجابة قاعدة البيانات في شكل مصفوفة من الكائنات / stdClass ()$ config هو مصفوفة ترابطية تعكس بنية بيانات المصفوفة الناتجةونتيجة لذلك ، في $ booksData لدينا مصفوفة تشبه الشجرة لها البنية الموضحة في $ config ، مليئة بالبيانات المقابلة.شيء من هذا القبيل.