Konfigurera ett belastningstest för slutpunkter för vektorsökning

Den här sidan innehåller vägledning, exempelkod och en exempelanteckningsbok för slutpunkter för belastningstestning av vektorsökning. Belastningstestning hjälper dig att förstå prestanda och produktionsberedskap för en slutpunkt för vektorsökning innan den distribueras till produktion. Belastningstestning kan berätta om:

  • Svarstid på olika skalningsnivåer
  • Dataflödesgränser och flaskhalsar (begäranden per sekund, svarstidsuppdelning)
  • Felfrekvenser under varaktig belastning
  • Resursanvändning och kapacitetsplanering

Mer information om belastningstestning och relaterade begrepp finns i Belastningstestning för serveringsslutpunkter.

Kravspecifikation

Innan du påbörjar de här stegen måste du ha en distribuerad slutpunkt för vektorsökning och ett tjänsthuvudnamn med Can Query-behörigheter på slutpunkten. Se Steg 1: Konfigurera autentisering med tjänstprincip.

Ladda ned och importera en kopia av följande filer och en exempelanteckningsbok till din Azure Databricks-arbetsyta:

  • input.json. Det här är ett exempel på input.json filen som anger nyttolasten som skickas av alla samtidiga anslutningar till slutpunkten. Du kan ha flera filer om det behövs. Om du använder exempelanteckningsboken genereras den här filen automatiskt från den angivna indatatabellen.
  • fast_vs_load_test_async_load.py. Ladda upp det här skriptet till din arbetsyta (till exempel /Workspace/Users/<your-username>/fast_vs_load_test_async_load.py) och ange locust_script_path notebook-parametern till dess sökväg. Det här skriptet hanterar autentisering, leverans av nyttolast och insamling av felsökningsmetrik.
  • Följande notebook-exempel, som kör belastningstesterna. För bästa prestanda ska du köra den här notebooken på ett kluster med en enda nod och ett stort antal kärnor (Locust skalar över alla tillgängliga processorer). Högt minne rekommenderas för frågor med förgenererade inbäddningar.

Exempelnotebook och snabbstart

Kom igång med följande exempelanteckningsbok. Det stöder två utforskningslägen: en gradvis svepning som testar specifika samtidighetsnivåer som du definierar och ett binärt sökläge som automatiskt hittar den maximala hållbara QPS (brytpunkt) i några få steg. Alla parametrar konfigureras med widgetar, så notebook-filen kan köras interaktivt eller som ett Databricks-jobb utan kodredigeringar.

Anteckningsbok för Locust-belastningstest

Hämta anteckningsbok

Ramverk för belastningstestning: Gräshoppa

Locust är ett ramverk för belastningstestning med öppen källkod som gör att du kan göra följande:

  • Variera antalet samtidiga klientanslutningar
  • Kontrollera hur snabbt anslutningarna skapas
  • Mäta slutpunktsprestanda under hela testet
  • Identifiera automatiskt och använd alla tillgängliga CPU-kärnor

Exempelanteckningsboken använder --processes -1 flaggan för att automatiskt identifiera CPU-kärnor och utnyttja dem fullt ut.

Om Locust begränsas av processorn visas det ett meddelande i utdata.

Steg 1: Konfigurera autentisering med tjänstens huvudnamn

Viktigt!

För produktionsliknande prestandatestning bör du alltid använda autentisering med OAuth-huvudanvändare. Tjänsthuvudprinciper ger därigenom upp till 100 ms snabbare svarstid och högre överföringsgränser för en begäran jämfört med personliga åtkomsttoken (PAT).

Skapa och konfigurera tjänstens huvudnamn

  1. Skapa ett huvudnamn för Databricks-tjänsten. Anvisningar finns i Lägga till tjänstens huvudnamn i ditt konto.

  2. Bevilja behörigheter:

    • Gå till slutpunktssidan för vektorsökning.
    • Klicka på Behörigheter.
    • Ge tjänstens huvudnamn Can Query-behörigheter .
  3. Skapa OAuth-hemlighet.

    • Gå till tjänsthuvudmannens detaljsida.
    • Klicka på fliken Hemligheter .
    • Klicka på Generera hemlighet.
    • Ange livslängd (rekommendera 365 dagar för långsiktig testning).
    • Kopiera både klient-ID och hemlighet omedelbart.
  4. Lagra autentiseringsuppgifter på ett säkert sätt.

    • Skapa ett Databricks-hemlighetsområde. Anvisningar finns i Självstudie: Skapa och använda en Databricks-hemlighet.
    • Som du ser i följande kodexempel lagrar du klient-ID:t för tjänstens huvudnamn som service_principal_client_id och lagrar OAuth-hemligheten som service_principal_client_secret.
    # In a Databricks notebook
    dbutils.secrets.put("load-test-auth", "service_principal_client_id", "<CLIENT_ID>")
    dbutils.secrets.put("load-test-auth", "service_principal_client_secret", "<SECRET>")
    

Steg 2: Konfigurera belastningstestet

Notebook-konfiguration

Konfigurera anteckningsbokparametrarna med widgetarna överst i anteckningsboken. När du kör notebook-filen som ett Databricks-jobb skickar du dessa värden som jobbparametrar. Inga kodredigeringar krävs.

Parameter Description Rekommenderat värde
endpoint_name Namnet på vektorsökningens slutpunkt Ditt slutpunktsnamn
index_name Fullständigt indexnamn (catalog.schema.index) Ditt indexnamn
test_table Källtabell för exempelfrågor från (catalog.schema.table) Din indextabell för indata
query_column Textkolumn som ska användas för hanterade inbäddningar Lämna som text eller ange som ditt kolumnnamn
embedding_column Kolumn som innehåller förberäknade inbäddningsvektorer. Används endast för självhanterade inbäddningar. Lämna tomt för hanterade inbäddningar
sample_size Antal frågor som ska provas för testet 1000
target_concurrencies Kommaavgränsad lista över samtidiga klientantal som ska testas 5,10,20,50
step_duration_seconds Varaktighet i sekunder per samtidighetsnivå. Ett värde gäller för alla nivåer eller ger en per nivå som en kommaavgränsad lista. 300 (5 minuter)
secret_scope_name Namn på Databricks hemlighetsomfång Ditt omfångsnamn
locust_script_path Arbetsytans sökväg till skriptet fast_vs_load_test_async_load.py /Workspace/Users/<your-username>/fast_vs_load_test_async_load.py
output_table (Valfritt) Deltatabell för lagring av resultat i (catalog.schema.table). Skapas automatiskt vid första körningen. catalog.schema.load_test_results
run_name Ange ett namn eller en kommentar för att tagga den här körningen för senare analys En beskrivande etikett
exploration_mode gradual sveper igenom target_concurrencies i ordning. binary_search hittar brytpunkten automatiskt (se Utforskning av brytpunkt). gradual
max_target_qps (binary_search endast) Övre gräns för QPS-sökningen 500
exploration_steps (binary_search endast) Maximalt antal binära sök iterationer 8
error_rate_threshold (binary_search endast) Högsta godtagbara felfrekvens (%) för ett steg som ska räknas som en framgång 1.0
num_results Antal resultat som ska returneras per fråga 10
columns_to_return Kommaavgränsad lista över kolumner som ska returneras i frågeresultat (till exempel id,text). Lämna det tomt för att returnera alla kolumner. Lämna tomt som standard

Förvaltade vs. självförvaltade inbäddningar

Notebook-filen stöder både hanterade inbäddningar (där Databricks genererar inbäddningar vid frågetillfället) och självhanterade inbäddningar (där du skickar förberäknade vektorer direkt). Konfigurera lämpliga parametrar baserat på din indextyp.

Indextyp Parameter som ska anges Lämna oet
Hanterade inbäddningar (Delta Sync-index med Databricks-hanterad inbäddningsmodell) query_column – det textkolumnnamn som ska användas som fråga embedding_column (lämna tomt)
Självhanterade inbäddningar (Delta Sync eller Direct Vector Access-index med förberäknade vektorer) embedding_column — kolumnen som innehåller förkomputerade inbäddningsvektorer query_column

Anmärkning

För hanterade inbäddningsindex mäter belastningstestet svarstid från slutpunkt till slutpunkt, inklusive inbäddningsgenereringstid. Om din inbäddningsslutpunkt skalas till noll, uppstår kallstartsfördröjning vid den första testkörningen. Se Identifiera flaskhalsen för inbäddningsmodellen för hur du isolerar svarstid för inbäddning från söksvarstid.

Varför 5-10 minuter?

En minsta testvaraktighet på 5 minuter är kritisk.

  • De första frågorna kan omfatta kostnader för kallstart.
  • Slutpunkter behöver tid för att uppnå prestanda med stabilt tillstånd.
  • Automatisk skalning av modellen som betjänar slutpunkter (om den är aktiverad) tar tid att aktivera.
  • Korta tester missar strypningsbeteenden under kontinuerlig belastning.

I följande tabell visas rekommenderade testvaraktigheter beroende på ditt testmål.

Testtyp Testlängd Testmål
Snabb röktest 2–3 minuter Verifiera grundläggande funktioner
Prestandabaslinje 5–10 minuter Tillförlitliga mått för stabilt tillstånd
Stresstest 15–30 minuter Identifiera resursöverbelastning
Uthållighetstestning 1–4 timmar Degradering, svarstidsstabilitet

Utforskning av brytpunkt (binärt sökläge)

Förutom den gradvisa svepningen (exploration_mode=gradual) stöder notebook-filen ett automatiskt binärt sökläge som letar upp maximalt hållbart QPS utan att du behöver ange samtidighetsnivåerna manuellt.

Så här fungerar det

Ange exploration_mode=binary_search och ange max_target_qps (till exempel 500). Notebook-filen använder Little's Law (concurrency = QPS × avg_latency_sec) för att konvertera varje QPS-mål till en uppskattad samtidighetsnivå och kör sedan en binär sökning enligt följande:

  1. Börja vid max_target_qps / 2 (250 i exemplet).
  2. Om felfrekvensen är lägre error_rate_threshold än (lyckades) höjer du den lägre gränsen och provar en högre QPS (375, sedan 500 och så vidare).
  3. Om felfrekvensen överskrider tröskelvärdet (fel) sänker du den övre gränsen och försöker halvvägs mellan den senaste lyckade och misslyckade åtgärden.
  4. Upprepa för upp till exploration_steps steg (standard 8) eller tills sökområdet begränsas till inom 5% av max_target_qps.

Följande tabell visar hur sökningen konvergerar efter en hypotetisk slutpunkt med en brytpunkt runt 430 QPS:

Steg QPS-mål Felfrekvens Outcome Nytt intervall
1 250 0.1% FRAMGÅNG [250, 500]
2 375 0,3% FRAMGÅNG [375, 500]
3 437 4.5% MISSLYCKANDE [375, 437]
4 406 0,8 % FRAMGÅNG [406, 437]
5 421 2.1% MISSLYCKANDE [406, 421]

Efter 5–8 steg konvergerar sökningen på brytpunkten – i det här exemplet ungefär 406–421 QPS – med betydligt färre testkörningar än en exhaustiv sökning.

När du ska använda varje läge

Läge När det bör användas
gradual Du känner redan till det förväntade driftsintervallet och vill karakterisera prestanda på specifika samtidighetsnivåer.
binary_search Du vill hitta maximalt hållbara QPS snabbt, utan att känna till samtidighetsnivåerna i förväg.

Steg 3. Utforma frågeuppsättningen

När det är möjligt bör frågeuppsättningen återspegla den förväntade produktionstrafiken så nära som möjligt. Mer specifikt bör du försöka matcha den förväntade fördelningen av frågor när det gäller innehåll, komplexitet och mångfald.

  • Använd realistiska frågor. Använd inte slumpmässig text, till exempel "testfråga 1234".

  • Matcha produktionstrafikens förväntade distribution. Om du förväntar dig 80% vanliga frågor, 15% medelfrekventa frågor och 5% sällsynta frågor, bör frågeuppsättningen återspegla den fördelningen.

  • Matcha den typ av fråga som du förväntar dig att se i produktion. Om du till exempel förväntar dig att produktionsfrågor ska använda hybridsökning eller -filter bör du också använda dem i frågeuppsättningen.

    Exempelfråga med filter:

    {
      "query_text": "wireless headphones",
      "num_results": 10,
      "filters": { "brand": "Sony", "noise_canceling": true }
    }
    

    Exempelfråga med hybridsökning:

    {
      "query_text": "best noise canceling headphones for travel",
      "query_type": "hybrid",
      "num_results": 10
    }
    

Förfrågevariation och cachehantering

Slutpunkter för vektorsökning cachelagrar flera typer av frågeresultat för att förbättra prestandan. Den här cachelagringen kan påverka belastningstestresultatet. Därför är det viktigt att vara uppmärksam på frågeuppsättningens mångfald. Om du till exempel upprepade gånger skickar samma uppsättning frågor testar du cachen, inte den faktiska sökprestandan.

Användning: När: Example
Identiska eller få frågor
  • Din produktionstrafik har hög frågerepetition (till exempel "populära produkter")
  • Du testar cacheeffektivitet specifikt
  • Ditt program drar nytta av cachelagring (till exempel instrumentpaneler med fasta frågor)
  • Du vill mäta bästa möjliga cachelagrade prestanda
En produktrekommendationswidget som visar "trendande objekt" – samma fråga körs tusentals gånger per timme.
Olika frågor
  • Din produktionstrafik har unika användarfrågor (till exempel sökmotorer eller chattrobotar)
  • Du vill mäta sämsta möjliga prestanda utan cache
  • Du vill testa prestanda för indexgenomsökning, inte cacheprestanda
  • Frågor har hög kardinalitet (miljontals möjliga variationer)
En e-handelssökning där varje användare skriver olika produktsökningar.

Ytterligare rekommendationer finns i Sammanfattning av metodtips.

Alternativ för att skapa en frågeuppsättning

Kodflikarna visar tre alternativ för att skapa en mängd olika frågeuppsättningar. Det finns ingen one-size-fits-all. Välj den som fungerar bäst för dig.

  • (Rekommenderas) Slumpmässig sampling från indexindatatabellen. Detta är en bra allmän utgångspunkt.
  • Sampling från produktionsloggar. Det här är en bra början om du har produktionsloggar. Tänk på att frågor vanligtvis ändras med tiden, så uppdatera testuppsättningen regelbundet för att hålla den uppdaterad.
  • Genererar syntetiska frågor. Detta är användbart om du inte har produktionsloggar eller om du använder komplexa filter.

Slumpmässig sampling från indatatabell

Följande kod tar exempel på slumpmässiga frågor från indexindatatabellen.

import pandas as pd
import random

# Read the index input table
input_table = spark.table("catalog.schema.index_input_table").toPandas()

# Sample random rows
n_samples = 1000
if len(input_table) < n_samples:
    print(f"Warning: Only {len(input_table)} rows available, using all")
    sample_queries = input_table
else:
    sample_queries = input_table.sample(n=n_samples, random_state=42)

# Extract the text column (adjust column name as needed)
queries = sample_queries['text_column'].tolist()

# Create query payloads
query_payloads = [{"query_text": q, "num_results": 10} for q in queries]

# Save to input.json
pd.DataFrame(query_payloads).to_json("input.json", orient="records", lines=True)

print(f"Created {len(query_payloads)} diverse queries from index input table")

Exempel från produktionsloggar

Följande kodexempel hämtas proportionellt från produktionsfrågor.

# Sample proportionally from production queries
production_queries = pd.read_csv("queries.csv")

# Take stratified sample maintaining frequency distribution
def create_test_set(df, n_queries=1000):
    # Group by frequency buckets
    df['frequency'] = df.groupby('query_text')['query_text'].transform('count')

    # Stratified sample
    high_freq = df[df['frequency'] > 100].sample(n=200)  # 20%
    med_freq = df[df['frequency'].between(10, 100)].sample(n=300)  # 30%
    low_freq = df[df['frequency'] < 10].sample(n=500)  # 50%

    return pd.concat([high_freq, med_freq, low_freq])

test_queries = create_test_set(production_queries)
test_queries.to_json("input.json", orient="records", lines=True)

Syntetiska frågor

Om du inte har produktionsloggar ännu kan du generera syntetiska olika frågor.

# Generate diverse queries programmatically
import random

# Define query templates and variations
templates = [
    "find {product} under ${price}",
    "best {product} for {use_case}",
    "{adjective} {product} recommendations",
    "compare {product1} and {product2}",
]

products = ["laptop", "headphones", "monitor", "keyboard", "mouse", "webcam", "speaker"]
prices = ["500", "1000", "1500", "2000"]
use_cases = ["gaming", "work", "travel", "home office", "students"]
adjectives = ["affordable", "premium", "budget", "professional", "portable"]

diverse_queries = []
for _ in range(1000):
    template = random.choice(templates)
    query = template.format(
        product=random.choice(products),
        product1=random.choice(products),
        product2=random.choice(products),
        price=random.choice(prices),
        use_case=random.choice(use_cases),
        adjective=random.choice(adjectives)
    )
    diverse_queries.append(query)

print(f"Generated {len(set(diverse_queries))} unique queries")

Steg 4. Testa nyttolasten

Verifiera nyttolasten innan du kör det fullständiga lasttestet:

  1. I Databricks-arbetsytan navigerar du till vektorsökningens slutpunkt.
  2. I det vänstra sidofältet klickar du på Servering.
  3. Välj slutpunkten.
  4. Klicka på Användfråga.
  5. Klistra in innehållet input.json i frågerutan.
  6. Kontrollera att slutpunkten returnerar förväntade resultat.

Detta säkerställer att belastningstestet mäter realistiska frågor, inte felsvar.

Steg 5. Kör belastningstestet

Anslutningskontroll och uppvärmning

Innan belastningstestet börjar utför anteckningsboken två förberedelsesteg:

  1. Anslutningskontroll: Skickar en enskild avsökningsfråga med autentiseringsuppgifterna för tjänsthuvudkontot. Om slutpunkten returnerar ett 401- eller 403-fel misslyckas notebooken omedelbart med ett tydligt PermissionError istället för att köra belastningstestet som bara resulterar i feldata. Detta sparar tid när autentiseringsuppgifter eller behörigheter är felkonfigurerade.

  2. Uppvärmningstest (1 minut): Kör ett kort test med låg samtidighet som värmer upp slutpunktscacheminnen och validerar ände-till-ände-flödet för begäran. Uppvärmningsresultaten används inte för prestandamått. I binärt sökläge används svarstiden för uppvärmning också som baslinje för Littles samtidighetsuppskattning för lag.

Testserie för huvudbelastning

Notebook-filen kör en serie tester med ökad samtidighet för klienten:

  • Start: Låg samtidighet (till exempel 5 samtidiga klienter)
  • Mellan: Medelhög samtidighet (till exempel 10, 20 eller 50 klienter)
  • Slut: Hög samtidighet (till exempel över 100 klienter)

Varje test körs under den tid som konfigurerats i step_duration_seconds (5–10 minuter rekommenderas).

Vad notebooken mäter

Bärbara datorn mäter och rapporterar följande:

Svarstidsmått:

  • P50 (median): Hälften av frågorna är snabbare än så här.
  • P95: 95% av frågor är snabbare än så. Det här är ett viktigt SLA-mått.
  • P99: 99% av frågor är snabbare än så här.
  • Max: Värsta möjliga svarstid.

Dataflödesmått:

  • RPS (begäranden per sekund): Lyckade frågor per sekund.
  • Totalt antal frågor: Antal slutförda frågor.
  • Lyckad frekvens: Procentandel lyckade frågor.

Fel:

  • Frågefel efter typ
  • Undantagsmeddelanden
  • Antal tidsgränser

Resultatlagring

Om parametern output_table har angetts lagrar notebook-filen en rad per samtidighetsnivå (eller per binärt söksteg) i en Delta-tabell i Unity Catalog. Tabellen skapas automatiskt vid den första körningen och läggs till vid efterföljande körningar. Varje rad innehåller run_namefälten , exploration_mode, samtidighet, lyckade/misslyckade, svarstids percentiler, RPS och binära sökspecifika fält (bs_step, bs_target_qps, bs_outcome). På så sätt kan du jämföra körningar över tid med hjälp av SQL- eller BI-verktyg.

Körs som ett Databricks-jobb

Alla notebook-parametrar definieras som dbutils.widgets, som mappas direkt till Databricks-jobbparametrar. Så här schemalägger eller automatiserar du belastningstester:

  1. Skapa ett jobb med anteckningsboken som uppgift.
  2. Ange widgetvärdena som Jobbparametrar. Inga kodredigeringar krävs.
  3. Koppla jobbet till ett kluster med en nod med många CPU-kärnor (locust-fördelar från parallella arbetare).
  4. Kör på begäran eller enligt ett schema för återkommande baslinjetester.

Steg 6. Tolka resultat

I följande tabell visas mål för bra prestanda:

Mätvärde Target Comment
P95-svarstid < 500 ms De flesta frågor är snabba
P99-svarstid < 1 s Rimlig prestanda för långsvansfrågor
Framgångsfrekvens > 99,5% Låg felfrekvens
Svarstid över tid Stabil Ingen försämring observerades under testet
Frågor per sekund Uppfyller målet Slutpunkten kan hantera förväntad trafik

Följande resultat indikerar dålig prestanda:

  • P95 > 1s. Anger att frågorna är för långsamma för användning i realtid.
  • P99 > 3 sek. Svarstid på långa frågor skadar användarupplevelsen.
  • Framgångsfrekvens < 99%. För många fel.
  • Ökad svarstid. Anger resursöverbelastning eller minnesläcka.
  • Hastighetsbegränsningsfel (429). Anger att högre slutpunktskapacitet krävs.

Kompromiss mellan RPS och svarstid

Maximal RPS är inte den optimala punkten för produktionseffektivitet. Svarstiden ökar icke-linjärt när du närmar dig maximalt dataflöde. Att arbeta med maximal RPS resulterar ofta i 2–5 gånger högre svarstid jämfört med 60–70% med maximal kapacitet.

I följande exempel visas hur du analyserar resultaten för att hitta den optimala driftpunkten.

  • Den maximala RPS är 480 vid 150 samtidiga klienter.
  • Den optimala driftpunkten är 310 RPS på 50 samtidiga klienter (65% kapacitet).
  • Svarstidsstraffet vid maximum: P95 är 4,3x högre (1,5 sekunder jämfört med 350 ms)
  • I det här exemplet är rekommendationen att storleksanpassa slutpunkten för 480 RPS-kapacitet och arbeta med ~310 RPS.
Konkurens P50 P95 P99 RPS Success Capacity
5 80 ms 120 ms 150 ms 45 100 % 10 %
10 85 ms 140 ms 180 ms 88 100 % 20%
20 95 ms 180 ms 250 ms 165 99,8% 35 %
50 150 ms 350 ms 500 ms 310 99.2% 65% ← Optimal punkt
100 250 ms 800 ms 1.2s 420 97,5% 90% ⚠️ Närmar sig max
150 450 ms 1,5 s 2.5s 480 95,0% 100% ❌ högsta RPS

Att arbeta med maximalT antal RPS kan leda till följande problem:

  • Försämring av latens. I exemplet är P95 350 ms vid 65% kapacitet men är 1,5 s vid 100% kapacitet.
  • Inget utrymme för att hantera trafiktoppar. Vid full kapacitet orsakar varje topp en timeout. Vid 65% kapacitet kan en trafiktoppar på 50% hanteras utan problem.
  • Ökade felfrekvenser. I exemplet är framgångsgraden 99,2% med 65% kapacitet men 95,0% – en felfrekvens på 5% – med 100% kapacitet.
  • Risk för resursöverbelastning. Vid maximal belastning ökar köerna, minnestrycket ökar, anslutningspoolerna börjar mättas och återställningstiden efter incidenter ökar.

I följande tabell visas rekommenderade driftpunkter för olika användningsfall.

Användningsfall Målkapacitet Logisk grund
Svarstidskänslig (sökning, chatt) 50–60% av max Prioritera låg P95/P99-svarstid
Balanserad (rekommendationer) 60-70% av max Bra balans mellan kostnader och svarstider
Kostnadsoptimerade batchjobb 70-80% av max. Acceptabel högre svarstid
Rekommenderas inte > 85% av det maximala Latensspikar, ingen burstkapacitet

Hjälpfunktioner för att beräkna driftpunkts- och slutpunktsstorlek

Hitta den optimala punkten

Följande kod ritar QPS jämfört med P95-svarstid. I diagrammet letar du efter den punkt där kurvan börjar böjas kraftigt uppåt. Det här är den optimala driftpunkten.

import matplotlib.pyplot as plt

# Plot QPS vs. P95 latency
qps_values = [45, 88, 165, 310, 420, 480]
p95_latency = [120, 140, 180, 350, 800, 1500]

plt.plot(qps_values, p95_latency, marker='o')
plt.axvline(x=310, color='green', linestyle='--', label='Optimal (65% capacity)')
plt.axvline(x=480, color='red', linestyle='--', label='Maximum (100% capacity)')
plt.xlabel('Queries Per Second (QPS)')
plt.ylabel('P95 Latency (ms)')
plt.title('QPS vs. Latency: Finding the Sweet Spot')
plt.legend()
plt.grid(True)
plt.show()

Formel för storleksrekommendation

def calculate_endpoint_size(target_qps, optimal_capacity_percent=0.65):
    """
    Calculate required endpoint capacity

    Args:
        target_qps: Your expected peak production QPS
        optimal_capacity_percent: Target utilization (default 65%)

    Returns:
        Required maximum endpoint QPS
    """
    required_max_qps = target_qps / optimal_capacity_percent

    # Add 20% safety margin for unexpected bursts
    recommended_max_qps = required_max_qps * 1.2

    return {
        "target_production_qps": target_qps,
        "operate_at_capacity": f"{optimal_capacity_percent*100:.0f}%",
        "required_max_qps": required_max_qps,
        "recommended_max_qps": recommended_max_qps,
        "burst_capacity": f"{(1 - optimal_capacity_percent)*100:.0f}% headroom"
    }

# Example
result = calculate_endpoint_size(target_qps=200)
print(f"Target production QPS: {result['target_production_qps']}")
print(f"Size endpoint for: {result['recommended_max_qps']:.0f} QPS")
print(f"Operate at: {result['operate_at_capacity']}")
print(f"Available burst capacity: {result['burst_capacity']}")

# Output:
# Target production QPS: 200
# Size endpoint for: 369 QPS
# Operate at: 65%
# Available burst capacity: 35% headroom

Identifiera flaskhalsen för inbäddningsmodellen

Om ditt index använder hanterade inbäddningar samlar notebook-filen för belastningstestet in tidsinställningen per komponent via parametern debug_level=1 för varje fråga. Resultattabellen innehåller:

  • ann_time — Tid som ägnas åt ungefärlig sökning efter närmaste granne
  • embedding_gen_time — tid som ägnas åt att generera frågeinbäddning på modellens serverdelsslutpunkt
  • reranker_time — Tid som ägnas åt att ändra rangordning (om den är aktiverad)
  • response_time — Total svarstid från slutpunkt till slutpunkt

Om embedding_gen_time är konsekvent stor i förhållande till ann_timeär inbäddningsslutpunkten flaskhalsen, inte slutpunkten för vektorsökning. Vanliga orsaker:

  • Den inbäddningsmodell som betjänar slutpunkten har Skala till noll aktiverat. Inaktivera den för testning av produktionsbelastning. Se Undvik skalning till noll för produktion.
  • Inbäddningsslutpunkten har inte tillräckligt med etablerad samtidighet för den frågefrekvens som du testar.
  • Slutpunkten för inbäddningsmodellen delas med andra arbetsbelastningar. Använd en dedikerad slutpunkt för belastningstestning.

Tips/Råd

Om du vill isolera prestanda för vektorsökning från inbäddningsmodellprestanda växlar du till självhanterade inbäddningar för belastningstestning . Skicka förkomputerade vektorer i parametern EMBEDDING_COLUMN i stället för textfrågor. Detta tar bort svarstid för inbäddning från mätningen helt och hållet.

Steg 7: Ändra storlek på slutpunkten

Använd notebookens rekommendation

Efter att ha analyserat resultaten, uppmanar anteckningsboken dig att:

  1. Välj den rad som bäst uppfyller dina svarstidskrav.
  2. Ange programmets önskade RPS.

Anteckningsboken visar sedan en rekommenderad slutpunktsstorlek. Den beräknar den kapacitet som krävs baserat på följande:

  • Målvärde för RPS
  • Observerade svarstider på olika samtidighetsnivåer
  • Tröskelvärden för framgångsfrekvens
  • Säkerhetsmarginal (vanligtvis 2x förväntad toppbelastning)

Att tänka på vid skalning

Standardslutpunkter:

  • Skala upp automatiskt för att stödja indexstorlek
  • Skala upp manuellt för att stödja genomströmning
  • Skala ned automatiskt när index tas bort
  • Skala ned manuellt för att minska kapaciteten

Lagringsoptimerade slutpunkter:

  • Skala upp automatiskt för att stödja indexstorlek
  • Skala ned automatiskt när index tas bort

Steg 8: Verifiera slutlig konfiguration

När du har uppdaterat slutpunktskonfigurationen:

  1. Vänta tills slutpunkten är klar. Det kan ta flera minuter.
  2. Kör det slutliga valideringstestet i notebook-filen.
  3. Bekräfta att prestanda uppfyller dina krav:
    • RPS ≥ målgenomströmning
    • P95-svarstid uppfyller SLA
    • Framgångsfrekvens > 99,5%
    • Inga varaktiga fel

Om verifieringen misslyckas kan du prova följande:

  • Öka slutpunktskapaciteten
  • Optimera frågekomplexitet
  • Granska filterprestanda
  • Kontrollera konfigurationen av inbäddningsslutpunkt

När du ska testa igen

För att upprätthålla prestandasynlighet är det en bra idé att köra baslinjebelastningstester kvartalsvis. Du bör också testa igen när du gör någon av följande ändringar:

  • Ändra frågemönster eller komplexitet
  • Uppdatera vektorsökningsindexet
  • Ändra filterkonfigurationer
  • Förvänta dig betydande trafikökningar
  • Distribuera nya funktioner eller optimeringar
  • Ändra från standard till lagringsoptimerade slutpunktstyper

Felsökning

Alla begäranden misslyckas med ~10 ms svarstid och svar på 240 byte

Detta anger att tjänstens principalkonto tar emot ett 401/403-svar. Kontrollera:

  1. Tjänstens huvudnamn har Can Query-behörigheter på vektorsökningsslutpunkten (inte bara indexet).
  2. Hemlighetsomfånget innehåller giltiga service_principal_client_id nycklar och service_principal_client_secret nycklar.
  3. OAuth-hemligheten har inte upphört att gälla.

Notebook-filen innehåller en anslutningskontroll som fångar upp detta innan du kör full belastningstestet.

Köra flera belastningstestjobb i samma kluster

Om du kör två belastningstestjobb samtidigt i samma kluster kan ett jobb få inaktuella OAuth-token eller uppleva CPU-konkurrens med det andra jobbets Locust-arbetare. För tillförlitliga resultat kör du belastningstestjobb en i taget på ett dedikerat kluster.

Diagram för komponenttidsscheman är tomma

Komponentens tidsschemadiagram (ann_time, embedding_gen_time, reranker_time) kräver att slutpunkten returneras debug_info i frågesvar. Om dessa diagram är tomma:

  • Kontrollera att du använder skriptet fast_vs_load_test_async_load.py (som parsar debug_info från svar) som locust_script_path.
  • Vissa slutpunktskonfigurationer kanske inte returnerar debug_info. Självhanterade inbäddningsindex returnerar ann_time vanligtvis och response_time men inte embedding_gen_time eller reranker_time.

Resultattabellen kan inte frågas från ett SQL-lager

Notebook-filen skriver resultat från klustrets Spark-session. Om ett SQL-lager visar 0 rader för en tabell som notebook-filen rapporterar som ifylld, kan problemet vara en fördröjning av synkroniseringen av Unity Catalog-metadata. Vänta några minuter och försök igen, eller fråga tabellen direkt från en notebook-fil som är kopplad till samma kluster.

Sammanfattning av metodtips

Testkonfiguration

  • Kör tester i minst 5 minuter vid hög belastning.

  • Använd OAuth-tjänstehuvuden för autentisering.

  • Skapa realistiska frågenyttolaster som matchar förväntade produktionsfrågor.

  • Testa med produktionsliknande filter och parametrar.

  • Inkludera en uppvärmningsperiod innan du mäter.

  • Testa på flera samtidighetsnivåer.

  • Spåra P95/P99-svarstider, inte bara medelvärden.

  • Testa både cachelagrade och ej cachelagrade prestanda.

    # Conservative approach: Size endpoint for UNCACHED performance
    uncached_results = run_load_test(diverse_queries, duration=600)
    endpoint_size = calculate_capacity(uncached_results, target_rps=500)
    
    # Then verify cached performance is even better
    cached_results = run_load_test(repetitive_queries, duration=300)
    print(f"Cached P95: {cached_results['p95']}ms (bonus performance)")
    

Frågeuppsättningsdesign

  • Matcha din testfrågas mångfald med verklig trafikdistribution (frekventa och sällsynta frågor).
  • Använd faktiska frågor från loggar (anonymiserade).
  • Inkludera olika frågekomplexiteter.
  • Testa både cachelagrade och ej åtkomliga scenarier och spåra resultaten separat.
  • Testa med förväntade filterkombinationer.
  • Använd samma parametrar som du kommer att använda i produktion. Om du till exempel använder hybridsökning i produktion kan du inkludera hybridsökningsfrågor. Använd en liknande num_results parameter som i produktion.
  • Använd inte frågor som aldrig inträffar i produktion.

Prestandaoptimering

Om svarstiderna är för höga kan du prova följande:

  1. Använda OAuth-tjänstens huvudnamn (inte PAT) – förbättring på 100 ms
  2. Minska num_results – Hämtningen av 100 resultat är långsammare än 10
  3. Optimera filter – Komplexa eller alltför restriktiva filter gör frågor långsammare
  4. Kontrollera inbäddningsslutpunkten – Kontrollera att den inte skalas till noll eller har tillräckligt med bandbredd

Om du når hastighetsgränserna kan du prova följande:

  1. Öka slutpunktskapaciteten – Skala upp slutpunkten
  2. Implementera begränsning av förfrågningshastighet eller sprid ut förfrågningar över tid på klientsidan.
  3. Använda anslutningspooler – Återanvända anslutningar
  4. Lägg till logik för återförsök – Använd exponentiell backoff (redan en del av Python SDK)

Ytterligare resurser