Spark – chatgpz.de – KI-Tools & Praxiswissen http://chatgpz.de Unabhängige Tests, Anleitungen und Hintergründe zu KI-Tools. Sat, 01 Nov 2025 08:48:31 +0000 de-DE hourly 1 https://wordpress.org/?v=6.4.2 234900186 So bauen Sie mit Apache Spark und PySpark eine Finish-to-Finish-Pipeline für Datentechnik und maschinelles Lernen auf http://chatgpz.de/artificial-intelligence/so-bauen-sie-mit-apache-spark-und-pyspark-eine-finish-to-finish-pipeline-fuer-datentechnik-und-maschinelles-lernen-auf/ http://chatgpz.de/artificial-intelligence/so-bauen-sie-mit-apache-spark-und-pyspark-eine-finish-to-finish-pipeline-fuer-datentechnik-und-maschinelles-lernen-auf/#respond Sat, 01 Nov 2025 08:48:30 +0000 http://chatgpz.de/artificial-intelligence/so-bauen-sie-mit-apache-spark-und-pyspark-eine-end-to-end-pipeline-fuer-datentechnik-und-maschinelles-lernen-auf/ [ad_1]

!pip set up -q pyspark==3.5.1
from pyspark.sql import SparkSession, capabilities as F, Window
from pyspark.sql.varieties import IntegerType, StringType, StructType, StructField, FloatType
from pyspark.ml.function import StringIndexer, VectorAssembler
from pyspark.ml.classification import LogisticRegression
from pyspark.ml.analysis import MulticlassClassificationEvaluator


spark = (SparkSession.builder.appName("ColabSparkAdvancedTutorial")
        .grasp("native(*)")
        .config("spark.sql.shuffle.partitions", "4")
        .getOrCreate())
print("Spark model:", spark.model)


information = (
   (1, "Alice", "IN", "2025-10-01", 56000.0, "premium"),
   (2, "Bob", "US", "2025-10-03", 43000.0, "normal"),
   (3, "Carlos", "IN", "2025-09-27", 72000.0, "premium"),
   (4, "Diana", "UK", "2025-09-30", 39000.0, "normal"),
   (5, "Esha", "IN", "2025-10-02", 85000.0, "premium"),
   (6, "Farid", "AE", "2025-10-02", 31000.0, "primary"),
   (7, "Gita", "IN", "2025-09-29", 46000.0, "normal"),
   (8, "Hassan", "PK", "2025-10-01", 52000.0, "premium"),
)
schema = StructType((
   StructField("id", IntegerType(), False),
   StructField("title", StringType(), True),
   StructField("nation", StringType(), True),
   StructField("signup_date", StringType(), True),
   StructField("revenue", FloatType(), True),
   StructField("plan", StringType(), True),
))
df = spark.createDataFrame(information, schema)
df.present()

[ad_2]

]]>
http://chatgpz.de/artificial-intelligence/so-bauen-sie-mit-apache-spark-und-pyspark-eine-finish-to-finish-pipeline-fuer-datentechnik-und-maschinelles-lernen-auf/feed/ 0 13627
Erstellen moderner Daten -Lakehouses in Google Cloud mit Apache Iceberg und Apache Spark http://chatgpz.de/data-analytics/erstellen-moderner-daten-lakehouses-in-google-cloud-mit-apache-iceberg-und-apache-spark/ http://chatgpz.de/data-analytics/erstellen-moderner-daten-lakehouses-in-google-cloud-mit-apache-iceberg-und-apache-spark/#respond Wed, 09 Jul 2025 09:08:10 +0000 http://chatgpz.de/data-analytics/erstellen-moderner-daten-lakehouses-in-google-cloud-mit-apache-iceberg-und-apache-spark/ [ad_1]

Gesponserte Inhalte

Eisberg, Google Cloud, Apache Spark

Die Landschaft von Huge Knowledge Analytics entwickelt sich ständig weiter. Unternehmen suchen flexiblere, skalierbare und kostengünstigere Möglichkeiten, um große Datenmengen zu verwalten und zu analysieren. Diese Verfolgung hat zum Anstieg des Daten-Lakehouse-Paradigmas geführt, das die kostengünstige Speicherung und Flexibilität von Datenseen mit den Datenverwaltungsfunktionen und der Transaktionskonsistenz von Datenlagern kombiniert. Im Zentrum dieser Revolution stehen offene Tabellenformate wie Apache Iceberg und leistungsstarke Verarbeitungsmotoren wie Apache Spark, die alle durch die robuste Infrastruktur von Google Cloud gestärkt werden.

Der Aufstieg von Apache Iceberg: Ein Recreation-Changer für Datenseen

Seit Jahren boten Knowledge Lakes, die in der Regel auf Cloud -Objektspeicher wie Google Cloud Storage (GCS) basieren, beispiellose Skalierbarkeit und Kosteneffizienz. Es fehlten ihnen jedoch häufig die entscheidenden Merkmale, die in herkömmlichen Datenlagern wie Transaktionskonsistenz, Schemaentwicklung und Leistungsoptimierungen für analytische Abfragen gefunden wurden. Hier glänzt Apache Iceberg.

Apache Iceberg ist ein offenes Tabellenformat, das diese Einschränkungen angeht. Es befindet sich oben in Ihren Datendateien (wie Parquet, ORC oder AVRO) im Cloud-Speicher und bietet eine Metadatenschicht, die eine Sammlung von Dateien in eine Hochleistungs-SQL-ähnliche Tabelle umwandelt. Folgendes macht Eisberg so mächtig:

  • Säurekonformität: Iceberg bringt Atomizität, Konsistenz, Isolation und Haltbarkeit (Säure) in Ihren Datensee. Dies bedeutet, dass Datenschreibvorgänge transaktional sind und die Datenintegrität auch bei gleichzeitigen Operationen sicherstellen. Keine teilweisen Schreibvorgänge oder inkonsistenten Lesevorgänge mehr.
  • Schemaentwicklung: Einer der größten Schmerzpunkte in traditionellen Datenseen ist die Verwaltung von Schemaveränderungen. Iceberg übernimmt nahtlos die Schemaentwicklung und ermöglicht es Ihnen, Spalten hinzuzufügen, zu fallen, umzubenennen oder neu zu ordnen, ohne die zugrunde liegenden Daten neu zu schreiben. Dies ist für die agile Datenentwicklung von entscheidender Bedeutung.
  • Versteckte Partitionierung: Iceberg verwaltet clever die Partitionierung und entzieht das physische Format Ihrer Daten ab. Benutzer müssen das Partitionierungsschema nicht mehr kennen, um effiziente Abfragen zu schreiben, und Sie können Ihre Partitionierungsstrategie im Laufe der Zeit ohne Datenmigrationen weiterentwickeln.
  • Zeitreisen und Rollback: Iceberg hält eine vollständige Geschichte von Tischschnappschüssen. Auf diese Weise können Sie „Zeitreisen“ -Anfragen ermöglichen, sodass Sie Daten in der Vergangenheit abfragen können. Es bietet auch Rollback -Funktionen, mit denen Sie eine Tabelle in einen früheren guten Zustand zurückversetzen können, der für das Debuggen und die Datenwiederherstellung von unschätzbarem Wert von unschätzbarem Zustand ist.
  • Leistungsoptimierungen: Mit der reichen Metadaten von Iceberg können Abfragemotoren irrelevante Datendateien und Partitionen effizient beschneiden und die Abfrageausführung erheblich beschleunigen. Es vermeidet kostspielige Dateilistenvorgänge und springt direkt zu den relevanten Daten basierend auf seinen Metadaten.

Durch die Bereitstellung dieser Knowledge Warehouse-ähnlichen Funktionen auf einem Datensee ermöglicht Apache Iceberg die Erstellung eines echten „Knowledge Lakehouse“, der das Beste aus beiden Welten bietet: die Flexibilität und Kostenwirksamkeit der Cloud-Speicherung in Kombination mit der Zuverlässigkeit und Leistung strukturierter Tabellen.

Google Clouds Biglake -Tabellen für Apache Iceberg in BigQuery Bietet ein voll verwaltetes Tabellenerlebnis, das den Normal-BigQuery-Tabellen ähnelt, aber alle Daten werden in kundenbesitzenden Speicherömer gespeichert. Assist -Funktionen umfassen:

  • Tabellenmutationen über Googlesql Knowledge Manipulationssprache (DML)
  • Einheitlicher Stapel und hoher Durchsatz -Streaming mit der Speicher -Schreibapi durch Biglake -Anschlüsse wie Spark
  • ICEBERG V2 SNAPSHOT -Export und automatische Aktualisierung auf jeder Tabellenmutation
  • Schema -Evolution, um die Spaltenmetadaten zu aktualisieren
  • Automatische Speicheroptimierung
  • Zeitreisen für historische Datenzugriff
  • Sicherheits- und Datenmaskierung auf Spaltenebene

Hier ist ein Beispiel dafür, wie man mit Googlesql eine leere Biglake -Eisberg -Tabelle erstellt:


SQL

CREATE TABLE PROJECT_ID.DATASET_ID.my_iceberg_table (
  identify STRING,
  id INT64
)
WITH CONNECTION PROJECT_ID.REGION.CONNECTION_ID
OPTIONS (
file_format="PARQUET"
table_format="ICEBERG"
storage_uri = 'gs://BUCKET/PATH');

Du kannst dann Daten importieren in die Daten verwenden LOAD INTO Daten aus einer Datei importieren oder INSERT INTO aus einem anderen Tisch.


SQL

# Load from file
LOAD DATA INTO PROJECT_ID.DATASET_ID.my_iceberg_table
FROM FILES (
uris=('gs://bucket/path/to/knowledge'),
format="PARQUET");

# Load from desk
INSERT INTO PROJECT_ID.DATASET_ID.my_iceberg_table
SELECT identify, id
FROM PROJECT_ID.DATASET_ID.source_table

Zusätzlich zu einem vollständig verwalteten Angebot wird Apache Iceberg als Lesen unterstützt.extern Tisch in BigQuery. Verwenden Sie dies, um auf einen vorhandenen Pfad mit Datendateien zu verweisen.


SQL

CREATE OR REPLACE EXTERNAL TABLE PROJECT_ID.DATASET_ID.my_external_iceberg_table
WITH CONNECTION PROJECT_ID.REGION.CONNECTION_ID
OPTIONS (
  format="ICEBERG",
  uris =
    ('gs://BUCKET/PATH/TO/DATA'),
  require_partition_filter = FALSE);

Apache Spark: Die Engine für Knowledge Lakehouse Analytics

Während Apache Iceberg die Struktur und das Administration für Ihr Daten -Lakehouse bietet, ist Apache Spark die Verarbeitungsmotor, die sie zum Leben erweckt. Spark ist ein leistungsstarkes Open-Supply-verteiltes Verarbeitungssystem, das für seine Geschwindigkeit, Vielseitigkeit und Fähigkeit zur Behandlung verschiedener Huge-Knowledge-Workloads bekannt ist. Die In-Reminiscence-Verarbeitung von Spark, das robuste Ökosystem von Werkzeugen, einschließlich ML und SQL-basierter Verarbeitung, und Deep Iceberg Assist machen es zu einer hervorragenden Wahl.

Apache Spark ist tief in das Google Cloud -Ökosystem integriert. Zu den Vorteilen der Verwendung von Apache Spark auf Google Cloud gehören:

  • Zugriff auf ein echtes serverloses Spark -Erlebnis ohne Clusterverwaltung mithilfe von Verwendung Google Cloud serverlos für Apache Spark.
  • Voll verwaltete Spark -Erfahrung mit flexibler Clusterkonfiguration und -verwaltung über DataProc.
  • Funkenjobs mit dem neuen beschleunigen Lightning Engine für Apache Spark Vorschau -Funktion.
  • Konfigurieren Sie Ihre Laufzeit mit GPUs und Treibern, die vorinstalliert sind.
  • Führen Sie AI/ML -Jobs mit einem robusten Satz von Bibliotheken aus, die standardmäßig in Spark -Laufzeiten verfügbar sind, einschließlich Xgboost, Pytorch und Transformers.
  • Schreiben Sie PySpark -Code direkt in BigQuery Studio über Colab Enterprise Notebooks zusammen mit der Gemini-angetriebenen PYSPark-Codegenerierung.
  • Stellen Sie einfach eine Verbindung zu Ihren Daten in BigQuery native Tabellen, Biglake -Eisberg -Tabellen, externen Tabellen und GCs her
  • Integration mit Vertex AI für Finish-to-Finish-Mlops

Eisberg + Spark: Besser zusammen

Zusammen bilden Eisberg und Funken eine starke Kombination für den Bau von leistungsfähigen und zuverlässigen Daten -Lakehouses. Spark kann die Metadaten von Iceberg nutzen, um Abfragepläne zu optimieren, ein effizientes Datenbeschneiden durchzuführen und die transaktionale Konsistenz in Ihrem Datensee zu gewährleisten.

Ihre Eisberg -Tische und BigQuery -nativen Tische sind über die durch Biglake Metastore. Dadurch werden Ihre Tabellen Open -Supply -Motoren mit BigQuery -Kompatibilität einschließlich Spark ausgesetzt.


Python

from pyspark.sql import SparkSession

# Create a spark session
spark = SparkSession.builder 
.appName("BigLake Metastore Iceberg") 
.config("spark.sql.catalog.CATALOG_NAME", "org.apache.iceberg.spark.SparkCatalog") 
.config("spark.sql.catalog.CATALOG_NAME.catalog-impl", "org.apache.iceberg.gcp.bigquery.BigQueryMetastoreCatalog") 
.config("spark.sql.catalog.CATALOG_NAME.gcp_project", "PROJECT_ID") 
.config("spark.sql.catalog.CATALOG_NAME.gcp_location", "LOCATION") 
.config("spark.sql.catalog.CATALOG_NAME.warehouse", "WAREHOUSE_DIRECTORY") 
.getOrCreate()
spark.conf.set("viewsEnabled","true")

# Use the blms_catalog
spark.sql("USE `CATALOG_NAME`;")
spark.sql("USE NAMESPACE DATASET_NAME;")

# Configure spark for temp outcomes
spark.sql("CREATE namespace if not exists MATERIALIZATION_NAMESPACE");
spark.conf.set("materializationDataset","MATERIALIZATION_NAMESPACE")

# Record the tables within the dataset
df = spark.sql("SHOW TABLES;")
df.present();

# Question the tables
sql = """SELECT * FROM DATASET_NAME.TABLE_NAME"""
df = spark.learn.format("bigquery").load(sql)
df.present()
sql = """SELECT * FROM DATASET_NAME.ICEBERG_TABLE_NAME"""
df = spark.learn.format("bigquery").load(sql)
df.present()

sql = """SELECT * FROM DATASET_NAME.READONLY_ICEBERG_TABLE_NAME"""
df = spark.learn.format("bigquery").load(sql)
df.present()

Die Verlängerung der Funktionalität von Biglake Metastore ist die Eisberg REST -Katalog (in der Vorschau) mit jeder Datenverarbeitungsmaschine auf Eisberg -Daten zugreifen. Hier erfahren Sie, wie Sie mit Spark verbinden können:


Python

import google.auth
from google.auth.transport.requests import Request
from google.oauth2 import service_account
import pyspark
from pyspark.context import SparkContext
from pyspark.sql import SparkSession

catalog = ""
spark = SparkSession.builder.appName("") 
    .config("spark.sql.defaultCatalog", catalog) 
    .config(f"spark.sql.catalog.{catalog}", "org.apache.iceberg.spark.SparkCatalog") 
    .config(f"spark.sql.catalog.{catalog}.sort", "relaxation") 
    .config(f"spark.sql.catalog.{catalog}.uri",
"https://biglake.googleapis.com/iceberg/v1beta/restcatalog") 
    .config(f"spark.sql.catalog.{catalog}.warehouse", "gs://") 
    .config(f"spark.sql.catalog.{catalog}.token", "") 
    .config(f"spark.sql.catalog.{catalog}.oauth2-server-uri", "https://oauth2.googleapis.com/token")                    .config(f"spark.sql.catalog.{catalog}.header.x-goog-user-project", "")      .config("spark.sql.extensions","org.apache.iceberg.spark.extensions.IcebergSparkSessionExtensions") 
.config(f"spark.sql.catalog.{catalog}.io-impl","org.apache.iceberg.hadoop.HadoopFileIO")     .config(f"spark.sql.catalog.{catalog}.rest-metrics-reporting-enabled", "false") 
.getOrCreate()

Fertigstellung des Lakehaus

Google Cloud bietet eine umfassende Suite von Diensten, die Apache Iceberg und Apache Spark ergänzen und es Ihnen ermöglichen, Ihr Daten-Lakehouse problemlos zu erstellen, zu verwalten und zu skalieren und gleichzeitig viele der Open-Supply-Technologien zu nutzen, die Sie bereits verwenden:

  • Dataplex Universalkatalog: Dataplex Common Catalog bietet eine einheitliche Datengewebe für die Verwaltung, Überwachung und Registrierung Ihrer Daten über Knowledge Lakes, Knowledge Warehouses und Knowledge Marts. Es wird in Biglake Metastore integriert, um sicherzustellen, dass Governance -Richtlinien in Ihren Eisberg -Tabellen konsequent erzwungen werden und Funktionen wie semantische Suche, Datenlinien und Datenqualitätsprüfungen ermöglichen.
  • Google Cloud Managed Service für Apache Kafka: Führen Sie in Google Cloud voll verwaltete Kafka-Cluster aus, einschließlich Kafka Join. Datenströme können direkt an BigQuery gelesen werden, einschließlich der verwalteten Eisberg -Tabellen mit Latenz mit geringer Latenz.
  • Wolkenkomponist: Ein vollständig verwalteter Workflow -Orchestrierungsdienst, der auf baut auf Apache -Luftstrom.
  • Scheitelpunkt AI: Verwenden Sie die Vertex AI, um das vollständige Finish-to-Finish-ML-OPS-Erlebnis zu verwalten. Sie können auch verwenden Scheitelpunkt AI Workbench Für eine verwaltete JupyterLab -Erfahrung, um eine Verbindung zu Ihren serverlosen Funken- und DataProc -Instanzen herzustellen.

Abschluss

Die Kombination von Apache Iceberg und Apache Spark auf Google Cloud bietet eine überzeugende Lösung für den Aufbau moderner Hochleistungsdaten-Lakehouses. Iceberg liefert die transaktionale Konsistenz, die Schemaentwicklung und die Leistungsoptimierungen, die historisch in Datenseen fehlten, während Spark eine vielseitige und skalierbare Engine für die Verarbeitung dieser großen Datensätze bietet.

Um mehr zu erfahren, sehen Sie sich unsere an Kostenloses Webinar Am 8. Juli um 11 Uhr PST, wo wir tiefer in die Verwendung von Apache Spark und unterstützenden Instruments auf Google Cloud eintauchen.

Autor: Brad Miro, Senior Developer Advocate – Google

[ad_2]

]]>
http://chatgpz.de/data-analytics/erstellen-moderner-daten-lakehouses-in-google-cloud-mit-apache-iceberg-und-apache-spark/feed/ 0 10627
Apache Spark 4.0: Eine neue Ära der Massive Knowledge-Verarbeitung http://chatgpz.de/data-analytics/apache-spark-4-0-eine-neue-aera-der-massive-knowledge-verarbeitung/ http://chatgpz.de/data-analytics/apache-spark-4-0-eine-neue-aera-der-massive-knowledge-verarbeitung/#respond Fri, 09 Aug 2024 23:21:09 +0000 http://chatgpz.de/data-analytics/apache-spark-4-0-eine-neue-aera-der-big-data-verarbeitung/ [ad_1]

Einführung

Als ich Apache Spark zum ersten Mal verwendete, battle ich von der einfachen Handhabung riesiger Datensätze begeistert. Jetzt, wo die Veröffentlichung von Apache Spark 4.0 vor der Tür steht, bin ich aufgeregter denn je. Dieses neueste Replace verspricht, bahnbrechend zu sein, vollgepackt mit leistungsstarken neuen Funktionen, bemerkenswerten Leistungssteigerungen und Verbesserungen, die es benutzerfreundlicher als je zuvor machen. Egal, ob Sie ein erfahrener Dateningenieur sind oder gerade erst Ihre Reise in die Welt der Massive Knowledge beginnen, Spark 4.0 hat für jeden etwas zu bieten. Lassen Sie uns einen Blick darauf werfen, was diese neue Model so bahnbrechend macht und wie sie die Artwork und Weise, wie wir Massive Knowledge verarbeiten, neu definieren wird.

Apache Spark 4.0

Überblick

  1. Apache Spark 4.0: Ein wichtiges Replace mit bahnbrechenden Funktionen, Leistungssteigerungen und verbesserter Benutzerfreundlichkeit für die Verarbeitung großer Datenmengen.
  2. Funkenverbindung: Revolutioniert die Artwork und Weise, wie Benutzer mit Spark-Clustern durch eine Skinny-Shopper-Architektur interagieren, und ermöglicht so sprachenübergreifende Entwicklung und vereinfachte Bereitstellungen.
  3. ANSI-Modus: Verbessert die Datenintegrität und SQL-Kompatibilität in Spark 4.0 und erleichtert Migrationen und Debugging durch verbesserte Fehlerberichterstattung.
  4. Beliebige Stateful Processing V2: Führt erweiterte Flexibilität für Streaming-Anwendungen ein und unterstützt komplexe Ereignisverarbeitung und zustandsbehaftete Modelle maschinellen Lernens.
  5. Kollationsunterstützung: Verbessert die Textverarbeitung und -sortierung für mehrsprachige Anwendungen und erhöht die Kompatibilität mit herkömmlichen Datenbanken.
  6. Variantendatentyp: Bietet eine versatile, leistungsfähige Möglichkeit zur Verarbeitung halbstrukturierter Daten wie JSON, perfekt für die IoT-Datenverarbeitung und Internet-Log-Analyse.

Apache Spark: Ein Überblick

Apache Spark ist ein leistungsstarkes, Open-Supply-Verteilungsrechnersystem für die Verarbeitung und Analyse großer Datenmengen. Es bietet eine Schnittstelle zum Programmieren ganzer Cluster mit impliziter Datenparallelität und Fehlertoleranz. Spark ist bekannt für seine Geschwindigkeit, Benutzerfreundlichkeit und Vielseitigkeit. Es ist eine beliebte Wahl für Datenverarbeitungsaufgaben, von der Stapelverarbeitung bis hin zu Echtzeit-Datenstreaming, maschinellem Lernen und interaktiven Abfragen.

Hier herunterladen:

Lesen Sie auch: Umfassende Einführung in Apache Spark, RDDs und Dataframes (mit PySpark)

Was bietet Apache Spark 4.0?

Dies sind die Neuerungen in Apache Spark 4.0:

1. Spark Join: Revolutionierte Konnektivität

Spark Join ist eine der bahnbrechendsten Ergänzungen zu Spark 4.0 und verändert die Interaktion der Benutzer mit Spark-Clustern grundlegend.

Hauptmerkmale Technische Particulars Anwendungsfälle
Skinny-Shopper-Architektur PySpark Join-Paket Erstellen interaktiver Datenanwendungen
Sprachunabhängig API-Konsistenz Sprachenübergreifende Entwicklung (z. B. Go-Shopper für Spark)
Interaktive Entwicklung Leistung Vereinfachte Bereitstellung in Containerumgebungen

2. ANSI-Modus: Verbesserung der Datenintegrität und SQL-Kompatibilität

Der ANSI-Modus wird in Spark 4.0 zur Standardeinstellung, wodurch Spark SQL näher an das Customary-SQL-Verhalten heranrückt und die Datenintegrität verbessert wird.

Wichtige Verbesserungen Technische Particulars Auswirkungen
Verhinderung stiller Datenbeschädigung Fehler bei der Callsite-Erfassung Verbesserte Datenqualität und Konsistenz in Datenpipelines
Verbesserte Fehlerberichterstattung Konfigurierbar Verbessertes Debugging-Erlebnis für SQL- und DataFrame-Operationen
SQL-Customary-Konformität – Einfachere Migration von herkömmlichen SQL-Datenbanken zu Spark

3. Beliebige Stateful Processing V2

Die zweite Model von Arbitrary Stateful Processing bietet mehr Flexibilität und Leistung für Streaming-Anwendungen.

Wichtige Verbesserungen:

  • Zusammengesetzte Typen in GroupState
  • Flexibilität bei der Datenmodellierung
  • Staatliche Unterstützung bei Zwangsräumungen
  • Entwicklung des Zustandsschemas

Technisches Beispiel:

@udf(returnType="STRUCT<rely: INT, max: INT>")

class CountAndMax:

    def __init__(self):

        self._count = 0

        self._max = 0

    def eval(self, worth: int):

        self._count += 1

        self._max = max(self._max, worth)

    def terminate(self):

        return (self._count, self._max)

# Utilization in a streaming question

df.groupBy("id").agg(CountAndMax("worth"))

Anwendungsfälle:

  • Komplexe Ereignisverarbeitung
  • Echtzeitanalyse mit benutzerdefinierter Statusverwaltung
  • Zustandsbehaftet maschinelles Lernen Modellbereitstellung in Streaming-Kontexten
Beliebige Stateful Processing V2
Quelle – Databricks

4. Kollationsunterstützung

Spark 4.0 führt eine umfassende Unterstützung für die Zeichenfolgensortierung ein und ermöglicht so differenziertere Zeichenfolgenvergleiche und -sortierungen.

Hauptmerkmale:

  • Vergleiche ohne Berücksichtigung der Groß-/Kleinschreibung
  • Akzentunabhängige Vergleiche
  • Lokale Sortierung

Technische Particulars:

  • Integration mit SQL
  • Leistungsoptimiert

Beispiel:

SELECT title

FROM names

WHERE startswith(title COLLATE unicode_ci_ai, 'a')

ORDER BY title COLLATE unicode_ci_ai;

Auswirkungen:

  • Verbesserte Textverarbeitung für mehrsprachige Anwendungen
  • Präziseres Sortieren und Suchen in textlastigen Datensätzen
  • Verbesserte Kompatibilität mit herkömmlichen Datenbanksystemen

5. Variantendatentyp für halbstrukturierte Daten

Der neue Variant-Datentyp bietet eine versatile und leistungsfähige Möglichkeit, halbstrukturierte Daten wie JSON zu verarbeiten.

Hauptvorteile:

  • Flexibilität
  • Leistung
  • Einhaltung von Requirements

Technische Particulars:

  • Interne Vertretung
  • Abfrageoptimierung

Anwendungsbeispiel:

CREATE TABLE occasions (

  id INT,

  knowledge VARIANT

);

INSERT INTO occasions VALUES (1, PARSE_JSON('{"degree": "warning", "message": "Invalid request"}'));

SELECT * FROM occasions WHERE knowledge:degree="warning";

Anwendungsfälle:

  • IoT-Datenverarbeitung
  • Internet-Log-Analyse
  • Versatile Schemaentwicklung in Knowledge Lakes

6. Python-Erweiterungen

Pandas API auf Spark
Quelle – Databricks

PySpark erhält in dieser Model große Aufmerksamkeit und umfasst mehrere wesentliche Verbesserungen.

Wichtige Verbesserungen:

  • Pandas 2.x-Unterstützung
  • Python-Datenquellen-APIs
  • Arrow-optimierte Python-UDFs
  • Benutzerdefinierte Tabellenfunktionen (UDTFs) in Python
  • Einheitliches Profiling für PySpark-UDFs

Technisches Beispiel (Python UDTF):

@udtf(returnType="num: int, squared: int")

class SquareNumbers:

    def eval(self, begin: int, finish: int):

        for num in vary(begin, finish + 1):

            yield (num, num * num)

# Utilization

spark.sql("SELECT * FROM SquareNumbers(1, 5)").present()

Leistungsverbesserungen:

  • Arrow-optimierte UDFs zeigen bei bestimmten Vorgängen eine bis zu doppelt so hohe Leistungssteigerung.
  • Python-Datenquellen-APIs reduzieren den Aufwand für die benutzerdefinierte Datenaufnahme.

7. SQL- und Scripting-Verbesserungen

Spark 4.0 bringt mehrere Verbesserungen seiner SQL-Funktionen mit sich und macht es leistungsfähiger und flexibler.

Hauptmerkmale:

  • SQL-benutzerdefinierte Funktionen (UDFs) und Tabellenfunktionen (UDTFs)
  • SQL-Skripting
  • Gespeicherte Prozeduren

Technisches Beispiel (SQL Scripting):

BEGIN

  DECLARE c INT = 10;

  WHILE c > 0 DO

    INSERT INTO t VALUES (c);

    SET c = c - 1;

  END WHILE;

END

Anwendungsfälle:

  • Komplexe ETL-Prozesse vollständig in SQL implementiert
  • Migrieren von älteren gespeicherten Prozeduren zu Spark
  • Erstellen wiederverwendbarer SQL-Komponenten für Datenpipelines

Lesen Sie auch: Ein umfassender Leitfaden zu Apache Spark RDD und PySpark

8. Delta Lake 4.0-Integration

Delta Lake 4.0
Quelle – Databricks

Apache Spark 4.0 integriert sich nahtlos in Delta Lake 4.0und bringt erweiterte Funktionen in die Lakehouse-Architektur.

Hauptmerkmale:

  • Flüssigkeitsclusterung
  • Unterstützung für VARIANT-Typ
  • Kollationsunterstützung
  • Identitätsspalten

Technische Particulars:

  • Flüssigkeitsclusterung
  • VARIANT-Implementierung

Auswirkungen auf die Leistung:

  • Liquid Clustering kann bei bestimmten Abfragemustern bis zu 12x schnellere Lesevorgänge ermöglichen.
  • Der Typ VARIANT bietet im Vergleich zu als Zeichenfolgen gespeichertem JSON eine bis zu doppelt so gute Komprimierung.

9. Verbesserungen der Benutzerfreundlichkeit

Spark 4.0 führt mehrere Funktionen ein, um das Entwicklererlebnis und die Benutzerfreundlichkeit zu verbessern.

Wichtige Verbesserungen:

  • Strukturiertes Protokollierungsframework
  • Framework für Fehlerbedingungen und -meldungen
  • Verbesserte Dokumentation
  • Prozess der Verhaltensänderung

Technisches Beispiel (Strukturiertes Logging):

{

  "ts": "2023-03-12T12:02:46.661-0700",

  "degree": "ERROR",

  "msg": "Fail to know the executor 289 is alive or not",

  "context": {

    "executor_id": "289"

  },

  "exception": {

    "class": "org.apache.spark.SparkException",

    "msg": "Exception thrown in awaitResult",

    "stackTrace": "..."

  },

  "supply": "BlockManagerMasterEndpoint"

}

Auswirkungen:

  • Verbesserte Funktionen zur Fehlerbehebung und Fehlerbehebung
  • Verbesserte Beobachtbarkeit für Spark-Anwendungen
  • Reibungsloserer Upgradepfad zwischen Spark-Versionen

10. Leistungsoptimierungen

Spark 4.0 bietet zahlreiche Leistungsverbesserungen, die die Gesamtsystemeffizienz steigern.

Wichtige Verbesserungsbereiche:

  • Verbesserter Catalyst Optimizer
  • Verbesserungen bei der adaptiven Abfrageausführung
  • Verbesserte Arrow-Integration

Technische Particulars:

  • Optimierung der Neuordnung beitreten
  • Dynamisches Partitionsbeschneiden
  • Vektorisierte Python-UDF-Ausführung

Benchmarks:

  • Bis zu 30 % Verbesserung der TPC-DS-Benchmark-Leistung im Vergleich zu Spark 3.x.
  • Python UDF-Leistungsverbesserungen von bis zu 100 % für bestimmte Workloads.

Abschluss

Apache Spark 4.0 stellt einen gewaltigen Sprung nach vorne bei der Verarbeitung von Massive Knowledge dar. Mit seinem Fokus auf Konnektivität (Spark Join), Datenintegrität (ANSI-Modus), erweitertes Streaming (Arbitrary Stateful Processing V2) und verbesserte Unterstützung für halbstrukturierte Daten (Variantentyp) erfüllt diese Model die sich entwickelnden Anforderungen von Dateningenieure, Datenwissenschaftlerund Analysten, die mit großen Datenmengen arbeiten.

Die Verbesserungen in Python Integration, SQL-Funktionen und allgemeine Benutzerfreundlichkeit machen Spark 4.0 zugänglicher und leistungsfähiger als je zuvor. Mit Leistungsoptimierungen und nahtloser Integration mit modernen Knowledge-Lake-Technologien wie Delta Lake bekräftigt Apache Spark 4.0 seine Place als Plattform der Wahl für die Verarbeitung und Analyse großer Datenmengen.

Während Unternehmen mit immer größeren Datenmengen und Komplexitäten zu kämpfen haben, bietet Apache Spark 4.0 die Instruments und Funktionen, die zum Erstellen skalierbarer, effizienter und innovativer Datenlösungen erforderlich sind. Egal, ob Sie an Echtzeitanalysen, groß angelegten ETL-Prozesseoder erweiterte Machine-Studying-Pipelines bietet Spark 4.0 die Funktionen und die Leistung, um die Herausforderungen moderner Datenverarbeitung.

Häufig gestellte Fragen

Frage 1. Was ist Apache Spark?

Antwort: Eine Open-Supply-Engine für die Verarbeitung und Analyse großer Datenmengen, die In-Reminiscence-Berechnungen für eine schnellere Verarbeitung bietet.

Frage 2. Worin unterscheidet sich Spark von Hadoop?

Antwort: Spark verwendet In-Reminiscence-Verarbeitung, ist einfacher zu verwenden und integriert Batch, Streaming und maschinelles Lernen in einem Framework, im Gegensatz zur festplattenbasierten Verarbeitung von Hadoop.

Frage 3. Was sind die Hauptkomponenten von Spark?

Antworten: Spark Core, Spark SQL, Spark Streaming, MLlib (Maschinelles Lernen) und GraphX ​​(Graphverarbeitung).

F4. Was sind RDDs in Spark?

Antwort: Robuste verteilte Datensätze sind unveränderliche, fehlertolerante Datenstrukturen, die parallel verarbeitet werden.

F5. Wie funktioniert Spark Streaming?

Antwort: Verarbeitet Echtzeitdaten, indem sie für Analysen mit geringer Latenz in Mikro-Batches aufgeteilt werden.

[ad_2]

]]>
http://chatgpz.de/data-analytics/apache-spark-4-0-eine-neue-aera-der-massive-knowledge-verarbeitung/feed/ 0 3035
Optimierung von Sigma-Regeln in Spark mit dem Aho-Corasick-Algorithmus | von Jean-Claude Cote | Juni 2024 http://chatgpz.de/machine-learning/optimierung-von-sigma-regeln-in-spark-mit-dem-aho-corasick-algorithmus-von-jean-claude-cote-juni-2024/ http://chatgpz.de/machine-learning/optimierung-von-sigma-regeln-in-spark-mit-dem-aho-corasick-algorithmus-von-jean-claude-cote-juni-2024/#respond Thu, 20 Jun 2024 12:58:23 +0000 http://chatgpz.de/machine-learning/optimierung-von-sigma-regeln-in-spark-mit-dem-aho-corasick-algorithmus-von-jean-claude-cote-juni-2024/ [ad_1]

Erweiterung von Spark für verbesserte Leistung bei der Verarbeitung mehrerer Suchbegriffe

Foto von Aditya Chinchure auf Unsplash

Während der Einführung unseres Intrusion Detection Programs in der Produktion bei CCCShaben wir festgestellt, dass viele der SigmaHQ-Regeln sehr umfangreiche Pay attention mit Suchmustern verwenden. Diese Pay attention werden verwendet, um zu testen, ob ein CommandLineeine bestimmte Zeichenfolge enthält oder CommandLinebeginnt mit oder endet mit einer bestimmten Teilzeichenfolge.

Wir waren besonders daran interessiert, die Regeln mit „enthält“-Bedingungen zu untersuchen, da wir vermuteten, dass die Auswertung dieser Bedingungen für Spark zeitaufwändig sein könnte. Hier ist ein Beispiel für eine typische Sigma-Regel:

detection:
selection_image:
- Picture|comprises:
- 'CVE-202'
- 'CVE202'
- Picture|endswith:
- 'poc.exe'
- 'artifact.exe'
- 'artifact64.exe'
- 'artifact_protected.exe'
- 'artifact32.exe'
- 'artifact32big.exe'
- 'obfuscated.exe'
- 'obfusc.exe'
- 'meterpreter'
selection_commandline:
CommandLine|comprises:
- 'inject.ps1'
- 'Invoke-CVE'
- 'pupy.ps1'
- 'payload.ps1'
- 'beacon.ps1'
- 'PowerView.ps1'
- 'bypass.ps1'
- 'obfuscated.ps1'

Die vollständige Regel zu verdächtigen Programmnamen finden Sie hier
https://github.com/SigmaHQ/sigma/blob/grasp/guidelines/home windows/process_creation/proc_creation_win_susp_progname.yml

Die Regel veranschaulicht die Verwendung von CommandLine|comprises und von Picture|endswith. Einige Sigma-Regeln haben Hunderte von Suchbegriffen unter einem <subject>|comprisesZustand.

Anwenden von Sigma-Regeln mit Spark SQL

Bei CCCSübersetzen wir Sigma-Regeln in ausführbare Spark-SQL-Anweisungen. Dazu haben wir den SQL Sigma-Compiler um ein benutzerdefiniertes Backend erweitert. Es übersetzt die obige Regel in eine Anweisung wie diese:

choose
map(
'Suspicious Program Names',
(
(
(
Imagepath LIKE '%cve-202%'
OR Imagepath LIKE '%cve202%'
)
OR (
Imagepath LIKE '%poc.exe'
OR Imagepath LIKE '%artifact.exe'
...
OR Imagepath LIKE '%obfusc.exe'
OR Imagepath LIKE '%meterpreter'
)
)
OR (
CommandLine LIKE '%inject.ps1%'
OR CommandLine LIKE '%invoke-cve%'
OR CommandLine LIKE '%pupy.ps1%'
...
OR CommandLine LIKE '%encode.ps1%'
OR CommandLine LIKE '%powercat.ps1%'
)
)
) as sigma_rules_map

Wir führen die obige Anweisung in einem Spark Structured Streaming-Job aus. In einem einzigen Durchlauf über die Ereignisse wertet Spark mehrere (Hunderte) Sigma-Regeln aus. Die sigma_rules_map Die Spalte enthält die Auswertungsergebnisse aller dieser Regeln. Mithilfe dieser Karte können wir feststellen, welche Regel ein Treffer ist und welche nicht.

Wie wir sehen, beinhalten die Regeln oft den Vergleich von Ereignisattributen, wie z. B. CommandLinezu mehreren Zeichenfolgenmustern.

Einige dieser Assessments sind exakte Übereinstimmungen, wie zum Beispiel CommandLine = ‘one thing’Andere verwenden startswithund werden wiedergegeben als Imagepath LIKE ‘%poc.exe’.

Equals, startswithUnd endswith werden sehr schnell ausgeführt, da diese Bedingungen alle an einer bestimmten Place im Attribut des Ereignisses verankert sind.

Allerdings können Assessments wie comprises werden wiedergegeben als CommandLine LIKE ‘%hound.ps1%’ Dazu muss Spark das gesamte Attribut scannen, um eine mögliche Startposition für den Buchstaben „h“ zu finden und dann zu prüfen, ob darauf der Buchstabe „o“, „u“ usw. folgt.

Intern verwendet Spark eine UTF8String Das Programm greift das erste Zeichen, durchsucht den Puffer und vergleicht, wenn es eine Übereinstimmung findet, die restlichen Bytes mit dem matchAt Funktion. Hier ist die Implementierung der UTF8String.comprises Funktion.

  public boolean comprises(last UTF8String substring) {
if (substring.numBytes == 0) {
return true;
}

byte first = substring.getByte(0);
for (int i = 0; i <= numBytes - substring.numBytes; i++) {
if (getByte(i) == first && matchAt(substring, i)) {
return true;
}
}
return false;
}

Der equals, startswithUnd endswith Bedingungen verwenden auch die matchAt Funktion, aber im Gegensatz zu comprises Diese Bedingungen wissen, wo der Vergleich beginnen muss, und werden daher sehr schnell ausgeführt.

Um unsere Annahme zu bestätigen, dass comprises Bedingung ist teuer in der Ausführung, wir haben ein schnelles und einfaches Experiment durchgeführt. Wir haben alle entfernt comprises Bedingungen für die Sigma-Regeln, um zu sehen, wie sich dies auf die Gesamtausführungszeit auswirken würde. Der Unterschied battle signifikant und ermutigte uns, die Idee der Implementierung einer benutzerdefinierten Spark Catalyst-Funktion zur Handhabung weiter zu verfolgen comprises Operationen mit einer großen Anzahl von Suchbegriffen.

Der Aho-Corasick-Algorithmus

Ein wenig Recherche führte uns zu der Aho-Corasick-Algorithmus was für diesen Anwendungsfall intestine geeignet schien. Der Aho-Corasick-Algorithmus erstellt einen Präfixbaum (einen Trie) und kann viele comprises Ausdrücke in einem einzigen Durchgang über den zu testenden Textual content.

So verwenden Sie die Aho-Corasick Java-Implementierung von Robert Bor, die hier auf GitHub verfügbar ist https://github.com/robert-bor/aho-corasick

// create the trie
val triBuilder = Trie.builder()
triBuilder.addKeyword("test1")
triBuilder.addKeyword("test2")
trie = triBuilder.construct()

// apply the trie to some textual content
aTextColumn = "some textual content to scan for both test1 or test2"
discovered = trie.containsMatch(aTextColumn)

Entwerfen einer aho_corasick_in Spark-Funktion

Unsere Funktion benötigt zwei Dinge: die zu testende Spalte und die zu suchenden Suchmuster. Wir implementieren eine Funktion mit der folgenden Signatur:

boolean aho_corasick_in(string textual content, array<string> searches)

Wir haben unseren CCCS Sigma-Compiler modifiziert, um SQL-Anweisungen zu erzeugen, die den aho_corasick_inFunktion, anstatt mehrere ORed LIKE-Prädikate zu erzeugen. In der Ausgabe unten werden Sie die Verwendung der aho_corasick_in Funktion. Wir übergeben das zu testende Feld und ein Array von Zeichenfolgen, nach denen gesucht werden soll. Hier ist die Ausgabe unseres benutzerdefinierten Compilers, der mehrere comprises Bedingungen:

choose 
map(
'Suspicious Program Names',
(
(
(
Imagepath LIKE '%cve-202%'
OR Imagepath LIKE '%cve202%'
)
OR (
Imagepath LIKE '%poc.exe'
OR Imagepath LIKE '%artifact.exe'
...
OR Imagepath LIKE '%meterpreter'
)
)
OR (
aho_corasick_in(
CommandLine,
ARRAY(
'inject.ps1',
'invoke-cve',
...
'hound.ps1',
'encode.ps1',
'powercat.ps1'
)
)
)
)
) as sigma_rules_map

Beachten Sie, wie die aho_corasick_in Funktion erhält zwei Argumente: das erste ist eine Spalte und das zweite ist ein String-Array. Lassen Sie uns nun die aho_corasick_inFunktion.

Implementierung der Katalysatorfunktion

Wir fanden nicht viel Dokumentation zur Implementierung von Catalyst-Funktionen, additionally verwendeten wir stattdessen den Quellcode vorhandener Funktionen als Referenz. Wir nahmen die regulärer Ausdruck(str, regulärer Ausdruck) Funktion als Beispiel, da sie ihr Regexp-Muster vorkompiliert und es dann bei der Verarbeitung von Zeilen verwendet. Dies ist vergleichbar mit dem Vorkompilieren eines Aho-Corasick-Tries und dessen anschließender Anwendung auf jede Zeile.

Unser benutzerdefinierter Katalysatorausdruck nimmt zwei Argumente an. Es ist additionally ein BinaryExpression welches zwei Felder hat, die Spark benannt hat left Und proper. Unser AhoCorasickIn Konstruktor weist den textual content Spaltenargument für left Feld und das searches String-Array in proper Feld.

Das andere, was wir während der Initialisierung von AhoCorasickIn tun, ist die Auswertung der cacheTrie Feld. Die Auswertung prüft, ob das searches argument ist ein faltbarer Ausdruck, additionally ein konstanter Ausdruck. Wenn ja, wird es ausgewertet und es wird erwartet, dass es sich um ein String-Array handelt, das zum Aufrufen verwendet wird createTrie(searches).

Der createTrie Funktion iteriert über die Suchvorgänge und fügt sie dem trieBuilder und erstellt schließlich einen Aho-Corasick-Trie.

case class AhoCorasickIn(textual content: Expression, searches: Expression) 
extends BinaryExpression
with CodegenFallback
with ImplicitCastInputTypes
with NullIntolerant
with Predicate {

override def prettyName: String = "aho_corasick_in"
// Assign textual content to left subject
override def left: Expression = textual content
// Assign searches to proper subject
override def proper: Expression = searches

override def inputTypes: Seq(DataType) = Seq(StringType, ArrayType(StringType))

// Cache foldable searches expression when AhoCorasickIn is constructed
personal lazy val cacheTrie: Trie = proper match {
case p: Expression if p.foldable => {
val searches = p.eval().asInstanceOf(ArrayData)
createTrie(searches)
}
case _ => null
}

protected def createTrie(searches: ArrayData): Trie = {
val triBuilder = Trie.builder()
searches.foreach(StringType, (i, s) => triBuilder.addKeyword(s.toString()))
triBuilder.construct()
}

protected def getTrie(searches: ArrayData) = if (cacheTrie == null) createTrie(searches) else cacheTrie

override protected def nullSafeEval(textual content: Any, searches: Any): Any = {
val trie = getTrie(searches.asInstanceOf(ArrayData))
trie.containsMatch(textual content.asInstanceOf(UTF8String).toString())
}

override protected def withNewChildrenInternal(
newLeft: Expression, newRight: Expression): AhoCorasickIn =
copy(textual content = newLeft, searches = newRight)
}

Der nullSafeEval Methode ist das Herzstück von AhoCorasickIn. Spark ruft die eval-Funktion für jede Zeile im Datensatz auf. In nullSafeEvalwir holen die cacheTrie und testen Sie damit die textual content Zeichenfolgenargument.

Bewertung der Leistung

Zum Vergleich der Leistung der aho_corasick_in Funktion haben wir ein kleines Benchmarking-Skript geschrieben. Wir haben die Leistung mehrerer Assessments verglichen. LIKE Operationen im Vergleich zu einer einzelnen aho_corasick_in Anruf.

choose
*
from (
choose
textual content like '%' || uuid() || '%' OR
textual content like '%' || uuid() || '%' OR
textual content like '%' || uuid() || '%' OR
...
as end result
from (
choose
uuid()||uuid()||uuid()... as textual content
from
vary(0, 1000000, 1, 32)
)
)
the place
end result = TRUE

Dasselbe Experiment mit aho_corasick_in:

choose
*
from (
choose
aho_corasick_in(textual content, array(uuid(), uuid(),...) as end result
from (
choose
uuid()||uuid()||uuid()... as textual content
from
vary(0, 1000000, 1, 32)
)
)
the place
end result = TRUE

Wir führten diese beiden Experimente (wie vs aho_corasick_in) mit einem textual content Spalte mit 200 Zeichen und variierte die Anzahl der Suchbegriffe. Hier ist ein logarithmisches Diagramm, das beide Abfragen vergleicht.

Bild vom Autor

Dieses Diagramm zeigt, wie die Leistung nachlässt, wenn wir der Abfrage „LIKE“ weitere Suchbegriffe hinzufügen, während die Abfrage mit aho_corasick_in Funktion bleibt relativ konstant, wenn die Anzahl der Suchbegriffe zunimmt. Bei 100 Suchbegriffen ist die aho_corasick_in Die Funktion wird fünfmal schneller ausgeführt als mehrere LIKE-Anweisungen.

Wir haben festgestellt, dass die Verwendung von Aho-Corasick erst nach mehr als 20 Suchvorgängen von Vorteil ist. Dies lässt sich durch die anfänglichen Kosten für die Erstellung des Tries erklären. Mit zunehmender Anzahl der Suchbegriffe zahlen sich diese Vorabkosten jedoch aus. Dies steht im Gegensatz zu den LIKE-Ausdrücken, bei denen die Abfrage umso teurer wird, je mehr LIKE-Ausdrücke wir hinzufügen.

Als nächstes setzten wir die Anzahl der Suchbegriffe auf 20 und variierten die Länge der textual content Zeichenfolge. Wir haben festgestellt, dass sowohl LIKE als auch aho_corasick_in Funktion dauert bei verschiedenen Stringlängen etwa gleich lange. In beiden Experimenten ist die Ausführungszeit abhängig von der Länge des textual content Zeichenfolge.

Bild vom Autor

Es ist wichtig zu beachten, dass die Kosten für die Erstellung des Tries von der Anzahl der Spark-Aufgaben im Abfrageausführungsplan abhängen. Spark instanziiert Ausdrücke (d. h. instanziiert neue AhoCorasickIn-Objekte) für jede Aufgabe im Ausführungsplan. Mit anderen Worten: Wenn Ihre Abfrage 200 Aufgaben verwendet, wird der AhoCorasickIn-Konstruktor 200 Mal aufgerufen.

Zusammenfassend lässt sich sagen, dass die zu verwendende Strategie von der Anzahl der Begriffe abhängt. Wir haben diese Optimierung in unseren Sigma-Compiler eingebaut. Unter einem bestimmten Schwellenwert (sagen wir 20 Begriffe) werden LIKE-Anweisungen ausgegeben, und über diesem Schwellenwert wird eine Abfrage ausgegeben, die die aho_corasick_in Funktion.

Dieser Schwellenwert hängt natürlich von Ihren tatsächlichen Daten und der Anzahl der Aufgaben in Ihrem Spark-Ausführungsplan ab.

Unsere ersten Ergebnisse, die wir mit Produktionsdaten und echten SigmaHQ-Regeln durchgeführt haben, zeigen, dass die Anwendung der aho_corasick_in Funktion erhöht unsere Verarbeitungsrate (Ereignisse professional Sekunde) um den Faktor 1,4.

Bild vom Autor

Abschluss

In diesem Artikel haben wir gezeigt, wie man eine native Spark-Funktion implementiert. Dieser Catalyst-Ausdruck nutzt den Aho-Corasick-Algorithmus, der viele Suchbegriffe gleichzeitig testen kann. Wie bei jedem Ansatz gibt es jedoch auch hier Kompromisse. Die Verwendung von Aho-Corasick erfordert den Aufbau eines Tries (Präfixbaum), was die Leistung beeinträchtigen kann, wenn nur wenige Suchbegriffe verwendet werden. Unser Compiler verwendet einen Schwellenwert (Anzahl der Suchbegriffe), um die optimale Strategie auszuwählen und so die effizienteste Abfrageausführung sicherzustellen.

[ad_2]

]]>
http://chatgpz.de/machine-learning/optimierung-von-sigma-regeln-in-spark-mit-dem-aho-corasick-algorithmus-von-jean-claude-cote-juni-2024/feed/ 0 1586
Leistungseinblicke aus Sigma-Regelerkennungen in Spark Streaming | von Jean-Claude Cote | Juni 2024 http://chatgpz.de/machine-learning/leistungseinblicke-aus-sigma-regelerkennungen-in-spark-streaming-von-jean-claude-cote-juni-2024/ http://chatgpz.de/machine-learning/leistungseinblicke-aus-sigma-regelerkennungen-in-spark-streaming-von-jean-claude-cote-juni-2024/#respond Sat, 01 Jun 2024 22:28:33 +0000 http://chatgpz.de/machine-learning/leistungseinblicke-aus-sigma-regelerkennungen-in-spark-streaming-von-jean-claude-cote-juni-2024/ [ad_1]

Nutzung von Sigma-Regeln zur Anomalieerkennung in Cybersicherheitsprotokollen: Eine Studie zur Leistungsoptimierung

Foto von Ed Vazquez auf Unsplash

Eine der Rollen des Kanadisches Zentrum für Cybersicherheit (CCCS) besteht darin, Anomalien zu erkennen und schnellstmöglich Gegenmaßnahmen zu ergreifen.

Während wir unsere Sigma-Regelerkennungen in die Produktion einführten, machten wir eine interessante Beobachtung in unserer Spark-Streaming-Anwendung. Das Ausführen einer einzelnen großen SQL-Anweisung mit 1000 Sigma-Erkennungsregeln struggle langsamer als das Ausführen von fünf separaten Abfragen, von denen jede 200 Sigma-Regeln anwendete. Das struggle überraschend, da das Ausführen von fünf Abfragen Spark dazu zwingt, die Quelldaten fünfmal statt einmal zu lesen. Weitere Einzelheiten finden Sie in unserer Artikelserie:

Angesichts der enormen Menge an Telemetriedaten und Erkennungsregeln, die wir ausführen müssen, führt jede Leistungssteigerung zu erheblichen Kosteneinsparungen. Daher haben wir uns entschlossen, diese eigenartige Beobachtung zu untersuchen, um sie zu erklären und möglicherweise zusätzliche Möglichkeiten zur Leistungssteigerung zu entdecken. Dabei haben wir einiges gelernt und wollten es mit der breiteren Neighborhood teilen.

Einführung

Wir hatten das Gefühl, dass wir bei der Codegenerierung von Spark an eine Grenze stoßen würden. Daher ist ein wenig Hintergrundwissen zu diesem Thema erforderlich. Im Jahr 2014 führte Spark die Codegenerierung ein, um Ausdrücke der Type auszuwerten (id > 1 and id > 2) and (id < 1000 or (id + id) = 12)Dieser Artikel von Databricks erklärt es sehr intestine: Spannende Leistungsverbesserungen für Spark SQL in Sicht

Zwei Jahre später führte Spark die Entire-Stage-Codegenerierung ein. Diese Optimierung führt mehrere Operatoren zu einer einzigen Java-Funktion zusammen. Wie die Expression-Codegenerierung eliminiert die Entire-Stage-Codegenerierung virtuelle Funktionsaufrufe und nutzt CPU-Register für Zwischendaten. Sie wird jedoch nicht auf der Expression-Ebene, sondern auf der Operatorebene angewendet. Operatoren sind die Knoten in einem Ausführungsplan. Weitere Informationen finden Sie unter Apache Spark als Compiler: Eine Milliarde Zeilen professional Sekunde auf einem Laptop computer zusammenführen

Um diese Artikel zusammenzufassen, erstellen wir den Plan für diese einfache Abfrage:

clarify codegen
choose
id,
(id > 1 and id > 2) and (id < 1000 or (id + id) = 12) as take a look at
from
vary(0, 10000, 1, 32)

In dieser einfachen Abfrage verwenden wir zwei Operatoren: Vary zum Generieren von Zeilen und Choose zum Ausführen einer Projektion. Wir sehen diese Operatoren im physischen Plan der Abfrage. Beachten Sie das Sternchen (codegen id : 1)neben den Knoten und den zugehörigen

|== Bodily Plan ==
* Mission (2)
+- * Vary (1)

(1) Vary (codegen id : 1)
Output (1): (id#36167L)
Arguments: Vary (0, 10000, step=1, splits=Some(32))

(2) Mission (codegen id : 1)
Output (2): (id#36167L, (((id#36167L > 1) AND (id#36167L > 2)) AND ((id#36167L < 1000) OR ((id#36167L + id#36167L) = 12))) AS take a look at#36161)
Enter (1): (id#36167L)

. Dies zeigt an, dass diese beiden Operatoren mithilfe der Entire-Stage-Codegenerierung zu einer einzigen Java-Funktion zusammengeführt wurden.

Generated code:
/* 001 */ public Object generate(Object() references) {
/* 002 */ return new GeneratedIteratorForCodegenStage1(references);
/* 003 */ }
/* 004 */
/* 005 */ // codegenStageId=1
/* 006 */ ultimate class GeneratedIteratorForCodegenStage1 extends org.apache.spark.sql.execution.BufferedRowIterator {
/* 007 */ non-public Object() references;
/* 008 */ non-public scala.assortment.Iterator() inputs;
/* 009 */ non-public boolean range_initRange_0;
/* 010 */ non-public lengthy range_nextIndex_0;
/* 011 */ non-public TaskContext range_taskContext_0;
/* 012 */ non-public InputMetrics range_inputMetrics_0;
/* 013 */ non-public lengthy range_batchEnd_0;
/* 014 */ non-public lengthy range_numElementsTodo_0;
/* 015 */ non-public org.apache.spark.sql.catalyst.expressions.codegen.UnsafeRowWriter() range_mutableStateArray_0 = new org.apache.spark.sql.catalyst.expressions.codegen.UnsafeRowWriter(3);
/* 016 */
/* 017 */ public GeneratedIteratorForCodegenStage1(Object() references) {
/* 018 */ this.references = references;
/* 019 */ }
/* 020 */
/* 021 */ public void init(int index, scala.assortment.Iterator() inputs) {
/* 022 */ partitionIndex = index;
/* 023 */ this.inputs = inputs;
/* 024 */
/* 025 */ range_taskContext_0 = TaskContext.get();
/* 026 */ range_inputMetrics_0 = range_taskContext_0.taskMetrics().inputMetrics();
/* 027 */ range_mutableStateArray_0(0) = new org.apache.spark.sql.catalyst.expressions.codegen.UnsafeRowWriter(1, 0);
/* 028 */ range_mutableStateArray_0(1) = new org.apache.spark.sql.catalyst.expressions.codegen.UnsafeRowWriter(1, 0);
/* 029 */ range_mutableStateArray_0(2) = new org.apache.spark.sql.catalyst.expressions.codegen.UnsafeRowWriter(2, 0);
/* 030 */
/* 031 */ }
/* 032 */
/* 033 */ non-public void project_doConsume_0(lengthy project_expr_0_0) throws java.io.IOException {
/* 034 */ // frequent sub-expressions
/* 035 */
/* 036 */ boolean project_value_4 = false;
/* 037 */ project_value_4 = project_expr_0_0 > 1L;
/* 038 */ boolean project_value_3 = false;
/* 039 */
/* 040 */ if (project_value_4) {
/* 041 */ boolean project_value_7 = false;
/* 042 */ project_value_7 = project_expr_0_0 > 2L;
/* 043 */ project_value_3 = project_value_7;
/* 044 */ }
/* 045 */ boolean project_value_2 = false;
/* 046 */
/* 047 */ if (project_value_3) {
/* 048 */ boolean project_value_11 = false;
/* 049 */ project_value_11 = project_expr_0_0 < 1000L;
/* 050 */ boolean project_value_10 = true;
/* 051 */
/* 052 */ if (!project_value_11) {
/* 053 */ lengthy project_value_15 = -1L;
/* 054 */
/* 055 */ project_value_15 = project_expr_0_0 + project_expr_0_0;
/* 056 */
/* 057 */ boolean project_value_14 = false;
/* 058 */ project_value_14 = project_value_15 == 12L;
/* 059 */ project_value_10 = project_value_14;
/* 060 */ }
/* 061 */ project_value_2 = project_value_10;
/* 062 */ }
/* 063 */ range_mutableStateArray_0(2).reset();
/* 064 */
/* 065 */ range_mutableStateArray_0(2).write(0, project_expr_0_0);
/* 066 */
/* 067 */ range_mutableStateArray_0(2).write(1, project_value_2);
/* 068 */ append((range_mutableStateArray_0(2).getRow()));
/* 069 */
/* 070 */ }
/* 071 */
/* 072 */ non-public void initRange(int idx) {
/* 073 */ java.math.BigInteger index = java.math.BigInteger.valueOf(idx);
/* 074 */ java.math.BigInteger numSlice = java.math.BigInteger.valueOf(32L);
/* 075 */ java.math.BigInteger numElement = java.math.BigInteger.valueOf(10000L);
/* 076 */ java.math.BigInteger step = java.math.BigInteger.valueOf(1L);
/* 077 */ java.math.BigInteger begin = java.math.BigInteger.valueOf(0L);
/* 078 */ lengthy partitionEnd;
/* 079 */
/* 080 */ java.math.BigInteger st = index.multiply(numElement).divide(numSlice).multiply(step).add(begin);
/* 081 */ if (st.compareTo(java.math.BigInteger.valueOf(Lengthy.MAX_VALUE)) > 0) {
/* 082 */ range_nextIndex_0 = Lengthy.MAX_VALUE;
/* 083 */ } else if (st.compareTo(java.math.BigInteger.valueOf(Lengthy.MIN_VALUE)) < 0) {
/* 084 */ range_nextIndex_0 = Lengthy.MIN_VALUE;
/* 085 */ } else {
/* 086 */ range_nextIndex_0 = st.longValue();
/* 087 */ }
/* 088 */ range_batchEnd_0 = range_nextIndex_0;
/* 089 */
/* 090 */ java.math.BigInteger finish = index.add(java.math.BigInteger.ONE).multiply(numElement).divide(numSlice)
/* 091 */ .multiply(step).add(begin);
/* 092 */ if (finish.compareTo(java.math.BigInteger.valueOf(Lengthy.MAX_VALUE)) > 0) {
/* 093 */ partitionEnd = Lengthy.MAX_VALUE;
/* 094 */ } else if (finish.compareTo(java.math.BigInteger.valueOf(Lengthy.MIN_VALUE)) < 0) {
/* 095 */ partitionEnd = Lengthy.MIN_VALUE;
/* 096 */ } else {
/* 097 */ partitionEnd = finish.longValue();
/* 098 */ }
/* 099 */
/* 100 */ java.math.BigInteger startToEnd = java.math.BigInteger.valueOf(partitionEnd).subtract(
/* 101 */ java.math.BigInteger.valueOf(range_nextIndex_0));
/* 102 */ range_numElementsTodo_0 = startToEnd.divide(step).longValue();
/* 103 */ if (range_numElementsTodo_0 < 0) {
/* 104 */ range_numElementsTodo_0 = 0;
/* 105 */ } else if (startToEnd.the rest(step).compareTo(java.math.BigInteger.valueOf(0L)) != 0) {
/* 106 */ range_numElementsTodo_0++;
/* 107 */ }
/* 108 */ }
/* 109 */
/* 110 */ protected void processNext() throws java.io.IOException {
/* 111 */ // initialize Vary
/* 112 */ if (!range_initRange_0) {
/* 113 */ range_initRange_0 = true;
/* 114 */ initRange(partitionIndex);
/* 115 */ }
/* 116 */
/* 117 */ whereas (true) {
/* 118 */ if (range_nextIndex_0 == range_batchEnd_0) {
/* 119 */ lengthy range_nextBatchTodo_0;
/* 120 */ if (range_numElementsTodo_0 > 1000L) {
/* 121 */ range_nextBatchTodo_0 = 1000L;
/* 122 */ range_numElementsTodo_0 -= 1000L;
/* 123 */ } else {
/* 124 */ range_nextBatchTodo_0 = range_numElementsTodo_0;
/* 125 */ range_numElementsTodo_0 = 0;
/* 126 */ if (range_nextBatchTodo_0 == 0) break;
/* 127 */ }
/* 128 */ range_batchEnd_0 += range_nextBatchTodo_0 * 1L;
/* 129 */ }
/* 130 */
/* 131 */ int range_localEnd_0 = (int)((range_batchEnd_0 - range_nextIndex_0) / 1L);
/* 132 */ for (int range_localIdx_0 = 0; range_localIdx_0 < range_localEnd_0; range_localIdx_0++) {
/* 133 */ lengthy range_value_0 = ((lengthy)range_localIdx_0 * 1L) + range_nextIndex_0;
/* 134 */
/* 135 */ project_doConsume_0(range_value_0);
/* 136 */
/* 137 */ if (shouldStop()) {
/* 138 */ range_nextIndex_0 = range_value_0 + 1L;
/* 139 */ ((org.apache.spark.sql.execution.metric.SQLMetric) references(0) /* numOutputRows */).add(range_localIdx_0 + 1);
/* 140 */ range_inputMetrics_0.incRecordsRead(range_localIdx_0 + 1);
/* 141 */ return;
/* 142 */ }
/* 143 */
/* 144 */ }
/* 145 */ range_nextIndex_0 = range_batchEnd_0;
/* 146 */ ((org.apache.spark.sql.execution.metric.SQLMetric) references(0) /* numOutputRows */).add(range_localEnd_0);
/* 147 */ range_inputMetrics_0.incRecordsRead(range_localEnd_0);
/* 148 */ range_taskContext_0.killTaskIfInterrupted();
/* 149 */ }
/* 150 */ }
/* 151 */
/* 152 */ }

Der generierte Code zeigt deutlich, wie die beiden Operatoren zusammengeführt werden. project_doConsume_0 Der (id > 1 and id > 2) and (id < 1000 or (id + id) = 12)Funktion enthält den auszuwertenden Code

. Beachten Sie, wie dieser Code generiert wird, um diesen spezifischen Ausdruck auszuwerten. Dies ist eine Illustration der Generierung von Ausdruckscode. processNext Die ganze Klasse ist ein Operator mit einem project_doConsume_0Methode. Dieser generierte Operator führt sowohl die Projektions- als auch die Bereichsoperation aus. Innerhalb der while-Schleife in Zeile 117 sehen wir den Code zum Erzeugen von Zeilen und einen spezifischen Aufruf (keine virtuelle Funktion) zum

Dies veranschaulicht, was die Codegenerierung für ganze Phasen bewirkt.

Aufschlüsselung der Leistung Imagepath Nachdem wir nun ein besseres Verständnis für die Codegenerierung von Spark haben, versuchen wir zu erklären, warum die Aufteilung einer Abfrage mit 1000 Sigma-Regeln in kleinere eine bessere Leistung bringt. Betrachten wir eine SQL-Anweisung, die zwei Sigma-Regeln auswertet. Diese Regeln sind unkompliziert: Regel1 gleicht Ereignisse mit einem Imagepath endet mit ’schtask.exe‘, und Rule2 entspricht einem


choose /* #3 */
Imagepath,
CommandLine,
PID,
map_keys(map_filter(results_map, (okay,v) -> v = TRUE)) as matching_rules
from (
choose /* #2 */
*,
map('rule1', rule1, 'rule2', rule2) as results_map
from (
choose /* #1 */
*,
(lower_Imagepath like '%schtasks.exe') as rule1,
(lower_Imagepath like 'd:%') as rule2
from (
choose
decrease(PID) as lower_PID,
decrease(CommandLine) as lower_CommandLine,
decrease(Imagepath) as lower_Imagepath,
*
from (
choose
uuid() as PID,
uuid() as CommandLine,
uuid() as Imagepath,
id
from
vary(0, 10000, 1, 32)
)
)
)
)

beginnend mit „d:“. results_mapDie Auswahl mit der Bezeichnung #1 führt die Erkennung durch und speichert die Ergebnisse in neuen Spalten mit den Namen rule1 und rule2. Auswahl #2 gruppiert diese Spalten unter einer einzigen map_filter und schließlich wandelt choose #3 die Karte in ein Array von Matching-Regeln um. Es verwendet map_keys um nur die Einträge der Regeln zu behalten, die tatsächlich übereinstimmen, und dann

wird verwendet, um die Map-Einträge in eine Liste passender Regelnamen umzuwandeln.


== Bodily Plan ==
Mission (4)
+- * Mission (3)
+- * Mission (2)
+- * Vary (1)

...

(4) Mission
Output (4): (Imagepath#2, CommandLine#1, PID#0, map_keys(map_filter(map(rule1, EndsWith(lower_Imagepath#5, schtasks.exe), rule2, StartsWith(lower_Imagepath#5, d:)), lambdafunction(lambda v#12, lambda okay#11, lambda v#12, false))) AS matching_rules#9)
Enter (4): (lower_Imagepath#5, PID#0, CommandLine#1, Imagepath#2)

Drucken wir den Spark-Ausführungsplan für diese Abfrage aus:

Beachten Sie, dass Knoten Projekt (4) kein Code generiert. Knoten 4 hat eine Lambda-Funktion. Verhindert diese die Codegenerierung für die gesamte Section? Mehr dazu später.

+--------------------+--------------------+--------------------+--------------+
| Imagepath| CommandLine| PID| matched_rule|
+--------------------+--------------------+--------------------+--------------+
|09401675-dc09-4d0...|6b8759ee-b55a-486...|44dbd1ec-b4e0-488...| rule1|
|e2b4a0fd-7b88-417...|46dd084d-f5b0-4d7...|60111cf8-069e-4b8...| rule1|
|1843ee7a-a908-400...|d1105cec-05ef-4ee...|6046509a-191d-432...| rule2|
+--------------------+--------------------+--------------------+--------------+

Diese Abfrage ist nicht ganz das, was wir wollen. Wir möchten eine Ereignistabelle mit einer Spalte erstellen, die die Regel angibt, die erfüllt wurde. Etwa so: matching_rules Das ist ganz einfach. Wir müssen nur die


choose
Imagepath,
CommandLine,
PID,
matched_rule
from (
choose
*,
explode(matching_rules) as matched_rule
from (
/* unique assertion */
)
)

Spalte.

== Bodily Plan ==
* Mission (7)
+- * Generate (6)
+- Mission (5)
+- * Mission (4)
+- Filter (3)
+- * Mission (2)
+- * Vary (1)

...

(3) Filter
Enter (3): (PID#34, CommandLine#35, Imagepath#36)
Situation : (measurement(map_keys(map_filter(map(rule1, EndsWith(decrease(Imagepath#36),
schtasks.exe), rule2, StartsWith(decrease(Imagepath#36), d:)),
lambdafunction(lambda v#47, lambda okay#46, lambda v#47, false))), true) > 0)
...

(6) Generate (codegen id : 3)
Enter (4): (PID#34, CommandLine#35, Imagepath#36, matching_rules#43)
Arguments: explode(matching_rules#43), (PID#34, CommandLine#35, Imagepath#36), false, (matched_rule#48)

(7) Mission (codegen id : 3)
Output (4): (Imagepath#36, CommandLine#35, PID#34, matched_rule#48)
Enter (4): (PID#34, CommandLine#35, Imagepath#36, matched_rule#48)

Dadurch entstehen zwei zusätzliche Operatoren: Generieren (6) und Projizieren (7). Es gibt jedoch auch einen neuen Filter (3). explode Der explode Funktion generiert Zeilen für jedes Factor im Array. Wenn das Array leer ist,

erzeugt keine Zeilen und filtert effektiv Zeilen heraus, bei denen das Array leer ist. org.apache.spark.sql.catalyst.optimizer.InferFiltersFromGenerateSpark verfügt über eine Optimierungsregel, die die Explode-Funktion erkennt und diese zusätzliche Bedingung erzeugt. Der Filter ist ein Versuch von Spark, die Verarbeitung so weit wie möglich abzukürzen. Der Quellcode für diese Regel, genannt

erklärt es so:

Leitet Filter aus Generate ab, sodass Zeilen, die durch dieses Generate entfernt worden wären, früher entfernt werden können – vor Verknüpfungen und in Datenquellen. Weitere Einzelheiten zur Optimierung von Ausführungsplänen durch Spark finden Sie im Artikel von David Vrba.

Abfragepläne in Spark 3.0 meistern

Eine weitere Frage stellt sich: Profitieren wir von diesem zusätzlichen Filter? Beachten Sie, dass dieser zusätzliche Filter vermutlich aufgrund der Lambda-Funktion auch kein Code ist, der für die gesamte Section generiert wird. Versuchen wir, dieselbe Abfrage auszudrücken, jedoch ohne Verwendung einer Lambda-Funktion. map_filterStattdessen können wir die Regelergebnisse in eine Karte einfügen, diese Karte auflösen und die Zeilen herausfiltern. Dadurch wird die Notwendigkeit umgangen,


choose
Imagepath,
CommandLine,
PID,
matched_rule
from (
choose
*
from (
choose
*,
explode(results_map) as (matched_rule, matched_result)
from (
/* unique assertion */
)
)
the place
matched_result = TRUE
)

. matched_rule Die Choose #3-Operation zerlegt die Karte in zwei neue Spalten. matched_result enthält den Schlüssel, der den Regelnamen darstellt, während die matched_resultSpalte enthält das Ergebnis des Erkennungstests. Um die Zeilen zu filtern, behalten wir einfach nur diejenigen mit einem positiven

.


== Bodily Plan ==
* Mission (8)
+- * Filter (7)
+- * Generate (6)
+- * Mission (5)
+- * Mission (4)
+- * Filter (3)
+- * Mission (2)
+- * Vary (1)

Der physische Plan zeigt, dass es sich bei allen Knoten um Vollphasencode handelt, der in einer einzigen Java-Funktion generiert wird, was vielversprechend ist. map_filter Führen wir einige Assessments durch, um die Leistung der Abfrage zu vergleichen mit

und diejenige, die „explodieren“ und dann „filtern“ verwendet.

Wir haben diese Assessments auf einer Maschine mit 4 CPUs ausgeführt. Wir haben 1 Million Zeilen mit jeweils 100 Regeln generiert und jede Regel hat 5 Ausdrücke ausgewertet. Diese Assessments wurden 5 Mal ausgeführt.

  • Im Durchschnitt
  • map_filter dauerte 42,6 Sekunden

explode_then_filter dauerte 51,2 Sekunden

Daher ist map_filter etwas schneller, obwohl es keine Codegenerierung für die gesamte Section verwendet.

Brought on by: org.codehaus.commons.compiler.InternalCompilerException: Code grows past 64 KB

In unserer Produktionsabfrage führen wir jedoch viel mehr Sigma-Regeln aus – insgesamt 1000 Regeln. Dazu gehören 29 Regex-Ausdrücke, 529 „Gleich“-Ausdrücke, 115 „beginnt mit“-Ausdrücke, 2352 „endet mit“-Ausdrücke und 5838 „enthält“-Ausdrücke. Lassen Sie uns unsere Abfrage noch einmal testen, diesmal jedoch mit einer leichten Erhöhung der Anzahl der Ausdrücke, indem wir 7 statt 5 professional Regel verwenden. Dabei ist in unseren Protokollen ein Fehler aufgetreten: spark.sql.codegen.maxFields Wir haben versucht, spark.sql.codegen.hugeMethodLimitUnd

aber grundsätzlich haben Java-Klassen eine Funktionsgrößenbeschränkung von 64 KB. Darüber hinaus beschränkt sich der JVM-JIT-Compiler auf das Kompilieren von Funktionen, die kleiner als 8 KB sind.

Die Abfrage läuft jedoch weiterhin einwandfrei, da Spark für bestimmte Teile des Plans auf das Volcano-Ausführungsmodell zurückgreift. WholeStageCodeGen ist schließlich nur eine Optimierung.

  • Wenn Sie den gleichen Take a look at wie zuvor ausführen, jedoch mit 7 Ausdrücken professional Regel statt 5, ist explode_then_filter viel schneller als map_filter.
  • map_filter dauerte 68,3 Sekunden

explode_then_filter dauerte 15,8 Sekunden org.apache.spark.sql.catalyst.optimizer.InferFiltersFromGenerate Eine Erhöhung der Anzahl der Ausdrücke führt dazu, dass Teile des explode_then_filter nicht mehr als Code für die gesamte Section generiert werden. Insbesondere der Filteroperator, der durch die Regel eingeführt wurde

spark.sql("SET spark.sql.optimizer.excludedRules=org.apache.spark.sql.catalyst.optimizer.InferFiltersFromGenerate")

ist zu groß, um in die Codegenerierung der gesamten Section integriert zu werden. Sehen wir uns an, was passiert, wenn wir die Regel InferFiltersFromGenerate ausschließen:


== Bodily Plan ==
* Mission (6)
+- * Generate (5)
+- Mission (4)
+- * Mission (3)
+- * Mission (2)
+- * Vary (1)

== Bodily Plan ==
* Mission (7)
+- * Filter (6)
+- * Generate (5)
+- * Mission (4)
+- * Mission (3)
+- * Mission (2)
+- * Vary (1)

Wie erwartet verfügt der physische Plan beider Abfragen nicht mehr über einen zusätzlichen Filteroperator.

  • Das Entfernen der Regel hatte tatsächlich erhebliche Auswirkungen auf die Leistung:
  • map_filter dauerte 22,49 Sekunden

explode_then_filter dauerte 4,08 Sekunden

Beide Abfragen profitierten stark vom Entfernen der Regel. Angesichts der verbesserten Leistung beschlossen wir, die Anzahl der Sigma-Regeln auf 500 und die Komplexität auf 21 Ausdrücke zu erhöhen:

  • Ergebnisse:
  • map_filter dauerte 195,0 Sekunden

explode_then_filter dauerte 25,09 Sekunden

Trotz der erhöhten Komplexität liefern beide Abfragen noch immer eine ziemlich gute Leistung, wobei explode_then_filter map_filter deutlich übertrifft.

Es ist interessant, die verschiedenen Aspekte der Codegenerierung zu untersuchen, die Spark verwendet. Auch wenn wir derzeit möglicherweise nicht von der Codegenerierung für die gesamte Section profitieren, können wir dennoch von der Ausdrucksgenerierung profitieren. spark.sql.codegen.methodSplitThreshold Die Generierung von Ausdrücken unterliegt nicht den gleichen Einschränkungen wie die Generierung von Code in der gesamten Section. Sehr große Ausdrucksbäume können in kleinere aufgeteilt werden, und Sparks

steuert, wie diese aufgeteilt werden. Obwohl wir mit dieser Eigenschaft experimentiert haben, konnten wir keine signifikanten Verbesserungen feststellen. Die Standardeinstellung scheint zufriedenstellend. spark.sql.codegen.factoryModeSpark bietet eine Debug-Eigenschaft namens spark.sql.codegen.factoryMode=NO_CODEGENdas auf FALLBACK, CODEGEN_ONLY oder NO_CODEGEN gesetzt werden kann. Wir können die Generierung von Ausdruckscodes deaktivieren, indem wir

was zu einer drastischen Leistungsverschlechterung führt:

  • Mit 500 Regeln und 21 Ausdrücken:
  • map_filter dauerte 1581 Sekunden

explode_then_filter dauerte 122,31 Sekunden.

Auch wenn nicht alle Operatoren an der Codegenerierung für die gesamte Section teilnehmen, stellen wir dennoch erhebliche Vorteile bei der Codegenerierung für Ausdrücke fest.

Die Ergebnisse

Bild vom Autor

Mit unserem Bestfall von 25,1 Sekunden zum Auswerten von 10.500 Ausdrücken in 1 Million Zeilen erreichen wir eine sehr respektable Charge von 104 Millionen Ausdrücken professional Sekunde professional CPU. map_filter Das Fazit dieser Studie ist, dass wir bei der Auswertung einer großen Anzahl von Ausdrücken davon profitieren, unsere Abfragen, die org.apache.spark.sql.catalyst.optimizer.InferFiltersFromGenerate zu denen, die einen Explodieren-und-Filtern-Ansatz verwenden. Darüber hinaus

Regel scheint in unserem Anwendungsfall nicht vorteilhaft zu sein, daher sollten wir diese Regel aus unseren Abfragen ausschließen.

Erklärt es unsere ersten Beobachtungen?

Die Umsetzung dieser Erkenntnisse in unseren Produktionsjobs brachte erhebliche Vorteile. Aber auch nach diesen Optimierungen brachte die Aufteilung der großen Abfrage in mehrere kleinere weiterhin Vorteile. Bei weiterer Untersuchung stellten wir fest, dass dies nicht nur auf die Codegenerierung zurückzuführen struggle, sondern eine einfachere Erklärung hatte.

Beim Spark-Streaming wird ein Mikro-Batch vollständig ausgeführt und anschließend der Fortschritt überprüft, bevor ein neuer Mikro-Batch gestartet wird.

Während jedes Mikrobatches muss Spark alle seine Aufgaben erledigen, normalerweise 200. Allerdings sind nicht alle Aufgaben gleich. Spark verwendet eine Spherical-Robin-Strategie, um Zeilen auf diese Aufgaben zu verteilen. Daher können einige Aufgaben gelegentlich Ereignisse mit großen Attributen enthalten, z. B. eine sehr große Befehlszeile, wodurch bestimmte Aufgaben schnell abgeschlossen werden, während andere viel länger dauern. Hier beispielsweise die Verteilung der Ausführungszeit einer Mikrobatch-Aufgabe. Die mittlere Aufgabenzeit beträgt 14 Sekunden. Der schlimmste Nachzügler benötigt jedoch 1,6 Minuten!

Bild vom Autor

Dies wirft tatsächlich Licht auf ein anderes Phänomen. Die Tatsache, dass Spark während jedes Mikro-Batches auf ein paar Nachzügler-Aufgaben wartet, lässt viele CPUs ungenutzt, was erklärt, warum die Aufteilung der großen Abfrage in mehrere kleinere Abfragen zu einer schnelleren Gesamtleistung führte.

Dieses Bild zeigt 5 kleinere Abfragen, die parallel in derselben Spark-Anwendung ausgeführt werden. Batch3 wartet auf eine Nachzügleraufgabe, während die anderen Abfragen weiter ausgeführt werden.

Bild vom Autor

Während dieser Wartezeiten kann Spark die inaktiven CPUs für die Bearbeitung anderer Abfragen nutzen und so die Ressourcennutzung und den Gesamtdurchsatz maximieren.

Abschluss

In diesem Artikel haben wir einen Überblick über den Codegenerierungsprozess von Spark gegeben und erläutert, dass integrierte Optimierungen nicht immer zu den gewünschten Ergebnissen führen. Darüber hinaus haben wir gezeigt, dass die Umgestaltung einer Abfrage von Lambda-Funktionen zu einer Abfrage mit einer einfachen Explode-Operation zu Leistungsverbesserungen führte. Schließlich kamen wir zu dem Schluss, dass das Aufteilen einer großen Anweisung zwar zu Leistungssteigerungen führte, der Hauptfaktor für diese Verbesserungen jedoch die Ausführungstopologie und nicht die Abfragen selbst struggle.

[ad_2]

]]>
http://chatgpz.de/machine-learning/leistungseinblicke-aus-sigma-regelerkennungen-in-spark-streaming-von-jean-claude-cote-juni-2024/feed/ 0 1075