Batch-Lesevorgänge brauchen einen Ergebnisvertrag

Eine Schleife von Primärschlüssel-Abfragen durch eine einzelne ANY-Abfrage zu ersetzen, entfernt Roundtrips. Dabei kann sich aber die Form der Antwort ändern. Ein Aufrufer könnte [42, 7, 42, NULL, -1] anfordern und fünf Ergebnispositionen erwarten. SQL-Mengen-Semantik verspricht diese Ausrichtung nicht.

Eine Zeilenmenge ist keine Liste von Antworten

Mit WHERE id = ANY($1::bigint[]) trifft eine doppelte ID normalerweise nur einmal auf ihre Tabellenzeile. Eine fehlende ID liefert keine Zeile. Eine Eingabe NULL trifft keinen nicht-nullbaren Primärschlüssel, und die Ausgabe hat keine garantierte Eingabereihenfolge. ORDER BY id sortiert nach Schlüssel; die angeforderten Positionen werden trotzdem nicht reproduziert.

Wenn Verbraucher eine Menge benötigen, ist das in Ordnung. Wenn sie ein Ergebnis für jede Eingabe brauchen, machen Sie die Positionen zum Teil der Abfrage oder stellen Sie sie in der Anwendung wieder her.

Positionen in SQL explizit halten

Starten Sie die lokale Demo und führen Sie dies in ihrer psql-Sitzung aus:

WITH requested AS (
  SELECT key, position
  FROM unnest(ARRAY[42, 7, 42, NULL, -1]::bigint[])
       WITH ORDINALITY AS input(key, position)
)
SELECT requested.position,
       requested.key,
       CASE WHEN items.id IS NULL THEN NULL
            ELSE row_to_json(items)::text END AS row
FROM requested
LEFT JOIN public.items AS items ON items.id = requested.key
ORDER BY requested.position;

Die Ordinalitätsspalte unterscheidet beide Vorkommen von 42. Der Left Join behält alle fünf Positionen einschließlich der Null-Eingabe und jedes fehlenden Schlüssels. Für einen fehlenden Schlüssel ist row SQL NULL. Übergeben Sie im Anwendungscode das Array als Parameter, statt IDs an SQL anzuhängen. Das Node.js-Beispiel zeigt die clientseitige Ausrichtung.

Die API für vollständige Zeilen vergleichen

Bei einer angehängten Tabelle lautet der entsprechende explizite Cache-Aufruf:

SELECT local_cache.mget(
  'public.items'::regclass,
  ARRAY[42, 7, 42, NULL, -1]::bigint[]
) AS rows;

Er gibt text[] zurück, wobei Eingabereihenfolge und Duplikate erhalten bleiben. Fehlende Schlüssel und Null-Eingaben erzeugen ausgerichtete SQL-NULL-Elemente; jedes vorhandene Element ist eine serialisierte vollständige Zeile. Ein Cache-Fehltreffer oder Bypass liest PostgreSQL. Die API akzeptiert höchstens 1.024 Schlüssel pro Aufruf. Sie ersetzt keine Projektionen, Joins, Zeilensperren oder das Caching beliebiger Abfrageergebnisse.

Batches begrenzen und beobachtbar halten

Bei mehr als 1.024 Schlüsseln teilen Sie Anfragen explizit auf oder behalten Sie eine gewöhnliche SQL-Abfrage bei. Chunking über mehrere Anweisungen kann unterschiedliche READ COMMITTED-Snapshots sehen; wählen Sie die Transaktionssemantik bewusst. Größere Batches erhöhen außerdem Antwortgröße und Dekodierarbeit des Clients, daher beweist „weniger Abfragen“ allein keine schnellere Anfrage.

Für GraphQL muss eine DataLoader-Batch-Funktion eine Antwort pro Eingabeschlüssel in derselben Reihenfolge zurückgeben. Anfragebezogene Memoization und der gemeinsame Cache von PostgreSQL sind getrennte Ebenen; löschen Sie betroffene Loader-Einträge nach Mutationen. Siehe den vollständigen Batching-Leitfaden und vergleichen Sie Latenz, Payloads und Durchsatz mit dem Benchmark-Runner.