Business Intelligence in Russisch - Quintette

In einem unserer Blog-Notizen haben wir den Ansatz zur Speicherung und Verarbeitung von Daten behandelt , über den wir einige durchaus erwartete Fragen zu einem solchen Plan erhalten haben: „Im Allgemeinen warten wir auf die Implementierung, jetzt fliegt es ...“. Basierend auf den Ergebnissen mehrerer Implementierungen werde ich am Beispiel einer unserer Entwicklungen über die Vor- und Nachteile dieses Ansatzes sprechen.


Wir bieten unseren Kunden normalerweise ein ziemlich leistungsfähiges und flexibles BI-Tool, das alle ihre Probleme lösen kann. Dies ist jedoch ein ausländisches Handelsprodukt, und die Kunden interessieren sich zunehmend für das Thema Importsubstitution. Um unsere diesbezüglichen Perspektiven zu untersuchen, haben wir begonnen, unser eigenes BI-Toolset mit Open-Source-Lösungen und einer quintettbasierten Entwicklungsplattform zu testen.




Wir haben unser bestehendes kommerzielles Produkt als Referenz genommen und werden, wann immer möglich, einen Vergleich damit durchführen.


Die Aufgabe bestand darin, folgende Komponenten zu erstellen:


  • eine Datenbank zum Speichern von Data Marts und Serviceinformationen (Benutzer, Einstellungen usw.);
  • Webschnittstelle des Systems und seines ORM;
  • BI-Funktionalität - Laden von Daten, benutzerdefinierte Berichte, Diagramme, Pivot-Tabellen.

Als Grundlage haben wir eine Entwicklungsplattform verwendet , die ein Datenmodell, einen Abfrage-Designer und eine Vorlagen-Engine enthält und ein Vorbild für die Benutzerzugriffskontrolle unterstützt.


Gegenstand der Bestellung ist die Abstimmung von Kontoauszügen und die Analyse der in den letzten 7 Jahren gesammelten Daten. Die Quelldaten werden in HDFS gespeichert, die Berichte selbst werden an derselben Stelle berechnet und ihre Ergebnisse fallen in das Fenster der relationalen Datenbank. Storefronts enthalten etwa 300 GB Daten für mehrere Dutzend verschiedene Berichtsformulare und mehrere hundert verwandte Berichte. Das System sollte 20 Benutzer bei Spitzenlast bedienen, die Antwortzeit der Schnittstelle sollte innerhalb von 1 Sekunde liegen.


Das Erstellen einer Datenstruktur hat nicht viel Zeit in Anspruch genommen: Mit dem Plattformtyp-Editor können Sie Geschäftsobjekte unverändert erstellen und beschreiben, ohne die Benutzeranforderungen an die Besonderheiten der Umgebung anpassen zu müssen (Datentypen und -dimensionen, Schlüssel, Einschränkungen, Datenfeldnamen, Bezeichner usw.). Dies ist das erste Plus der Quintette, die wir reparieren können.


So entsteht die Datenstruktur - wir definieren die notwendigen Begriffe und bilden daraus die Objekte unseres Themenbereichs:



Nach einigen Minuten Aktivität im Copy / Paste-Format haben wir die erforderliche Datenstruktur für ein Formular und mehrere Hilfsverzeichnisse dafür erhalten. Die Struktur der Formulardaten (nach Zerlegung durch den Analytiker) sieht folgendermaßen aus:




Ein Analyst, der mit dem Geschäftssinn der hier präsentierten Daten vertraut ist, lautet wie folgt: Jede F110-Instanz (Formular 110 in der CB-Terminologie) hat eine bestimmte Genauigkeit (sie kann „genau“ oder „gerundet“ sein) und enthält eine Reihe von Codes, für die jeweils Beträge in Rubel und Währung sind angegeben.


Im Datennavigator, in dem die Daten gemäß der angegebenen Struktur dargestellt werden, sehen wir eine solche Tabelle über die im System vorhandenen Formularinstanzen:




Der identifizierende Wert des Formulars ist sein Berichtsdatum. Die Berichtscodes werden in Form eines untergeordneten Arrays gespeichert, dessen Größe in Klammern angegeben ist.


Wie bereits erwähnt, haben wir die Daten im Vergleich zur ursprünglichen Struktur ein wenig zerlegt, um keine langen Zeilen sich wiederholender Werte in der Datenbank zu speichern, wie dies ein Programmierer oder Datenbankadministrator sieht:


Tabelle mit Daten im Referenzsystem:


Aus diesem Grund positionieren wir die Plattform (im Folgenden Integral genannt) als Entwicklungswerkzeug für den Analysten und nicht für den Programmierer.


Die Hilfsdatenstruktur ist nicht wesentlich größer, da sie alle Anfangsdaten, Berichtseinstellungen, Regeln zur Überprüfung der Integrität der Daten im Bericht und in den zugehörigen Berichten, den Verlauf der Berechnungen und Abstimmungen sowie einige Regeln für die Datengeschäftstransformation während der Berichtserstellung speichert:



(Die Struktur ist nicht vollständig angegeben)


Wenn die Datenstruktur fertig ist, können Sie Daten in sie laden. Am einfachsten ist es, eine im Integral-Format erstellte Datei hochzuladen (analog zu .csv, jedoch mit Typ-Markup). Dieses Format enthält eine Beschreibung der Daten und der Daten selbst.


Datei anzeigen

Im folgenden Beispiel beschreiben die ersten drei Zeilen der Datei die Struktur des Formulars (wenn es nicht im System vorhanden ist, wird es erstellt) und dann die Daten selbst - die Formularparameter und die Parameter der ihm untergeordneten Berichtsobjekte.


268:110:DATE;277;270; 277::SHORT; 270:  :SHORT;  :SIGNED;   :SIGNED; 268::20121231;281;; 270::A/5.2;1233682389.47;; 277:281:; 270::A/5.3;622836720.22;; 270::A/6.4;19800;; 270::A/9.2;27125165.14;; 270::S16203/1.2;608607846.309999;; 270::S16305/4;2727510994.84;; 270::S16305/4.1;32049069.51;; 270::S16305/14;2737711.65;; 270::S25302/4;2725748122.98999;; 270::S25302/4.1;40952511.36;; 270::IL/2;87429694.5699999;62717458.21; 270::IL/4;33517212.95;; 270::IL/9;1423281.69;8278.24; 270::IL/11;86433534.5699999;519956.63; 270::IA/1;147792224.509999;4517060.94; 270::IA/2;737704.92;; 270::IA/3;27099836.07;2637.79; 270::IA/6;5607868.86;408410.4; 270::IA/8;103837028.49;48841202.69; 270::IA/10;112302573.56;; 268::20121231;280;; 270::A/5.2;1233682;; 277:280:; 270::A/5.3;622837;; 270::A/6.4;20;; 270::A/9.2;27125;; 270::S16203/1.2;608608;; 

Für dieses Formular verfügt die Datenbank über 4470 Berichtsdaten, die beim Entladen in eine flache Datei etwas mehr als 1 MB benötigen. In der ursprünglichen Datenbank (Oracle) belegen sie 3,1 MB (ohne Indizes) in normalisierter Form und 4,2 MB in einer denormalisierten Storefront, die wir als Quintette wiederholen möchten. Quintette werden indiziert und normalisiert, und in ihrem Format belegen diese Daten bereits 10 MB.


Die zu vergleichenden Datenmengen sind in der Tabelle (in Megabyte) zusammengefasst:
TextRDBMSQuintette
Daten1.13.15.1
Denormalisiert4.2
Indizes6.25.1
Daten + Indizes9.310.2

An dieser Stelle sollte auf die Größe geachtet werden, die die Grundlagen für die verglichenen Ansätze einnehmen. Aufgrund der zusätzlichen Normalisierung von Quintetten und Ausgaben für zusammengesetzte Indizes in der Referenzbasis ist die Gesamtgröße der Datenbanken nahezu gleich.


Referenzbasis:


Quintette:


Darüber hinaus haben wir in Integral sofort alle Felder der Tabelle und im Referenzsystem indiziert - nur Datum, Code und Menge in Rubel, was zusätzliche Kosten erfordert, wenn neue Anforderungen auftreten.


Als Referenz: In der Datenbank beträgt die Gesamtgröße dieses Formulars, einschließlich unterstützender Berichte und Einstellungen, ca. 400 MB (es ist relativ klein).


Die Daten werden also hochgeladen und der schwierigste Teil des Projekts liegt vor uns - die Erstellung einer Schnittstelle. Über die Schnittstelle des Referenzsystems können Sie die Daten von Formularen, unterstützenden Berichten, Einstellungen und den Lebenszyklus von Formularen anzeigen. Um den Zugriff zu verwalten und mit der Datenbank zu kommunizieren, haben wir die grundlegenden Funktionen unserer Plattform verwendet - ein Vorbild und einen Berichtsdesigner.


Die Liste der Benutzer mit ihren Rollen sieht folgendermaßen aus:




Wenn Sie auf den Rollennamen klicken (in der Abbildung oben mit einem roten Oval markiert), können Sie sich dessen Inhalt ansehen:




Rollenobjekte können auf 3 Zugriffsebenen eingestellt werden, Maske kann verwendet werden:




Die Datenbearbeitung erfolgt ebenfalls über die Basisschnittstelle. Hier ist zum Beispiel ein Benutzerbearbeitungsformular:




Wir haben das spezifische Menü unserer Anwendung und ihrer Arbeitsplätze in einer kompakten Datei angeordnet, da sie alle vom gleichen Typ sind: ein Anforderungsformular mit 2-3 Elementen und eine Tabelle mit den Ergebnissen der Anforderungen.




Die Architektur erwies sich als sehr einfach: Wir haben viele Datenanforderungen (Ansichten) erstellt und ein Plug-In geschrieben, das beliebige Datenbeispiele in den in diesen Ansichten enthaltenen Tabellen und Feldern implementiert.


Zum Beispiel haben wir einen sogenannten Entschlüsselungsbericht zu Form 110, der nicht aggregierte Daten enthält, auf denen er aufgebaut ist. So sieht dieser Bericht aus:




Um die Richtigkeit des Formulars zu überprüfen, sollte der Benutzer in der Lage sein, eine Auswahl zu treffen, zu sortieren, zu filtern, zu gruppieren, zu transponieren sowie eigene berechnete Felder zu erstellen. Unser Plugin wird über die Schaltfläche "Aktionen" oben in der Tabelle aufgerufen.




Das Plugin wiederholt die Funktionalität des Integral Query Builder, kann aber nicht nur Daten abrufen, sondern auch Diagramme und Pivot-Tabellen zeichnen. Zum Beispiel müssen wir nach Abschnitt filtern, ein Paar berechneter Spalten hinzufügen und eine Auswahl der nach ihnen gruppierten Beträge treffen. Wir setzen das alles:




Neue Spalten werden der Liste über den gleichnamigen Link hinzugefügt. Mit der Schaltfläche „Berechnungen“ legen wir die Formeln für sie mit einem einfachen Konstruktor fest:




Wir legen eine neue Spaltenreihenfolge fest und klicken auf "Übernehmen". Unser Bericht wird nach Bedarf geändert. Anstelle von 7 Basisspalten werden drei angezeigt, von denen zwei gerade erstellt wurden:




Wie funktioniert es unter der Haube?

Das Plugin kommuniziert mit dem Webdienst der Anwendung über die API und hat die folgende Anfrage ausgeführt:


 api/neo/report/1392573?FR_date=20181231&FR_%D0%A0%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB=&FR_%D0%9A%D0%BE%D0%B4_%D0%BE%D0%B1%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F=&SELECT=LEFT(\:1392578\:\,5),SUBSTRING(\:1392578\:\,6\,3),1392617:SUM&ORDER=1392617&FR_%D0%A0%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB=1&TOTALS=1392617:SUM&LIMIT=10 

Und ich habe diese Antwort bekommen:


 { «columns»: [ «LEFT(:1392578:,5)», «SUBSTRING(:1392578:,6,3)», «1392617» ], «formats»: [ «SHORT», «SHORT», «SIGNED» ], «data»: { «LEFT(:1392578:,5)»: [ «60324», «40817», «47425», «47404», «60302», «47404» ], «SUBSTRING(:1392578:,6,3)»: [ «810», «810», «810», «840», «810», «978» ], «  »: [ «153 825.71», «527 901.11», «2 415 189.23», «3 000 000.02», «5 588 330.88», «58 000 000.00» ] }, «totals»: [ «„, “», «69 685 246.95» ] } 

Wenn jemand daran interessiert ist, welche echte SQL-Abfrage in der Quintett-Datenbank ausgeführt wurde, dann ist es hier:


SQL anzeigen

Der Analyst sieht diese SQL nicht und verwendet den unten beschriebenen Abfrage-Generator.


 SELECT LEFT(a182088.val, 5) v13, SUBSTRING(a182088.val, 6, 3) v14, SUM(round(a182090.val, 2)) '  ' FROM neo a182081 LEFT JOIN neo a182083 ON a182083.up=a182081.id AND a182083.t=182083 LEFT JOIN neo a182088 ON a182088.up=a182083.id AND a182088.t=182088 LEFT JOIN neo a182090 ON a182090.up=a182083.id AND a182090.t=182090 LEFT JOIN neo a182091 ON a182091.up=a182083.id AND a182091.t=182091 LEFT JOIN neo a182092 ON a182092.up=a182083.id AND a182092.t=182092 LEFT JOIN neo a299 ON a299.t=299 AND a182083.val=a299.val LEFT JOIN neo a328 ON a328.up=a299.id AND a328.t=328 LEFT JOIN neo a303 ON a303.up=a299.id AND a303.t=303 LEFT JOIN neo a304 ON a304.up=a299.id AND a304.t=304 LEFT JOIN neo a182089 ON a182089.up=a182083.id AND a182089.t=182089 WHERE a182081.up!=0 AND length(a182081.val)!=0 AND a182081.t=182081 AND a182081.val='20181231′ AND a328.val ='1AND a303.val>='19000101′ AND a303.val<='20181231AND a304.val>='20181231′ AND a304.val<='20991231GROUP BY v13, v14 ORDER BY CAST(SUM(round(a182090.val, 2)) AS SIGNED) LIMIT 10 

Die Anforderung erscheint möglicherweise etwas komplizierter als erwartet, da die aktuellen Daten der Berichtscodes anhand ihrer Gültigkeit ausgewählt werden. Im Integral Report Builder besteht diese Abfrage bei Bedarf aus Berichtsspalten, Parametern und Tabellenverknüpfungsbedingungen.




Das Integral selbst kann Tabellenverbindungsbedingungen generieren, da alle durch Quintettbeziehungen bestimmt werden. Bei der Versionierung mussten wir die Tabellen jedoch manuell kombinieren und die Bedingung für JOIN explizit angeben. Codes in der ON-Klausel sind Bezeichner für Spalten- und Abfrageobjekte.


Die Abfrage kombiniert drei Tabellen und wählt aus ihnen die folgenden Datenfelder aus (erforderliche "Abfragespalten"):



(Bild in voller Größe)

Hier werden die Berichtsspalten, berechneten Felder, Filter usw. aufgelistet, aus denen die SQL-Abfrage besteht. Mit dem Berichts-Generator können Sie nahezu jedes Design der SQL-Sprache implementieren, einschließlich des Verbindens von Abfragen und verschachtelten Abfragen.



Zusätzlich zur Auswahl mit Gruppierungen kann der Benutzer den Mechanismus von Pivot-Tabellen verwenden. Wir haben unser Plugin um das beliebte Tabellen-Tool pivottable.js.org erweitert .
Wählen Sie die für uns interessanten Spalten aus und wechseln Sie in den Pivot-Tabellenmodus:




Hier können wir mit drag'n'drop die Daten analysieren, die von der von uns konfigurierten Stichprobe empfangen wurden, einschließlich unserer beliebigen Felder. Außerdem können Sie hier zusätzlich Daten nach beliebigen Feldern filtern.




Wir haben das kostenlose Produkt www.amcharts.com verwendet, um Grafiken zu zeichnen. Wie bei Pivottable ist auch hier alles ganz einfach: Wir wählen den Diagrammtyp aus und initialisieren die Komponente mit unserem von Integral erhaltenen Datenarray:




Damit haben wir die Aufgabe tatsächlich so weit erledigt, dass die Benutzer des vorhandenen Produkts zufrieden sind. Jetzt haben wir ein System, das die Anforderungen der Importsubstitution erfüllt: Alle Produkte sind kostenlos und austauschbar. Ja, wir haben bei weitem nicht alle Möglichkeiten erkannt, die das bestehende System bietet, sondern nur diejenigen, die für diesen Kunden notwendig sind. Aber wir haben gerade erst angefangen!



Also geflogen oder nicht?


Wir sollten auch die Leistung des resultierenden Systems diskutieren. Bei diesem Problem wirken sich die Stichproben bei einer ausreichend großen Datenmenge (Hunderte von Gigabyte) auf kleine Fragmente aus, deren Quintette immer mithilfe von Indizes erfasst werden. Dies führt dazu, dass Abfragen bei jeder Größe der Datenbank mit einer akzeptablen Geschwindigkeit verarbeitet werden, ohne dass es zu einer Lawinen-ähnlichen Leistungsverschlechterung kommt.


Wir haben 20 Benutzeraktionen in einem Testskript aufgezeichnet und auf dem Dienst loadimpact.com ausgeführt . Es stellte sich heraus, dass 27 verschiedene Anforderungen vorliegen, da einige Aktionen in zwei Anforderungen an den Server ausgeführt werden (z. B. zum Erstellen einer Seitenanzeige).


Das Testskript stellte sich so heraus
 import { group, sleep } from 'k6′; import http from 'k6/http'; // Version: 1.3 // Creator: Load Impact URL test analyzer export let options = { stages: [ { «duration»: «3m0s», «target»: 25 } ], maxRedirects: 0, discardResponseBodies: true, }; export default function() { group("page_1 — https://*****.ru/neo/dict«, function() { let req, res; req = [{ «method»: «get», «url»: «https://*****.ru/neo/info», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «upgrade-insecure-requests»: «1», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8» } } }]; res = http.batch(req); sleep(0.62); req = [{ «method»: «get», «url»: «https://*****.ru/neo/info», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «upgrade-insecure-requests»: «1», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392573?FR_date=20181231&LIMIT=10», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392573?FR_date=20181130&ORDER=1392617&LIMIT=10&RECORD_COUNT», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392573?FR_date=20181031», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392573?FR_date=20180930&RECORD_COUNT», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «*/*», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1387723?&LIMIT=10», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «*/*», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1387723?&LIMIT=10&RECORD_COUNT», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «*/*», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392741?», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392757?&LIMIT=10», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392768?&LIMIT=10», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/download/neo/img/nav_dropdown_arrow.svg», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/download/neo/img/nav_detailed_report.svg», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/download/neo/img/nav_classifiers.svg», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/download/neo/img/nav_launch_report.svg», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/download/neo/img/nav_manage_form_status.svg», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/download/neo/img/nav_quality_management.svg», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/download/neo/img/nav_download.svg», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «image/webp,image/apng,image/*,*/*;q=0.8», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/download/neo/css/variables.css», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392779?&LIMIT=10», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392538?&LIMIT=10&RECORD_COUNT», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/edit_obj/1392129», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/edit_obj/1390552», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/object/18», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1387723?&LIMIT=140,10», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1387723?&LIMIT=140,10&RECORD_COUNT», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392573?FR_date=20180731&FR_%D0%A0%D0%B0%D0%B7%D0%B4%D0%B5%D0%BB=&FR_%D0%9A%D0%BE%D0%B4_%D0%BE%D0%B1%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F=&SELECT=1392576,1392617:SUM,1392589&LIMIT=100», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392678?FR_date=20180831&FR_section=1&SELECT=1392698,1392685,1392690&LIMIT=10», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392678?FR_date=20180630&FR_section=1&SELECT=1392698,1392685,1392690&LIMIT=10&RECORD_COUNT», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392678?FR_date=20180531&FR_section=1&SELECT=1392698,1392685,1392690&LIMIT=500», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392678?FR_date=20181231&FR_section=2&SELECT=1392698,1392685,1392690&LIMIT=500», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392678?FR_date=20181231&FR_section=4&SELECT=1392698,1392685,1392690,1392694&LIMIT=20», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/report/1392678?FR_date=20181231&FR_section=4&SELECT=1392698,1392685,1392690,1392694&LIMIT=20&RECORD_COUNT», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/neo/info», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/api/neo/report/1392678?FR_date=20190131&FR_section=1&FR_precision=280&SELECT=1392698,1392685,1392715&LIMIT=50», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/api/neo/report/1392678?FR_date=20190131&FR_section=1&FR_precision=280&SELECT=1392698,1392685,1392715&LIMIT=50&RECORD_COUNT», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/api/neo/report/1392573?FR_date=20190131&FR_section=1&FR_precision=280&FR_%D0%9A%D0%BE%D0%B4_%D0%BE%D0%B1%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F=A60302/9&LIMIT=10», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://*****.ru/api/neo/report/1392573?FR_date=20190131&FR_section=1&FR_precision=280&ORDER=1392617&FR_%D0%9A%D0%BE%D0%B4_%D0%BE%D0%B1%D0%BE%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F=A60302/9&LIMIT=10», «params»: { «headers»: { «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «text/css,*/*;q=0.1», «referer»: «https://*****.ru/neo/dict» } } },{ «method»: «get», «url»: «https://fonts.gstatic.com/s/roboto/v19/KFOmCnqEu92Fr1Mu4mxP.ttf», «params»: { «headers»: { «origin»: «https://*****.ru», «accept-encoding»: «gzip, deflate», «accept-language»: «en-US», «user-agent»: «Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/62.0.3183.0 Safari/537.36», «accept»: «*/*», «referer»: «https://fonts.googleapis.com/css?family=Roboto» } } }]; res = http.batch(req); // Random sleep between 5s and 10s sleep(Math.floor(Math.random()*5+5)); }); } 


Folgendes haben wir gesehen, als wir das Skript ausgeführt haben: Der Lastgenerator hat unserer Anwendung eine zunehmende Anzahl von Anforderungen pro Sekunde gesendet. Wir haben eine klassische Leiter, um nach maximaler / maximaler Leistung zu suchen:




Dieser Generator sendet Anforderungen stapelweise und nicht gleichmäßig, wie dies bei gleichzeitigen Benutzern der Fall wäre. Daher zeigt das Diagramm Lastspitzen, und die Gesamtleistung sieht in diesem Modus ebenfalls schlechter aus.


:




, - SQL-. , , 8 33 SQL- : , -, SQL- ( , ) .


, 20-25 ( 20 ), — 1 . , : 1 2.4 1 .


( 10 ) 0.1-0.3 , .


, .

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


All Articles