Een belastingstest configureren voor vectorzoekeindpunten

Deze pagina bevat richtlijnen, voorbeeldcode en een voorbeeldnotebook voor het testen van vectorzoekeindpunten. Loadtests helpen u inzicht te krijgen in de prestaties en productiegereedheid van een vectorzoekeindpunt voordat deze in productie wordt geïmplementeerd. Loadtesten kunnen u vertellen over:

  • Latentie op verschillende schaalniveaus
  • Doorvoerlimieten en knelpunten (aanvragen per seconde, uitsplitsing van latentie)
  • Foutpercentages onder langdurige belasting
  • Resourcegebruik en capaciteitsplanning

Zie Belastingstests voor het leveren van eindpunten voor meer informatie over belastingstests en gerelateerde concepten.

Requirements

Voordat u met deze stappen begint, moet u een geïmplementeerd eindpunt voor vectorzoekopdrachten en een service-principal met machtigingen voor canquery's voor het eindpunt hebben. Zie Stap 1: Authenticatie van de service-principal instellen.

Download en importeer een kopie van de volgende bestanden en voorbeeldnotebook naar uw Azure Databricks-werkruimte:

  • input.json. Dit is een voorbeeld van het input.json bestand dat de nettolading aangeeft die wordt verzonden door alle gelijktijdige verbindingen met uw eindpunt. U kunt indien nodig meerdere bestanden hebben. Als u het voorbeeldnotitieblok gebruikt, wordt dit bestand automatisch gegenereerd op basis van de opgegeven invoertabel.
  • fast_vs_load_test_async_load.py. Upload dit script naar uw werkruimte (bijvoorbeeld /Workspace/Users/<your-username>/fast_vs_load_test_async_load.py) en stel de notebook parameter locust_script_path in op het pad. Dit script verwerkt verificatie, levering van nettoladingen en het opsporen van fouten in de verzameling metrische gegevens.
  • Het volgende voorbeeldnotebook, waarmee de belastingstests worden uitgevoerd. Voor de beste prestaties voert u dit notebook uit op een cluster met één knooppunt met een groot aantal kernen (Locust-schaalt voor alle beschikbare CPU's). Hoog geheugen wordt aanbevolen voor query's met vooraf gegenereerde insluitingen.

Voorbeeldnotitieblok en quickstart

Gebruik het volgende voorbeeldnotitieblok om aan de slag te gaan. Het ondersteunt twee verkenningsmodi: een geleidelijke sweeping die specifieke gelijktijdigheidsniveaus test die u definieert, en een binaire zoekmodus die automatisch het maximale duurzame QPS in een paar stappen vindt. Alle parameters worden geconfigureerd met behulp van widgets, zodat het notebook interactief of als Een Databricks-taak kan worden uitgevoerd zonder codebewerkingen.

Notebook voor het testen van locust-belasting

Notebook krijgen

Framework voor belastingstests: Locust

Locust is een opensource-framework voor belastingstests waarmee u het volgende kunt doen:

  • Het aantal gelijktijdige clientverbindingen variëren
  • Beheer hoe snel verbindingen ontstaan
  • Eindpuntprestaties tijdens de test meten
  • Automatisch detecteren en gebruiken van alle beschikbare CPU-kernen

In het voorbeeldnotitieblok wordt de --processes -1 flag gebruikt om CPU-kernen automatisch te detecteren en volledig te benutten.

Als Locust een CPU-knelpunt ervaart, verschijnt er een bericht in de uitvoer.

Stap 1: Authenticatie voor service-principal instellen

Belangrijk

Gebruik voor productieachtige prestatietests altijd verificatie van de OAuth-service-principal. Service-principals bieden tot 100 ms snellere reactietijd en hogere aanvraagsnelheidslimieten in vergelijking met persoonlijke toegangstokens (PAW's).

Service-principal maken en configureren

  1. Maak een Databricks-service-principal. Zie Service-principals toevoegen aan uw account voor instructies.

  2. Machtigingen verlenen:

    • Navigeer naar de eindpuntpagina voor vectorzoekopdrachten.
    • Klik op Machtigingen.
    • Geef de service-principal Kan Query-machtigingen.
  3. OAuth-geheim maken.

    • Ga naar de pagina met details van de service-principal.
    • Klik op het tabblad Geheimen .
    • Klik op Geheim genereren.
    • Stel de levensduur in (raad 365 dagen aan voor langdurige tests).
    • Kopieer zowel de client-id als het geheim onmiddellijk.
  4. Sla referenties veilig op.

    • Maak een Databricks-geheimenscope. Zie Zelfstudie: Een Databricks-geheim maken en gebruiken voor instructies.
    • Zoals wordt weergegeven in het volgende codevoorbeeld, slaat u de client-id van de service-principal op als service_principal_client_id en slaat u het OAuth-geheim op als 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>")
    

Stap 2: Uw belastingstest configureren

Notebookconfiguratie

Configureer de notebookparameters met behulp van de widgets boven aan het notitieblok. Wanneer u het notebook uitvoert als een Databricks-taak, geeft u deze waarden door als taakparameters. Er zijn geen codebewerkingen nodig.

Kenmerk Description Aanbevolen waarde
endpoint_name Naam van uw vectorzoekeindpunt De naam van uw eindpunt
index_name Volledige indexnaam (catalog.schema.index) Uw indexnaam
test_table Brontabel naar voorbeeldquery's van (catalog.schema.table) De indexinvoertabel
query_column Tekstkolom die moet worden gebruikt voor beheerde insluitingen Laat staan als text of stel in als uw kolomnaam
embedding_column Kolom met vooraf samengestelde insluitingsvectoren. Alleen gebruikt voor zelfbeheerde insluitingen. Leeg laten voor beheerde insluitingen
sample_size Aantal queries dat moet worden gemonsterd voor de test. 1000
target_concurrencies Door komma's gescheiden lijst met gelijktijdige clientaantallen om te testen 5,10,20,50
step_duration_seconds Duur in seconden per gelijktijdigheidsniveau. Eén waarde is van toepassing op alle niveaus of geef één per niveau op als een door komma's gescheiden lijst. 300 (5 minuten)
secret_scope_name Naam van uw Databricks-geheim bereik Uw scopenaam
locust_script_path Pad van de werkruimte naar het fast_vs_load_test_async_load.py script /Workspace/Users/<your-username>/fast_vs_load_test_async_load.py
output_table (Optioneel) Delta-tabel voor het opslaan van resultaten in (catalog.schema.table). Automatisch gemaakt bij eerste uitvoering. catalog.schema.load_test_results
run_name Naam of opmerking om deze uitvoering te taggen voor latere analyse Een beschrijvend label
exploration_mode gradual doorloopt target_concurrencies in volgorde. binary_search bepaalt het breekpunt automatisch (zie Breekpuntverkenning). gradual
max_target_qps (binary_search alleen) Bovengrens voor de QPS-zoekopdracht 500
exploration_steps (binary_search alleen) Maximale aantal zoekiteraties voor binaire zoekactie 8
error_rate_threshold (binary_search alleen) Maximaal acceptabel foutpercentage (%) om een stap te tellen als een succes 1.0
num_results Aantal resultaten dat per query moet worden geretourneerd 10
columns_to_return Door komma's gescheiden lijst met kolommen die moeten worden geretourneerd in queryresultaten (bijvoorbeeld id,text). Laat leeg om alle kolommen weer te geven. Laat leeg voor standaard

Beheerde versus zelfbeheerde insluitingen

Het notebook ondersteunt zowel beheerde insluitingen (waarbij Databricks insluitingen genereert tijdens het uitvoeren van query's) als zelfbeheerde insluitingen (waarbij u vooraf gedefinieerde vectoren rechtstreeks doorgeeft). Configureer de juiste parameters op basis van uw indextype.

Indextype Parameter die moet worden ingesteld Ongedefinieerd laten
Beheerde insluitingen (Delta Sync-index met door Databricks beheerd insluitmodel) query_column — de naam van de tekstkolom die moet worden gebruikt als de query embedding_column (leeg laten)
Zelfbeheerde insluitingen (Delta Sync of Direct Vector Access-index met vooraf samengestelde vectoren) embedding_column — de kolom met vooraf samengestelde insluitingsvectoren query_column

Opmerking

Bij beheerde insluitingsindexen meet de loadtest de end-to-end latentie, inclusief de generatietijd van embeddings. Als het embedding-eindpunt naar nul wordt geschaald, zal de koudestart-overhead zichtbaar zijn in de eerste testrun. Zie Het knelpunt van het insluitmodel identificeren voor het isoleren van de insluitingslatentie van zoeklatentie.

Waarom 5-10 minuten?

Een minimale testduur van 5 minuten is kritiek.

  • Initiële query's kunnen met opstartoverhead te maken hebben.
  • Eindpunten hebben tijd nodig om stabiele prestaties te bereiken.
  • Automatisch schalen van het model dat eindpunten bedient (indien ingeschakeld) kost tijd om te activeren.
  • Korte tests missen het throttlinggedrag onder langdurige belasting.

In de volgende tabel ziet u de aanbevolen testduur, afhankelijk van uw testdoel.

Testtype Testduur Doelstellingen van test
Snelle rooktest 2-3 minuten Basisfunctionaliteit controleren
Prestatiebasislijn 5-10 minuten Betrouwbare metriek in een stationaire toestand
Stresstest 15-30 minuten Uitputting van middelen identificeren
Uithoudingsvermogen testen 1-4 uur Degradatie, latentiestabiliteit

Breekpuntverkenning (binaire zoekmodus)

Naast de geleidelijke sweep (exploration_mode=gradual), ondersteunt het notebook een automatische modus voor binaire zoekopdrachten die het maximale duurzame QPS zoekt zonder dat u handmatig de gelijktijdigheidsniveaus hoeft op te geven.

Hoe werkt het?

Stel exploration_mode=binary_search in en specificeer max_target_qps (bijvoorbeeld 500). Het notebook maakt gebruik van Little's Law (concurrency = QPS × avg_latency_sec) om elk QPS-doel te converteren naar een geschat gelijktijdigheidsniveau en voert vervolgens als volgt een binaire zoekopdracht uit:

  1. Begin bij max_target_qps / 2 (250 in het voorbeeld).
  2. Als het foutpercentage lager is dan error_rate_threshold (geslaagd), verhoog de ondergrenswaarde en probeer een hogere QPS (375, dan 500 enzovoort).
  3. Als de foutfrequentie de drempelwaarde (fout) overschrijdt, verlaagt u de bovengrens en probeert u het halverwege tussen het laatste succes en de laatste fout.
  4. Herhaal dit voor maximaal stappen exploration_steps (standaard 8) of totdat het zoekbereik wordt beperkt tot binnen 5% van max_target_qps.

In de volgende tabel ziet u hoe de zoekopdracht convergeert naar een hypothetisch eindpunt met een breekpunt rond 430 QPS:

Stap DoelQPS Foutpercentage Resultaat Nieuw bereik
1 250 0.1% SUCCES [250, 500]
2 375 0.3% SUCCES [375, 500]
3 437 4,5% MISLUKKING [375, 437]
4 406 0,8% SUCCES [406, 437]
5 421 2.1% MISLUKKING [406, 421]

Na 5-8 stappen convergeert de zoekopdracht op het breekpunt, in dit voorbeeld ongeveer 406-421 QPS, met veel minder tests dan een uitgebreide sweep.

Wanneer moet elke modus worden gebruikt

Mode Wanneer gebruiken
gradual U kent al het verwachte bedrijfsbereik en wilt de prestaties op specifieke gelijktijdigheidsniveaus karakteriseren.
binary_search U wilt snel de maximaal duurzame QPS vinden, zonder dat u de gelijktijdigheidsniveaus van tevoren kent.

Stap 3. Uw queryset ontwerpen

Indien mogelijk moet de queryset het verwachte productieverkeer zo dicht mogelijk weergeven. U moet proberen om met name de verwachte distributie van query's af te stemmen op het gebied van inhoud, complexiteit en diversiteit.

  • Gebruik realistische query's. Gebruik geen willekeurige tekst, zoals 'testquery 1234'.

  • Komt overeen met de verwachte distributie van productieverkeer. Als u 80% veelvoorkomende query's, 15% middelfrequentiequery's en vijf% onregelmatige query's verwacht, moet uw queryset die verdeling weerspiegelen.

  • Komt overeen met het type query dat u verwacht te zien in productie. Als u bijvoorbeeld verwacht dat productiequery's hybride zoeken of filters gebruiken, moet u deze ook gebruiken in uw queryset.

    Voorbeeldquery met behulp van filters:

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

    Voorbeeldquery met hybride zoekopdracht:

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

Diversiteit van query's en caching

Vectorzoekeindpunten cachen verschillende typen queryresultaten om de prestaties te verbeteren. Deze caching kan van invloed zijn op de resultaten van de belastingtest. Daarom is het belangrijk om aandacht te besteden aan de diversiteit van de queryset. Als u bijvoorbeeld herhaaldelijk dezelfde set query's verzendt, test u de cache, niet de werkelijke zoekprestaties.

Gebruik: Wanneer: Example
Identieke of weinig queries
  • Uw productieverkeer heeft een hoge herhaling van query's (bijvoorbeeld 'populaire producten')
  • U test specifiek de effectiviteit van de cache
  • Uw toepassing profiteert van caching (bijvoorbeeld dashboards met vaste query's)
  • U wilt de best-case scenario van caching-prestaties meten
Een productaanbevelingswidget die 'trending items' weergeeft: dezelfde query wordt duizenden keren per uur uitgevoerd.
Diverse queries
  • Uw productieverkeer heeft unieke gebruikersquery's (bijvoorbeeld zoekmachines of chatbots)
  • U wilt de slechtste prestaties zonder cache meten
  • U wilt de prestaties van indexscans testen, niet de cacheprestaties
  • Query's hebben een hoge kardinaliteit (miljoenen mogelijke variaties)
Een e-commerce zoekopdracht waarbij elke gebruiker verschillende productzoekopdrachten typt.

Zie Samenvatting van aanbevolen procedures voor aanvullende aanbevelingen.

Opties voor het maken van een queryset

De codetabbladen bevatten drie opties voor het maken van een diverse queryset. Er is geen one-size-fits-all. Kies degene die het beste voor u werkt.

  • (Aanbevolen) Willekeurige steekproeven uit de indexinvoertabel. Dit is een goed algemeen uitgangspunt.
  • Steekproeven uit productielogboeken. Dit is een goed begin als u productielogboeken hebt. Houd er rekening mee dat query's doorgaans na verloop van tijd veranderen, dus vernieuw de test die regelmatig is ingesteld om deze up-to-date te houden.
  • Synthetische queries genereren. Dit is handig als u geen productielogboeken hebt of als u complexe filters gebruikt.

Willekeurige steekproeven uit invoertabel

De volgende codevoorbeelden zijn willekeurige query's uit uw indexinvoertabel.

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")

Voorbeeld uit productielogboeken

De volgende codevoorbeelden zijn representatief afkomstig van productiequeries.

# 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)

Synthetische vragen

Als u nog geen productielogboeken hebt, kunt u synthetische diverse query's genereren.

# 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")

Stap 4. Uw nettolading testen

Voordat u de volledige belastingstest uitvoert, valideert u uw payload:

  1. Navigeer in de Databricks-werkruimte naar uw eindpunt voor vectorzoekopdrachten.
  2. Klik in de linkerzijbalk op Serveren.
  3. Selecteer uw eindpunt.
  4. Klik op GebruikenQuery.
  5. Plak uw input.json inhoud in het queryvak.
  6. Controleer of het eindpunt verwachte resultaten retourneert.

Dit zorgt ervoor dat uw belastingtest realistische query's meet, geen foutreacties.

Stap 5. De belastingstest uitvoeren

Connectiviteitscontrole en opwarmen

Voordat de belastingstest begint, voert het notebook twee installatiestappen uit:

  1. Connectiviteitscontrole: verzendt één testquery met behulp van de credentials van de service principal. Als het eindpunt een 401- of 403-fout retourneert, mislukt het notebook onmiddellijk met een duidelijke melding van PermissionError in plaats van een volledige belastingstest uit te voeren die uitsluitend foutgegevens produceert. Dit bespaart tijd wanneer referenties of machtigingen onjuist zijn geconfigureerd.

  2. Opwarmtest (1 minuut): voert een korte test met lage gelijktijdigheid uit waarmee eindpuntcaches worden opgewarmd en de end-to-end aanvraagstroom wordt gevalideerd. De opwarmresultaten worden niet gebruikt voor metrische prestatiegegevens. In de binaire zoekmodus wordt de opwarmlatentie ook gebruikt als de basislijn voor de gelijktijdigheidsraming van Little's Law.

Reeks hoofdbelastingstests

Het notebook voert een reeks tests uit met toenemende gelijktijdigheid van clients:

  • Start: Lage gelijktijdigheid (bijvoorbeeld 5 gelijktijdige clients)
  • Midden: Gemiddelde gelijktijdigheid (bijvoorbeeld 10, 20 of 50 clients)
  • Einde: Hoge gelijktijdigheid (bijvoorbeeld meer dan 100 gebruikers)

Elke test wordt uitgevoerd voor de duur die is geconfigureerd in step_duration_seconds (5-10 minuten aanbevolen).

Wat de laptop meet

Het notebook meet en rapporteert het volgende:

Metrische latentiegegevens:

  • P50 (mediaan): De helft van de query's is sneller dan dit.
  • P95: 95% van de query's zijn sneller dan deze waarde. Dit is een belangrijke SLA-metrische waarde.
  • P99: 99% query's zijn sneller dan dit.
  • Max: Slechtste latentie.

Metrische gegevens over doorvoer:

  • RPS (aanvragen per seconde): Succesvolle queries per seconde.
  • Totaal aantal query's: Aantal voltooide query's.
  • Slagingspercentage: Percentage van geslaagde queries.

Fouten:

  • Queryfouten per type
  • Uitzonderingsberichten
  • Aantal time-outs

Resultatenopslag

Als de output_table parameter is ingesteld, slaat het notebook één rij per gelijktijdigheidsniveau (of per binaire zoekstap) op in een Unity Catalog Delta-tabel. De tabel wordt automatisch gemaakt tijdens de eerste uitvoering en toegevoegd aan volgende uitvoeringen. Elke rij bevat run_name, exploration_modegelijktijdigheid, succes-/foutpercentages, latentie percentielen, RPS en binaire zoekspecifieke velden (bs_step, bs_target_qps, ). bs_outcome Hiermee kunt u uitvoeringen in de loop van de tijd vergelijken met behulp van SQL- of BI-hulpprogramma's.

Uitvoeren als een Databricks-taak

Alle notebookparameters worden gedefinieerd als dbutils.widgets, die rechtstreeks worden toegewezen aan databricks-taakparameters. Om de belastingtesten te plannen of te automatiseren:

  1. Maak een taak met het notitieblok als taak.
  2. Stel de widgetwaarden in als taakparameters. Er zijn geen codebewerkingen nodig.
  3. Koppel de taak aan een cluster met één knooppunt met veel CPU-kernen (Locust profiteert van parallelle werkrollen).
  4. Voer op aanvraag of volgens een schema voor terugkerende basislijntests uit.

Stap 6. Resultaten interpreteren

In de volgende tabel ziet u doelen voor goede prestaties:

Metrische gegevens Target Comment
P95-latentie < 500 ms De meeste query's zijn snel
P99-latentie < 1 s Redelijke prestaties voor langstaartzoekopdrachten
Slagingspercentage > 99,5% Laag storingspercentage
Latentie na verloop van tijd Stabiel Geen afname waargenomen tijdens de test
Queries per seconde Voldoet aan het doel Het eindpunt kan verwacht verkeer verwerken.

De volgende resultaten geven slechte prestaties aan:

  • P95 > 1s. Geeft aan dat query's te traag zijn voor realtime gebruik.
  • P99 > 3s. Latentie bij long tail-query's kan de gebruikerservaring schaden.
  • Slagingspercentage < 99%. Te veel fouten.
  • Toenemende latentie. Geeft de uitputting van resources of het geheugenlek aan.
  • Snelheidsbeperkingsfouten (429). Geeft aan dat een hogere eindpuntcapaciteit vereist is.

Compromis tussen RPS en latentie

De maximale RPS is niet het optimale punt voor productiedoorvoer. Latentie neemt niet-lineair toe wanneer u de maximale doorvoer nadert. Het gebruik van maximaal RPS resulteert vaak in 2-5x hogere latentie in vergelijking met 60-70% maximale capaciteit.

In het volgende voorbeeld ziet u hoe u de resultaten kunt analyseren om het optimale operationele punt te vinden.

  • De maximale RPS is 480 bij 150 gelijktijdige clients.
  • Het optimale bedieningspunt is 310 RPS bij 50 gelijktijdige clients (65% capaciteit).
  • De latentiestraf op max: P95 is 4,3x hoger (1,5s versus 350 ms)
  • In dit voorbeeld wordt aanbevolen om de capaciteit van het eindpunt aan te passen voor 480 RPS en te werken met ongeveer 310 RPS.
Concurrency P50 P95 P99 RPS Success Capaciteit
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% ← Ideale punt
100 250 ms 800 ms 1.2s 420 97,5% 90% ⚠bijna maximaal
150 450 ms 1,5s 2,5s 480 95.0% 100% ❌ Maximale RPS

Werken met de maximale RPS kan leiden tot de volgende problemen:

  • Latentieverslechtering. In het voorbeeld is P95 350 ms bij 65% capaciteit, maar is 1,5s bij 100% capaciteit.
  • Er is geen ruimte voor verkeerstoenames of pieken. Bij 100% capaciteit veroorzaakt een piek een time-out. Bij 65% capaciteit kan een piek van 50% verkeer zonder problemen worden afgehandeld.
  • Verhoogde foutpercentages. In het voorbeeld is het slagingspercentage 99,2% met een capaciteit van 65%, maar 95,0% - een foutpercentage van 5% - met een capaciteit van 100%.
  • Risico op uitputting van resources. Bij maximale belasting nemen wachtrijen toe, neemt de geheugendruk toe, beginnen verbindingsgroepen te verzadiging en neemt de hersteltijd na incidenten toe.

In de volgende tabel ziet u aanbevolen besturingspunten voor verschillende gebruiksvoorbeelden.

Gebruiksituatie Doelcapaciteit Motivatie
Latentiegevoelig (zoeken, chatten) 50-60% van het maximum Geef prioriteit aan lage P95/P99-latentie
Evenwichtig (aanbevelingen) 60-70% van maximaal Goede balans tussen kosten en latentie
Geoptimaliseerd voor kosten (batchtaken) 70-80% van maximaal Acceptabele hogere latentie
Niet aanbevolen > 85% van maximaal Latentiepieken, geen burstcapaciteit

Helperfuncties voor het berekenen van de grootte van het besturingspunt en het eindpunt

Het optimale punt vinden

De volgende code plot QPS versus P95 latentie. Zoek in de plot naar het punt waar de curve scherp omhoog begint te buigen. Dit is het optimale bedieningspunt.

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()

Grootte-aanbevelingsformule

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

Het knelpunt van het insluitmodel identificeren

Als in uw index beheerde insluitingen worden gebruikt, legt het notebook voor de belastingtest de timing per onderdeel vast via de debug_level=1 parameter voor elke query. De resultatentabel bevat:

  • ann_time — tijd besteed aan het zoeken naar dichtstbijzijnde buren
  • embedding_gen_time — tijd besteed aan het genereren van query-embeddings op het modelserve-eindpunt
  • reranker_time — de tijd besteed aan het herordenen (indien ingeschakeld)
  • response_time — totale end-to-end reactietijd

Als embedding_gen_time consistent groot is ten opzichte van ann_time, is het embedding-eindpunt het knelpunt, niet het eindpunt voor vectorzoekopdrachten. Veelvoorkomende oorzaken:

  • Voor het embeddingmodel voor het eindpunt is schaal naar nul ingeschakeld. Schakel dit uit voor het testen van productiebelastingen. Zie Het vermijden van afschalen naar nul voor productie.
  • Het embedding-eindpunt heeft niet genoeg voorziene gelijktijdigheid voor de queryfrequentie die u test.
  • Het eindpunt van het insluitmodel wordt gedeeld met andere workloads. Gebruik een toegewezen eindpunt voor het testen van belasting.

Aanbeveling

Als u vectorzoekprestaties wilt isoleren van de prestaties van het insluiten van modellen, schakelt u over naar zelfbeheerde insluitingen voor belastingstests. Geef vooraf gecomputeerde vectoren door in de EMBEDDING_COLUMN parameter in plaats van tekstquery's. Hierdoor wordt de insluitingslatentie van de meting volledig verwijderd.

Stap 7: Uw eindpunt afmeten

De aanbeveling van het notitieblok gebruiken

Nadat de resultaten zijn geanalyseerd, vraagt het notebook u het volgende te doen:

  1. Selecteer de rij die het beste voldoet aan uw latentievereisten.
  2. Voer de gewenste RPS van uw toepassing in.

Het notebook geeft vervolgens een aanbevolen eindpuntgrootte weer. Hiermee wordt de vereiste capaciteit berekend op basis van het volgende:

  • Uw doel-RPS
  • Waargenomen latentie op verschillende gelijktijdigheidsniveaus
  • Drempelwaarden voor slagingspercentage
  • Veiligheidsmarge (doorgaans 2x verwachte piekbelasting)

Overwegingen met betrekking tot schaalvergroting

Standaardeindpunten:

  • Automatisch omhoog schalen ter ondersteuning van de indexgrootte
  • Handmatig omhoog schalen ter ondersteuning van doorvoer
  • Automatisch omlaag schalen wanneer indexen worden verwijderd
  • Handmatig omlaag schalen om de capaciteit te verminderen

Eindpunten die zijn geoptimaliseerd voor opslag:

  • Automatisch omhoog schalen ter ondersteuning van de indexgrootte
  • Automatisch omlaag schalen wanneer indexen worden verwijderd

Stap 8: Definitieve configuratie valideren

Na het bijwerken van uw eindpuntconfiguratie:

  1. Wacht tot het eindpunt gereed is. Dit kan enkele minuten duren.
  2. Voer de laatste validatietest uit in het notebook.
  3. Controleer of de prestaties voldoen aan uw vereisten:
    • RPS ≥ doeldoorvoer
    • P95-latentie voldoet aan SLA.
    • Slagingspercentage > 99,5%
    • Geen aanhoudende fouten

Als de validatie mislukt, probeert u het volgende:

  • Eindpuntcapaciteit verhogen
  • Querycomplexiteit optimaliseren
  • Filterprestaties controleren
  • De configuratie van het insluiten van eindpunten controleren

Wanneer moet u de test opnieuw uitvoeren

Om de zichtbaarheid van de prestaties te behouden, is het een goed idee om driemaandelijkse basislijnbelastingstests uit te voeren. U moet ook opnieuw testen wanneer u een van de volgende wijzigingen aanbrengt:

  • De querypatronen of de complexiteit wijzigen
  • De vectorzoekindex bijwerken
  • Filterconfiguraties wijzigen
  • Verwacht aanzienlijke toename van verkeer
  • Nieuwe functies of optimalisaties implementeren
  • Overstappen van standaard naar eindpunttypen die zijn geoptimaliseerd voor opslag

Troubleshooting

Alle aanvragen mislukken met latentie van ~10 ms en antwoorden van 240 bytes

Dit geeft aan dat de service-principal een 401/403-antwoord ontvangt. Controleren:

  1. De service-principal heeft kan querymachtigingen voor het eindpunt voor vectorzoekopdrachten (niet alleen de index).
  2. Het geheime bereik bevat geldige service_principal_client_id en service_principal_client_secret sleutels.
  3. Het OAuth-geheim is niet verlopen.

Het notebook bevat een connectiviteitscontrole die dit detecteert voordat de volledige loadtest wordt uitgevoerd.

Meerdere belastingstesttaken uitvoeren op hetzelfde cluster

Als u twee loadtesttaken tegelijk uitvoert op hetzelfde cluster, kan één taak verouderde OAuth-tokens krijgen of CPU-conflicten ondervinden met de Locust-werkers van de andere taak. Voor betrouwbare resultaten voert u taaktesttaken één voor één uit op een toegewezen cluster.

Tijdsgrafieken voor onderdelen zijn leeg

De eindpunt moet ann_time retourneren in query-antwoorden voor de tijdsgrafieken van onderdelen (embedding_gen_time, reranker_time, debug_info). Als deze grafieken leeg zijn:

  • Controleer of u het fast_vs_load_test_async_load.py script gebruikt (dat debug_info uit antwoorden parseert) als de locust_script_path.
  • Sommige eindpuntconfiguraties retourneren mogelijk niet debug_info. Zelfbeheerde indexen voor insluiten retourneren meestal ann_time en response_time, maar niet embedding_gen_time of reranker_time.

Resultatentabel die niet kan worden opgevraagd vanuit een SQL-warehouse

Het notebook registreert de resultaten van de Spark-sessie van het cluster. Als in een SQL Warehouse 0 rijen worden weergegeven voor een tabel die het notebook rapporteert als gevuld, kan het probleem een vertraging in de synchronisatie van Unity Catalog metagegevens zijn. Wacht enkele minuten en probeer het opnieuw of voer een query uit op de tabel vanuit een notebook dat is gekoppeld aan hetzelfde cluster.

Samenvatting van aanbevolen procedures

Testconfiguratie

  • Voer tests uit gedurende ten minste 5 minuten bij piekbelasting.

  • Gebruik OAuth-service-principals voor verificatie.

  • Maak realistische querypayloads zodat ze overeenkomen met verwachte productievragen.

  • Test met productieachtige filters en parameters.

  • Neem een opwarmperiode op voordat u meet.

  • Test op meerdere gelijktijdigheidsniveaus.

  • Houd P95/P99-latenties bij, niet alleen gemiddelden.

  • Test zowel de gecachete prestaties als de niet-gecachete prestaties.

    # 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)")
    

Ontwerp van queryset

  • Koppel uw testquerydiversiteit aan de werkelijke verkeersdistributie (frequente en zeldzame query's).
  • Gebruik werkelijke query's uit logboeken (geanonimiseerd).
  • Neem verschillende complexiteitsniveaus van queries op.
  • Test zowel scenario's met cache als niet-cache en volg de resultaten afzonderlijk.
  • Test met verwachte filtercombinaties.
  • Gebruik dezelfde parameters die u in productie gaat gebruiken. Als u bijvoorbeeld hybride zoekfuncties in een productieomgeving gebruikt, neemt u hybride zoekquery's op. Gebruik een vergelijkbare num_results parameter als in productie.
  • Gebruik geen query's die nooit in productie worden uitgevoerd.

Optimalisatie van prestaties

Als de latentie te hoog is, probeert u het volgende:

  1. Gebruik OAuth-service-principals (geen persoonlijke toegangs tokens) - een verbetering van 100 ms
  2. Reduce num_results - Het ophalen van 100 resultaten is langzamer dan 10
  3. Filters optimaliseren - Complexe of te beperkende filters vertragen query's
  4. Controleer het eindpunt voor insluiten: zorg ervoor dat het niet naar nul wordt geschaald of dat het voldoende bandbreedte heeft

Als u frequentielimieten bereikt, probeert u het volgende:

  1. Capaciteit van eindpunt verhogen - Uw eindpunt omhoog schalen
  2. Frequentiebeperking of verspreiding van query's aan de clientzijde op tijd implementeren
  3. Groepsgewijze verbindingen gebruiken - Verbindingen opnieuw gebruiken
  4. Logica voor opnieuw proberen toevoegen - Exponentieel uitstel gebruiken (al een deel van de Python SDK)

Aanvullende bronnen