{"id":"4317be7d-f5ba-4734-bb15-45118030c79b","shortId":"nZKDDt","kind":"skill","title":"spark-advisor","tagline":"Diagnose, compare, and optimize Apache Spark applications and SQL queries using Spark History Server data. Use this skill whenever the user wants to understand why a Spark app is slow, compare two benchmark runs or TPC-DS results, find performance bottlenecks (skew, GC pressure, ","description":"# Spark Advisor\n\nYou are a Spark performance engineer. Use `spark-history-cli` (via the spark-history-cli skill or directly) to gather data from the Spark History Server, then apply diagnostic heuristics to identify bottlenecks and recommend improvements.\n\n## Quick Start\n\nDiagnose an app in one shot:\n\n```bash\n# Get the latest app ID, then diagnose it\nspark-history-cli --json apps --limit 1\nspark-history-cli --json -a <app-id> summary\nspark-history-cli --json -a <app-id> stages\nspark-history-cli --json -a <app-id> executors --all\n```\n\nThen ask: \"Why is this app slow?\" — the skill will analyze the data and produce findings.\n\n## When to use this skill\n\n- User asks why a Spark application or SQL query is slow\n- User wants to compare two benchmark runs (especially TPC-DS)\n- User asks for tuning advice based on actual execution data\n- User mentions performance regressions between runs\n- User wants to understand executor skew, GC pressure, shuffle overhead, or spill\n- User asks about Gluten/Velox offloading effectiveness\n\n## Prerequisites\n\n- A running Spark History Server accessible via `spark-history-cli`\n- If the CLI is not installed: `pip install spark-history-cli`\n- Default server: `http://localhost:18080` (override with `--server`)\n\n## Core Workflow\n\n### 1. Gather Context\n\nAlways start by understanding what the user has and what they want to know:\n- Which application(s)? Get app IDs.\n- Single app diagnosis or comparison between two apps?\n- Specific query concern or overall app performance?\n- What changed between runs (config, data, Spark version, Gluten version)?\n\n### 2. Collect Data\n\nUse `--json` for all data collection so you can reason over structured data.\n\n**For single-app diagnosis**, collect in this order:\n```bash\n# Overview first\nspark-history-cli --json -a <app> summary\nspark-history-cli --json -a <app> env\n\n# Then drill into workload\nspark-history-cli --json -a <app> sql                    # all SQL executions\nspark-history-cli --json -a <app> stages                 # all stages\nspark-history-cli --json -a <app> executors --all         # executor metrics\n```\n\n**For app comparison**, collect the same data for both apps.\n\n**For specific query diagnosis**, also fetch:\n```bash\nspark-history-cli --json -a <app> sql <exec-id>          # SQL detail with nodes/edges\nspark-history-cli -a <app> sql-plan <exec-id> --view final   # post-AQE plan\nspark-history-cli -a <app> sql-plan <exec-id> --view initial # pre-AQE plan\nspark-history-cli --json -a <app> sql-jobs <exec-id>     # linked jobs\nspark-history-cli --json -a <app> stage-summary <stage>  # task quantiles for slow stages\nspark-history-cli --json -a <app> stage-tasks <stage> --sort-by -runtime --length 10  # stragglers\n```\n\n### 3. Analyze\n\nApply the diagnostic rules from `references/diagnostics.md` to identify issues.\nKey areas to check:\n- **Duration breakdown**: Where is time spent? (stages, tasks, shuffle, GC)\n- **Skew detection**: Compare p50 vs p95 in stage-summary; >3x ratio suggests skew\n- **GC pressure**: Total GC time vs executor run time; >10% is concerning\n- **Shuffle overhead**: Large shuffle read/write relative to input size\n- **Spill**: Any memory or disk spill indicates memory pressure\n- **Straggler tasks**: Tasks much slower than peers (check stage-tasks sorted by runtime)\n- **Config issues**: Suboptimal shuffle partitions, executor sizing, serializer choice\n\n### 4. Compare (when applicable)\n\nFor TPC-DS benchmark comparisons, see `references/comparison.md` for the structured approach:\n- Match queries by name (q1, q2, ..., q99)\n- Calculate speedup/regression per query\n- Identify top-N improved and regressed queries\n- Drill into regressed queries to find root cause\n- Compare configurations side-by-side\n\n### 5. Report\n\nProduce two outputs:\n1. **Conversation summary**: Key findings and top recommendations (concise, actionable)\n2. **Detailed report file**: Full analysis saved to disk as Markdown\n\nReport structure:\n```markdown\n# Spark Performance Report\n\n## Executive Summary\n<2-3 sentence overview of findings>\n\n## Application Overview\n<summary data for each app>\n\n## Findings\n### Finding 1: <title>\n- **Severity**: High/Medium/Low\n- **Evidence**: <specific metrics>\n- **Recommendation**: <what to change>\n\n## Configuration Comparison (if comparing)\n<side-by-side diff of key Spark properties>\n\n## Query-Level Analysis (if TPC-DS)\n<table of query durations with speedup/regression>\n\n## Recommendations\n<prioritized list of actionable changes>\n```\n\n## Diagnostic Quick Reference\n\nThese are the most impactful things to check. For the full diagnostic ruleset, see `references/diagnostics.md`.\n\n| Symptom | What to Check | CLI Command |\n|---------|--------------|-------------|\n| Slow overall | Duration breakdown by stage | `summary`, `stages` |\n| Task skew | p50 vs p95 duration | `stage-summary <id>` |\n| GC pressure | GC time vs run time per executor | `executors --all` |\n| Shuffle heavy | Shuffle bytes vs input bytes | `stages`, `stage <id>` |\n| Memory spill | Spill bytes > 0 | `stage <id>`, `stage-summary <id>` |\n| Straggler tasks | Top tasks by runtime | `stage-tasks <id> --sort-by -runtime` |\n| Bad config | Partition count, executor sizing | `env`, `summary` |\n| AQE ineffective | Initial vs final plan difference | `sql-plan <id> --view initial/final` |\n| Gluten fallback | Non-Transformer nodes in final plan | `sql-plan <id> --view final` |\n| Small files read | Avg file size < 3MB, files > 100 | `sql <exec-id>` node metrics |\n| Small files written | Avg file size < 3MB, files > 100 | `sql <exec-id>` node metrics |\n| Broadcast too large | Broadcast data > 1GB | `sql <exec-id>` node metrics |\n| SMJ→BHJ conversion | SMJ with small input side | `sql-plan <id> --view final` |\n| Large cross join | Cross join rows > 10B | `sql <exec-id>` node metrics |\n| Long filter condition | Filter condition > 1000 chars | `sql-plan <id> --view final` |\n| Full scan on partitioned | Missing partition/cluster filters | `sql-plan <id> --view final` |\n| Large partition size | Max partition > 5GB | `stage-summary <id>` |\n| Wasted cores | Idle cores > 50% | `executors --all` |\n| Memory over-provisioned | Max usage < 70% | `executors --all` |\n| Driver memory risk | Driver heap > 95% | `executors --all` |\n| Iceberg inefficient replace | Files replaced > 30%, records < 30% | `sql <exec-id>` node metrics |\n\n## SQL Plan Analysis\n\nWhen diagnosing specific SQL queries, analyze the SQL plan nodes for these patterns:\n\n- **File I/O efficiency**: Check scan/write node metrics for `files read`, `bytes read`, `files written`, `bytes written`. Calculate average file size — small files (< 3MB) are a common hidden bottleneck.\n- **Join strategy**: Look for `SortMergeJoin` nodes where one input is significantly smaller than the other. These may benefit from broadcast hints or AQE tuning.\n- **Broadcast sizing**: Check `BroadcastExchange` node `data size` metric. Broadcasts > 1 GB cause excessive memory pressure and network overhead.\n- **Cross joins**: Identify `BroadcastNestedLoopJoin` or `CartesianProduct` nodes. Calculate total scanned rows from input sizes — cross joins on large tables are extremely dangerous.\n- **Filter complexity**: Inspect `Filter` node conditions. Very long conditions (> 1000 chars) with large IN-lists or OR chains should be converted to joins.\n- **Partition pruning**: For Delta Lake and Iceberg tables, verify that scan nodes show partition filters being applied. Full scans on partitioned tables waste I/O.\n- **Partition sizing**: Check stage task distribution for oversized partitions (> 5GB). These cause OOM risk, long tail tasks, and GC pressure.\n\nUse `sql <exec-id>` for node-level metrics and `sql-plan <exec-id> --view final` for post-AQE plan structure.\n\n## Lakehouse Awareness\n\nWhen analyzing workloads on Delta Lake or Apache Iceberg tables:\n\n### Delta Lake\n- **OPTIMIZE**: Recommend `OPTIMIZE` for tables with small file problems detected in scan metrics\n- **Z-ORDER**: Check if queries filter on z-ordered columns; if not, the z-ordering provides no benefit\n- **Liquid Clustering**: For Databricks, check if cluster key filters are being applied in scans\n- **Full scans**: Flag scans on partitioned Delta tables without partition filters\n\n### Apache Iceberg\n- **Copy-on-Write overhead**: For update/delete workloads, check if files replaced >> records changed — this indicates COW overhead\n- **Merge-on-Read**: Recommend `write.merge-mode=merge-on-read` for update-heavy tables\n- **Table maintenance**: Recommend `rewrite_data_files` for small file compaction\n- **Bulk replace detection**: If > 60% of table files are replaced in a single operation, flag potential misuse\n\n### General Lakehouse Checks\n- File sizes in scan/write metrics (target ~128MB per file)\n- Partition filter pushdown in scan nodes\n- Table statistics availability for cost-based optimization\n\n## Gluten/Velox Awareness\n\nWhen analyzing Gluten-accelerated applications:\n- **Plan nodes**: `*Transformer` and `*ExecTransformer` nodes indicate Gluten-offloaded operators\n- **Fallback detection**: Non-Transformer nodes in the final plan (e.g., `SortMergeJoin` instead of `ShuffledHashJoinExecTransformer`) indicate Gluten fallback — these are performance-critical to investigate\n- **Columnar exchanges**: `ColumnarExchange` and `ColumnarBroadcastExchange` are Gluten's native shuffle — look for `VeloxColumnarToRow` transitions which indicate fallback boundaries\n- **Native metrics**: Gluten stages may show different metric patterns (lower GC, different memory profiles) than vanilla Spark stages\n\n## References\n\n- `references/diagnostics.md` — Full diagnostic ruleset with thresholds and heuristics\n- `references/comparison.md` — TPC-DS benchmark comparison methodology","tags":["spark","advisor","history","cli","yaooqinn","agent-skills","benchmark","diagnostics","gluten","performance","spark-history-server","tpc-ds"],"capabilities":["skill","source-yaooqinn","skill-spark-advisor","topic-agent-skills","topic-benchmark","topic-cli","topic-diagnostics","topic-gluten","topic-performance","topic-spark","topic-spark-history-server","topic-tpc-ds","topic-velox"],"categories":["spark-history-cli"],"synonyms":[],"warnings":[],"endpointUrl":"https://skills.sh/yaooqinn/spark-history-cli/spark-advisor","protocol":"skill","transport":"skills-sh","auth":{"type":"none","details":{"cli":"npx skills add yaooqinn/spark-history-cli","source_repo":"https://github.com/yaooqinn/spark-history-cli","install_from":"skills.sh"}},"qualityScore":"0.461","qualityRationale":"deterministic score 0.46 from registry signals: · indexed on github topic:agent-skills · 22 github stars · SKILL.md body (9,718 chars)","verified":false,"liveness":"unknown","lastLivenessCheck":null,"agentReviews":{"count":0,"score_avg":null,"cost_usd_avg":null,"success_rate":null,"latency_p50_ms":null,"narrative_summary":null,"summary_updated_at":null},"enrichmentModel":"deterministic:skill-github:v1","enrichmentVersion":1,"enrichedAt":"2026-04-23T13:02:30.812Z","embedding":null,"createdAt":"2026-04-18T23:05:36.881Z","updatedAt":"2026-04-23T13:02:30.812Z","lastSeenAt":"2026-04-23T13:02:30.812Z","tsv":"'-3':642 '0':734 '1':113,246,612,651,987 '10':464,514 '100':794,806 '1000':847,1027 '10b':838 '128mb':1250 '18080':240 '1gb':815 '2':294,622,641 '3':466 '30':904,906 '3mb':792,804,948 '3x':501 '4':558 '5':607 '50':879 '5gb':871,1075 '60':1228 '70':888 '95':896 'acceler':1273 'access':219 'action':621 'actual':186 'advic':183 'advisor':3,50 'also':383 'alway':249 'analysi':627,663,912 'analyz':146,467,918,1108,1270 'apach':8,1114,1178 'app':31,93,101,111,141,267,270,276,282,313,370,378 'appli':80,468,1058,1164 'applic':10,162,264,561,647,1274 'approach':573 'aqe':409,423,760,976,1102 'area':478 'ask':137,158,180,208 'avail':1261 'averag':943 'avg':789,801 'awar':1106,1268 'bad':752 'base':184,1265 'bash':97,319,385 'benchmark':36,173,566,1360 'benefit':971,1152 'bhj':820 'bottleneck':45,85,953 'boundari':1328 'breakdown':482,696 'broadcast':810,813,973,978,986 'broadcastexchang':981 'broadcastnestedloopjoin':999 'bulk':1224 'byte':724,727,733,936,940 'calcul':581,942,1003 'cartesianproduct':1001 'caus':600,989,1077 'chain':1036 'chang':285,1193 'char':848,1028 'check':480,542,679,690,929,980,1068,1135,1157,1188,1243 'choic':557 'cli':61,67,109,117,124,131,224,227,236,325,332,343,353,362,389,400,414,428,439,453,691 'cluster':1154,1159 'collect':295,302,315,372 'column':1143 'columnar':1311 'columnarbroadcastexchang':1315 'columnarexchang':1313 'command':692 'common':951 'compact':1223 'compar':5,34,171,493,559,601,659 'comparison':273,371,567,657,1361 'complex':1019 'concern':279,516 'concis':620 'condit':844,846,1023,1026 'config':288,549,753 'configur':602,656 'context':248 'convers':613,821 'convert':1039 'copi':1181 'copy-on-writ':1180 'core':244,876,878 'cost':1264 'cost-bas':1263 'count':755 'cow':1196 'critic':1308 'cross':833,835,996,1010 'danger':1017 'data':18,73,148,188,289,296,301,309,375,814,983,1218 'databrick':1156 'default':237 'delta':1045,1111,1117,1173 'detail':394,623 'detect':492,1128,1226,1287 'diagnos':4,91,104,914 'diagnosi':271,314,382 'diagnost':81,470,669,683,1350 'differ':766,1335,1340 'direct':70 'disk':530,630 'distribut':1071 'drill':337,593 'driver':891,894 'ds':41,178,565,667,1359 'durat':481,695,706 'e.g':1296 'effect':212 'effici':928 'engin':56 'env':335,758 'especi':175 'evid':654 'excess':990 'exchang':1312 'exectransform':1279 'execut':187,349,639 'executor':134,199,365,367,511,554,718,719,756,880,889,897 'extrem':1016 'fallback':773,1286,1303,1327 'fetch':384 'file':625,787,790,793,799,802,805,902,926,934,938,944,947,1126,1190,1219,1222,1231,1244,1252 'filter':843,845,860,1018,1021,1056,1138,1161,1177,1254 'final':406,764,779,785,831,853,865,1098,1294 'find':43,151,598,616,646,649,650 'first':321 'flag':1169,1238 'full':626,682,854,1059,1167,1349 'gather':72,247 'gb':988 'gc':47,201,490,505,508,710,712,1084,1339 'general':1241 'get':98,266 'gluten':292,772,1272,1283,1302,1317,1331 'gluten-acceler':1271 'gluten-offload':1282 'gluten/velox':210,1267 'heap':895 'heavi':722,1212 'heurist':82,1355 'hidden':952 'high/medium/low':653 'hint':974 'histori':16,60,66,77,108,116,123,130,217,223,235,324,331,342,352,361,388,399,413,427,438,452 'i/o':927,1065 'iceberg':899,1048,1115,1179 'id':102,268 'identifi':84,475,585,998 'idl':877 'impact':676 'improv':88,589 'in-list':1031 'indic':532,1195,1281,1301,1326 'ineffect':761 'ineffici':900 'initi':420,762 'initial/final':771 'input':524,726,825,962,1008 'inspect':1020 'instal':230,232 'instead':1298 'investig':1310 'issu':476,550 'job':433,435 'join':834,836,954,997,1011,1041 'json':110,118,125,132,298,326,333,344,354,363,390,429,440,454 'key':477,615,1160 'know':262 'lake':1046,1112,1118 'lakehous':1105,1242 'larg':519,812,832,866,1013,1030 'latest':100 'length':463 'level':662,1091 'limit':112 'link':434 'liquid':1153 'list':1033 'localhost':239 'long':842,1025,1080 'look':956,1321 'lower':1338 'mainten':1215 'markdown':632,635 'match':574 'max':869,886 'may':970,1333 'memori':528,533,730,882,892,991,1341 'mention':190 'merg':1199,1206 'merge-on-read':1198,1205 'methodolog':1362 'metric':368,797,809,818,841,909,932,985,1092,1131,1248,1330,1336 'miss':858 'misus':1240 'mode':1204 'much':538 'n':588 'name':577 'nativ':1319,1329 'network':994 'node':777,796,808,817,840,908,922,931,959,982,1002,1022,1053,1090,1258,1276,1280,1291 'node-level':1089 'nodes/edges':396 'non':775,1289 'non-transform':774,1288 'offload':211,1284 'one':95,961 'oom':1078 'oper':1237,1285 'optim':7,1119,1121,1266 'order':318,1134,1142,1149 'output':611 'over-provis':883 'overal':281,694 'overhead':204,518,995,1184,1197 'overrid':241 'overs':1073 'overview':320,644,648 'p50':494,703 'p95':496,705 'partit':553,754,857,867,870,1042,1055,1062,1066,1074,1172,1176,1253 'partition/cluster':859 'pattern':925,1337 'peer':541 'per':583,717,1251 'perform':44,55,191,283,637,1307 'performance-crit':1306 'pip':231 'plan':404,410,418,424,765,769,780,783,829,851,863,911,921,1096,1103,1275,1295 'post':408,1101 'post-aq':407,1100 'potenti':1239 'pre':422 'pre-aq':421 'prerequisit':213 'pressur':48,202,506,534,711,992,1085 'problem':1127 'produc':150,609 'profil':1342 'provid':1150 'provis':885 'prune':1043 'pushdown':1255 'q1':578 'q2':579 'q99':580 'quantil':446 'queri':13,165,278,381,575,584,592,596,661,917,1137 'query-level':660 'quick':89,670 'ratio':502 'read':788,935,937,1201,1208 'read/write':521 'reason':306 'recommend':87,619,655,668,1120,1202,1216 'record':905,1192 'refer':671,1347 'references/comparison.md':569,1356 'references/diagnostics.md':473,686,1348 'regress':192,591,595 'relat':522 'replac':901,903,1191,1225,1233 'report':608,624,633,638 'result':42 'rewrit':1217 'risk':893,1079 'root':599 'row':837,1006 'rule':471 'ruleset':684,1351 'run':37,174,194,215,287,512,715 'runtim':462,548,744,751 'save':628 'scan':855,1005,1052,1060,1130,1166,1168,1170,1257 'scan/write':930,1247 'see':568,685 'sentenc':643 'serial':556 'server':17,78,218,238,243 'sever':652 'shot':96 'show':1054,1334 'shuffl':203,489,517,520,552,721,723,1320 'shuffledhashjoinexectransform':1300 'side':604,606,826 'side-by-sid':603 'signific':964 'singl':269,312,1236 'single-app':311 'size':525,555,757,791,803,868,945,979,984,1009,1067,1245 'skew':46,200,491,504,702 'skill':21,68,144,156 'skill-spark-advisor' 'slow':33,142,167,448,693 'slower':539 'small':786,798,824,946,1125,1221 'smaller':965 'smj':819,822 'sort':460,546,749 'sort-bi':459,748 'sortmergejoin':958,1297 'source-yaooqinn' 'spark':2,9,15,30,49,54,59,65,76,107,115,122,129,161,216,222,234,290,323,330,341,351,360,387,398,412,426,437,451,636,1345 'spark-advisor':1 'spark-history-c':58,64,106,114,121,128,221,233,322,329,340,350,359,386,397,411,425,436,450 'specif':277,380,915 'speedup/regression':582 'spent':486 'spill':206,526,531,731,732 'sql':12,164,346,348,392,393,403,417,432,768,782,795,807,816,828,839,850,862,907,910,916,920,1087,1095 'sql-job':431 'sql-plan':402,416,767,781,827,849,861,1094 'stage':127,356,358,443,449,457,487,499,544,698,700,708,728,729,735,737,746,873,1069,1332,1346 'stage-summari':442,498,707,736,872 'stage-task':456,543,745 'start':90,250 'statist':1260 'straggler':465,535,739 'strategi':955 'structur':308,572,634,1104 'suboptim':551 'suggest':503 'summari':120,328,444,500,614,640,699,709,738,759,874 'symptom':687 'tabl':1014,1049,1063,1116,1123,1174,1213,1214,1230,1259 'tail':1081 'target':1249 'task':445,458,488,536,537,545,701,740,742,747,1070,1082 'thing':677 'threshold':1353 'time':485,509,513,713,716 'top':587,618,741 'top-n':586 'topic-agent-skills' 'topic-benchmark' 'topic-cli' 'topic-diagnostics' 'topic-gluten' 'topic-performance' 'topic-spark' 'topic-spark-history-server' 'topic-tpc-ds' 'topic-velox' 'total':507,1004 'tpc':40,177,564,666,1358 'tpc-ds':39,176,563,665,1357 'transform':776,1277,1290 'transit':1324 'tune':182,977 'two':35,172,275,610 'understand':27,198,252 'updat':1211 'update-heavi':1210 'update/delete':1186 'usag':887 'use':14,19,57,154,297,1086 'user':24,157,168,179,189,195,207,255 'vanilla':1344 'veloxcolumnartorow':1323 'verifi':1050 'version':291,293 'via':62,220 'view':405,419,770,784,830,852,864,1097 'vs':495,510,704,714,725,763 'want':25,169,196,260 'wast':875,1064 'whenev':22 'without':1175 'workflow':245 'workload':339,1109,1187 'write':1183 'write.merge':1203 'written':800,939,941 'z':1133,1141,1148 'z-order':1132,1140,1147","prices":[{"id":"39d5e46b-b736-4f32-bb6b-d06c551a8e46","listingId":"4317be7d-f5ba-4734-bb15-45118030c79b","amountUsd":"0","unit":"free","nativeCurrency":null,"nativeAmount":null,"chain":null,"payTo":null,"paymentMethod":"skill-free","isPrimary":true,"details":{"org":"yaooqinn","category":"spark-history-cli","install_from":"skills.sh"},"createdAt":"2026-04-18T23:05:36.881Z"}],"sources":[{"listingId":"4317be7d-f5ba-4734-bb15-45118030c79b","source":"github","sourceId":"yaooqinn/spark-history-cli/spark-advisor","sourceUrl":"https://github.com/yaooqinn/spark-history-cli/tree/main/skills/spark-advisor","isPrimary":false,"firstSeenAt":"2026-04-18T23:05:36.881Z","lastSeenAt":"2026-04-23T13:02:30.812Z"}],"details":{"listingId":"4317be7d-f5ba-4734-bb15-45118030c79b","quickStartSnippet":null,"exampleRequest":null,"exampleResponse":null,"schema":null,"openapiUrl":null,"agentsTxtUrl":null,"citations":[],"useCases":[],"bestFor":[],"notFor":[],"kindDetails":{"org":"yaooqinn","slug":"spark-advisor","github":{"repo":"yaooqinn/spark-history-cli","stars":22,"topics":["agent-skills","benchmark","cli","diagnostics","gluten","performance","spark","spark-history-server","tpc-ds","velox"],"license":"apache-2.0","html_url":"https://github.com/yaooqinn/spark-history-cli","pushed_at":"2026-03-22T17:59:03Z","description":"CLI tool for querying Apache Spark History Server REST API","skill_md_sha":"caafacbbf816eb4f420f2cdc69c60b15fd5a1f6a","skill_md_path":"skills/spark-advisor/SKILL.md","default_branch":"main","skill_tree_url":"https://github.com/yaooqinn/spark-history-cli/tree/main/skills/spark-advisor"},"layout":"multi","source":"github","category":"spark-history-cli","frontmatter":{"name":"spark-advisor","description":"Diagnose, compare, and optimize Apache Spark applications and SQL queries using Spark History Server data. Use this skill whenever the user wants to understand why a Spark app is slow, compare two benchmark runs or TPC-DS results, find performance bottlenecks (skew, GC pressure, shuffle spill, straggler tasks), get tuning recommendations, or optimize Spark/Gluten configurations. Also trigger when the user mentions 'diagnose', 'compare runs', 'why is this query slow', 'tune my Spark job', 'benchmark comparison', 'performance regression', or asks about executor skew, shuffle overhead, AQE effectiveness, or Gluten offloading issues."},"skills_sh_url":"https://skills.sh/yaooqinn/spark-history-cli/spark-advisor"},"updatedAt":"2026-04-23T13:02:30.812Z"}}