Zuordnen von Daten aus einer relationalen Datenbank

Manchmal treten Situationen auf, in denen die Lösung des Problems des Abrufs von Daten aus einer relationalen Datenbank nicht in die Funktionen des im Projekt verwendeten ORM passt, beispielsweise aufgrund der unzureichenden Geschwindigkeit des ORM selbst oder der nicht ganz optimalen SQL-Abfragen, die von ihm generiert werden. In diesem Fall müssen Sie Abfragen normalerweise manuell schreiben.

Das Problem besteht darin, dass die Daten aus der Datenbank (auch als Antwort auf eine JOIN-Anforderung) als "flaches" zweidimensionales Array zurückgegeben werden, das nicht die komplexe "Baum" -Struktur der Anwendungsdaten widerspiegelt. Es ist äußerst unpraktisch, mit einem solchen Array weiter zu arbeiten, daher ist eine mehr oder weniger universelle Lösung erforderlich, um dieses Array gemäß einem gegebenen Muster in eine geeignetere Form zu bringen.

Die Lösung wurde gefunden, bequem und schnell genug.

Wie schnell


Um die Geschwindigkeit der Bibliothek zu beurteilen, habe ich einen kleinen Prüfstand zusammengestellt, auf dem die Geschwindigkeit meiner Bibliothek mit der Geschwindigkeit von Eloquent verglichen wird. Für Messungen wurde das phpbench-Paket verwendet.

So stellen Sie einen Stand zu Hause auf:

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

Hier habe ich das in meinem vorherigen Artikel beschriebene Tool verwendet .

Dann wählen wir im Menü: 1 Entwickeln, dann: 1 Erstellen, dann 2 Bereitstellen und Hochfahren;
Führen Sie dann die Tests aus. 5. Führen Sie Tests aus

. Die Datenbank enthält 3000 Bücher. Die Ergebnisse sind wie folgt:

+-----------------+-----+------+------+-------------+--------------+
| 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 - zieht alle Bücher mit den Autoren Eloquent mit
benchEloquentId - zieht ein bestimmtes Buch mit den Autoren Eloquent mit (10 - mal)

benchProc - zieht alle Bücher mit den Autoren der Bibliothek
benchProcId - zieht ein bestimmtes Buch mit den Autoren der Bibliothek (10)

zu betätigen , Tests sind nicht repräsentativ genug, aber der Unterschied ist sowohl in der Laufzeit als auch im Speicherverbrauch spürbar.

Wie es funktioniert


Installieren:

composer require hrustbb2/arrayproc:v1.0.0

Stellen Sie sich zum Beispiel (extrem einfach) vor, wir hätten eine Datenbank mit Büchern und Autoren mit der folgenden Struktur.

Bild

Die Aufgabe besteht darin, alle Bücher mit ihren Autoren herauszuholen.

Die Anfrage sieht ungefähr so ​​aus:

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

Als Antwort erhalten wir über ein solches Array von Daten.

book.idbook.nameauthor.idAutorenname
1Buch 12author2
1Buch 14author4
1Buch 16author6
2book22author2
2book23author3
2book26author6
2book27author7


Das Array ist zweidimensional, einige Felder sind dupliziert. Zur Vereinfachung müssen Sie es konvertieren
[
	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'
			],
		]
	],
]


Ändern Sie dazu leicht unsere Anfrage:


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

Hier setzen wir Aliase im Abschnitt SELECT: für Felder mit Daten zu Büchern, Aliase mit dem Präfix 'book_' und für Felder mit Informationen zu Autoren mit dem Präfix 'author'.

Als nächstes konvertieren wir die Datenbankantwort

use hrustbb2\arrayproc\ArrayProcessor;

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

Dabei gilt:

$ rows ist die Datenbankantwort in Form eines Arrays von Objekten / stdClass ()
$ config ist ein assoziatives Array, das die Datenstruktur des resultierenden Arrays

widerspiegelt. Daher haben wir in $ booksData ein baumartiges Array mit der in $ config beschriebenen Struktur, das mit den entsprechenden Daten gefüllt ist.

Irgendwie so.

All Articles