Memetakan data dari database relasional

Kadang-kadang situasi muncul ketika solusi untuk masalah pengambilan data dari database relasional tidak sesuai dengan kemampuan ORM yang digunakan dalam proyek, misalnya, baik karena kecepatan ORM itu sendiri yang kurang, atau permintaan SQL yang tidak cukup optimal yang dihasilkan olehnya. Dalam hal ini, Anda biasanya harus menulis kueri secara manual.

Masalahnya adalah bahwa data dari database (termasuk dalam menanggapi permintaan BERGABUNG) dikembalikan sebagai array dua dimensi "datar" yang tidak mencerminkan struktur "pohon" kompleks dari data aplikasi. Sangat tidak nyaman untuk bekerja dengan array seperti itu lebih lanjut, oleh karena itu, diperlukan solusi yang kurang lebih universal untuk membawa array ini ke bentuk yang lebih cocok sesuai dengan pola yang diberikan.

Solusinya ditemukan, nyaman dan cukup cepat.

Seberapa cepat


Untuk mengevaluasi kecepatan perpustakaan, saya mengumpulkan bangku tes kecil di mana kecepatan perpustakaan saya dibandingkan dengan kecepatan Eloquent. Untuk pengukuran, paket phpbench digunakan.

Untuk menggelar stand di rumah:

git clone https://github.com/hrustbb2/env-arrayproc-bench.git
cd env-arrayproc-bench
./env

Di sini saya menggunakan alat yang dijelaskan dalam artikel saya sebelumnya .

Kemudian di menu kita pilih: 1 Develop, lalu: 1 Build, lalu 2 Deploy and Up;
Kemudian jalankan tes 5. Jalankan tes

Ada 3.000 buku dalam database. Hasilnya adalah sebagai berikut:

+-----------------+-----+------+------+-------------+--------------+
| 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 - mencabut semua buku dengan penulis menggunakan
Eloquent benchEloquentId - mencabut buku tertentu dengan penulis menggunakan Eloquent (10 kali)

benchProc - mencabut semua buku dengan penulis menggunakan perpustakaan
benchProcId - mengeluarkan buku tertentu dengan penulis menggunakan perpustakaan (10)

untuk menjalankan tes tidak cukup representatif, tetapi perbedaannya terlihat, baik dalam runtime dan konsumsi memori.

Bagaimana itu bekerja


Install:

composer require hrustbb2/arrayproc:v1.0.0

Selanjutnya, sebagai contoh (sangat sederhana), bayangkan bahwa kita memiliki database buku dan penulis dengan struktur berikut.

gambar

Tugasnya adalah untuk mengeluarkan semua buku dengan penulisnya.

Permintaan akan terlihat seperti ini:

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

Sebagai tanggapan, kami mendapatkan tentang array data seperti itu.

book.idbook.nameauthor.idauthor.name
1buku12penulis2
1buku14penulis4
1buku16penulis6
2buku22penulis2
2buku23penulis3
2buku26penulis6
2buku27penulis7


Array ini dua dimensi, beberapa bidang digandakan, untuk kenyamanan Anda perlu mengubahnya
[
	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'
			],
		]
	],
]


Untuk melakukan ini, ubah sedikit permintaan kami:


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

Di sini kami menetapkan alias di bagian SELECT: untuk bidang dengan data tentang buku, alias dengan awalan 'book_', dan untuk bidang dengan informasi tentang penulis dengan awalan 'penulis'.

Selanjutnya, kami mengonversi respons basis data

use hrustbb2\arrayproc\ArrayProcessor;

$arrayProcessor = new ArrayProcessor();
$config = [
	'prefix' => 'book_',
	'authors' => [
		'prefix' => 'author_',
	]
]
$booksData = $arrayProcessor->process($conf, $rows)->resultArray();

di mana:

$ rows adalah respons basis data dalam bentuk array objek / stdClass ()
$ config adalah array asosiatif yang mencerminkan struktur data dari array yang dihasilkan.

Akibatnya, dalam $ booksData kita memiliki array mirip pohon yang memiliki struktur yang dijelaskan dalam $ config, diisi dengan data yang sesuai.

Sesuatu seperti ini.

All Articles