Дебъгване на Apache Spark SQL планове с големи езикови модели: Практическият подход на Expedia Group

Публикувано от Svetni.me Editorial на 30 юни 2026 г.

Всеки инженер, който е прекарал безсънни нощи в 2 часа сутринта, взирайки се във физически план на изпълнение с над 300 възела в опит да открие липсващо излъчване (broadcast join) или грешно разпределен партишън (skewed partition), е наясно с трудностите при оптимизацията на мащабни задачи за обработка на данни. Apache Spark улеснява писането на сложни SQL заявки, които изглеждат коректни, но при мащабиране се превръщат в сериозен проблем за производителността и разходите. Заявка, която работи нормално при първоначалните тестове, може да се забави драстично с нарастването на обема данни.

В публикация на технологичния блог на Expedia Group [1] инженерният екип споделя как е решил този проблем, като е изградил автоматизирана система, базирана на LLM (големи езикови модели). Системата анализира Spark SQL плановете за изпълнение, открива антимодели на производителността и предлага конкретни софтуерни решения за инженерите.

Архитектура на автоматизирания LLM тръбопровод за анализ на Spark SQL планове
Изображение: Svetni.me / Авторско изображение

Предизвикателствата пред традиционното отстраняване на грешки

Когато Spark задачите започнат да закъсняват или да надхвърлят бюджетите, откриването на първопричината е изключително трудоемко. Отстраняването на грешки изисква преминаване през дълбоко вложени физически планове, фрагментирани показатели в потребителския интерфейс (Spark UI) и статистики на ниво етап (stage-level statistics).

Инженерите често са принудени да гадаят дали проблемът се дължи на лоша стратегия за съединяване на таблици (join strategy), неравномерно разпределени данни (data skew), прекомерно разместване по мрежата (shuffling) или липса на памет. Оптимизацията бързо се превръща в процес на проба-грешка, който изисква специфични и дълбоки познания за вътрешната архитектура на Spark.

За да превърне този реактивен процес в предвидим и системен инструмент, Expedia Group разработва LLM-базиран анализатор, захранван от реални метаданни за изпълнението.

Архитектура на LLM-базирания анализатор

Анализаторът се състои от три основни компонента, които осигуряват точност и проследимост на резултатите [1]:

1. Извличане на контекст чрез Spark MCP сървър

За разлика от обикновените чат ботове, които работят на сляпо, системата на Expedia Group използва разширение с отворен код Model Context Protocol (MCP) сървър за Apache Spark [2]. Сървърът излага стандартизирани API интерфейси за:

  • Метаданни за SQL изпълненията;
  • Физически и логически планове на заявките;
  • Метрики на ниво етапи (stages) и задачи (tasks);
  • Статистики за shuffle операции, мрежов вход-изход (I/O) и дискови разливи (spills).

Това позволява на големия езиков модел да работи с чисти, структурирани данни, фокусирани само върху най-бавните SQL изрази в приложението.

2. Шаблонно ориентирано подсказване (Pattern-Guided Prompting)

Първоначалните опити с общи заявки от типа „Анализирай този Spark план и предложи оптимизации“ се провалят. Моделът е давал твърде общи съвети, халюцинирал е несъществуващи проблеми и е пропускал реални тесни места.

Затова разработчиците променят стратегията и дефинират ясни, базирани на правила антимодели със строги критерии. Задачата на LLM се свежда до това да сканира за тези специфични шаблони и да не анализира нищо извън тях. Това гарантира консистентност и надеждност на резултатите.

3. Задължителна проследимост (Traceability)

Всеки открит проблем трябва да съдържа доказателство: Stage ID, Task ID, Node ID, име на оператора и препратка към конкретна таблица. Целият изходен формат е строго дефиниран в JSON структура, която позволява на автоматизирани системи за CI/CD или мониторинг да консумират анализа без допълнително парсване.

Ключови антимодели, откривани от LLM

По време на експлоатацията в реални среди, екипът се фокусира върху няколко основни риска с високо въздействие върху производителността.

Пропуснати излъчвани съединения (Missed Broadcast Joins)

Често Spark избира по-бавната стратегия SortMergeJoin, въпреки че една от двете таблици е достатъчно малка, за да бъде излъчена в паметта на всички изпълнители (BroadcastHashJoin). LLM автоматично засича такива случаи, като анализира размера на таблиците във физическия план.

Пример за засечен от модела проблем в JSON формат [1]:

{
  "name": "Missing Broadcast Joins",
  "detections": [{
    "stage_id": "10.0",
    "join_details": {
      "right": {
        "name": "destination_attribute",
        "size_human": "96.6 MiB"
      },
      "chosen_strategy": "SortMergeJoin",
      "expected_strategy": "BroadcastHashJoin"
    },
    "notes": "Broadcast threshold likely too low; AQE skew handling favored SMJ."
  }]
}

Чрез увеличаване на прага за излъчване (broadcast threshold), времето за изпълнение на засегнатата задача спада от 1 час на 30 минути, без да се налага пренаписване на самата SQL заявка.

Неравномерно разпределени партишъни (Skewed Partitions)

Когато определени ключове при съединяване на таблици са изключително натоварени (например при наличие на голям брой стойности null), Spark изпраща почти цялата информация към един единствен партишън. Това води до т.нар. straggler tasks — задачи, които продължават да работят с часове след като всички останали са приключили.

Анализаторът лесно разпознава този проблем чрез сравняване на минималните, медианните и максималните размери на партишъните:

{
  "name": "Skewed Partitions",
  "detections": [{
    "stage_id": 35,
    "node_type": "SortMergeJoin(skew=true)",
    "partition_sizes": {
      "min_human": "0.0 B",
      "med_human": "0.0 B",
      "max_human": "279.7 GiB",
      "partition_count": 16
    },
    "likely_cause": "Extreme skew detected in join output."
  }]
}

В конкретния случай, ляво съединение (left join) с колони, съдържащи предимно празни стойности (null), е изпратило 280 GB към една задача. Промяната на логиката за обработка на null ключове преди съединяването връща изпълнението на задачата в рамките на очакваното време.

Пълно сканиране на таблици (Full Table Scans)

Инженерите лесно могат да пропуснат филтри по дата или партишън колони при работа с големи източници. LLM веднага сигнализира, когато във физическия план се забележи сканиране на голяма таблица без приложени предикати.

В един от анализираните случаи системата засича сканиране на 23.5 TB данни от таблица на Apache Iceberg [1]:

{
  "name": "Missing Partition or Date Filters",
  "detections": [{
    "table": "lodging_content_vrbo_room_type_profile_history",
    "input_size_human": "23.5 TiB",
    "partition_filters": [],
    "pushed_filters": [],
    "issue": "Full table scan without partition filters."
  }]
}

След добавяне на липсващите филтри, времето за работа на заданието спада от 20 минути на едва 1 минута.

Прекомерно големи излъчвания (Oversized Broadcasts)

От друга страна, излъчването на твърде големи таблици също крие рискове. Когато се излъчват обекти с размер от порядъка на няколко гигабайта (например 2.7 GB и 2.2 GB в една заявка), това натоварва паметта на драйвера (driver node) и може да доведе до срив на целия клъстер. Анализаторът разпознава този модел и предупреждава инженерите да преминат към друга стратегия за съединяване.

Допълнителни показатели

Системата също така открива:

  • Агресивно обединяване на партишъни (coalesce): Когато AQE (Adaptive Query Execution) намалява паралелизма твърде много, оставяйки ресурсите на клъстера ненатоварени;
  • Високи дискови разливи (high spills): Етапи, при които дисковият разлив надхвърля 1 GB (или 5 GB при критични ситуации), индикирайки недостиг на оперативна памет;
  • Експлозия на данни (data explosion): Случаи, в които изходните редове след съединяване на таблици нарастват двойно спрямо входа поради дублирани ключове.

Реални резултати и стойност за бизнеса

Реалното прилагане на LLM-базирания анализ в средите на Expedia Group води до изключително добри резултати:

  1. Спестени часове за ръчно дебъгване — автоматизираният триаж дава на готово точните проблемни места;
  2. Намаляване на времето за изпълнение (runtime) с 40% до 95% за дълготрайни задачи;
  3. Намаляване на разходите за облачни изчисления с 50% до 90% за оптимизираните задания.

Бъдещо развитие на концепцията

Развитието на този подход може да поеме в няколко посоки:

  • Интегриране на специализирани проверки за формати като Delta Lake или Apache Iceberg;
  • Директно визуализиране на бавните етапи върху физическите възли на плановете;
  • Автоматично изпращане на препоръки под формата на коментари в инструменти за ревю на код при промяна на SQL заявки.

Това решение не цели да замени Spark експертите, а да им даде мощен инструмент за автоматизиране на повтаряемия анализ. По този начин те могат да фокусират времето си изцяло върху отстраняването на проблемите.

Източници:

[1]: Using LLMs to Analyze Spark SQL Plans: A Practical Approach to Debugging Long-Running Jobs - Expedia Group Technology
[2]: GitHub - kubeflow/mcp-apache-spark-history-server
[3]: Prompt Gist - Sagibhuvana