Suchindexe

Auf dieser Seite wird beschrieben, wie Sie Suchindexe hinzufügen und verwenden. Die Volltextsuche wird für Einträge im Suchindex ausgeführt.

Suchindexe verwenden

Sie können einen Suchindex für alle Spalten erstellen, die Sie für Volltextsuchen verfügbar machen möchten. Verwenden Sie zum Erstellen eines Suchindex die DDL-Anweisung CREATE SEARCH INDEX. Verwenden Sie zum Aktualisieren eines Index die DDL-Anweisung ALTER SEARCH INDEX. Spanner erstellt und verwaltet den Suchindex automatisch. Dazu gehört auch das Hinzufügen und Aktualisieren von Daten im Suchindex, sobald sie sich in der Datenbank ändern.

Partitionen des Suchindex

Ein Suchindex kann partitioniert oder nicht partitioniert sein, je nachdem, welche Art von Abfragen Sie beschleunigen möchten.

  • Ein Beispiel dafür, wann ein partitionierter Index die beste Wahl ist, ist, wenn die Anwendung ein E-Mail-Postfach abfragt. Jede Abfrage ist auf ein bestimmtes Postfach beschränkt.

  • Ein Beispiel für eine unpartitionierte Abfrage ist eine Abfrage über alle Produktkategorien in einem Produktkatalog.

Anwendungsfälle für den Suchindex

Neben der Volltextsuche unterstützen Spanner-Suchindexe Folgendes:

  • JSON-Suchen, eine effiziente Methode zum Indexieren und Abfragen von JSON- und JSONB-Dokumenten.
  • Teilzeichenfolgensuchen: Bei diesem Abfragetyp wird nach einer kürzeren Zeichenfolge (der Teilzeichenfolge) in einem größeren Textkörper gesucht.
  • Kombination von Bedingungen für eine beliebige Teilmenge indexierter Daten, einschließlich genauer Übereinstimmungen und numerischer Daten, in einem einzigen Indexscan.

Weitere Informationen zu Anwendungsfällen finden Sie unter Suchindexe im Vergleich zu sekundären Indexen.

Beispiel für einen Suchindex

Angenommen, es gibt eine Tabelle, in der Informationen zu Musikalben gespeichert sind, um die Funktionen von Suchindexen zu veranschaulichen:

GoogleSQL

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  AlbumTitle STRING(MAX)
) PRIMARY KEY(AlbumId);

PostgreSQL

CREATE TABLE albums (
  albumid character varying NOT NULL,
  albumtitle character varying,
PRIMARY KEY(albumid));

Spanner bietet mehrere Tokenisierungsfunktionen, mit denen Tokens erstellt werden. Wenn Sie die vorherige Tabelle so ändern möchten, dass Nutzer eine Volltextsuche nach Albumtiteln ausführen können, verwenden Sie die Funktion TOKENIZE_FULLTEXT, um Tokens aus Albumtiteln zu erstellen. Erstellen Sie dann eine Spalte, die den Datentyp TOKENLIST verwendet, um die Tokenisierungsausgabe von TOKENIZE_FULLTEXT zu speichern. In diesem Beispiel erstellen wir die Spalte AlbumTitle_Tokens.

GoogleSQL

ALTER TABLE Albums
  ADD COLUMN AlbumTitle_Tokens TOKENLIST
  AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN;

PostgreSQL

ALTER TABLE albums
  ADD COLUMN albumtitle_tokens spanner.tokenlist
    GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN;

Im folgenden Beispiel wird die DDL CREATE SEARCH INDEX verwendet, um einen Suchindex (AlbumsIndex) für die AlbumTitle-Tokens (AlbumTitle_Tokens) zu erstellen:

GoogleSQL

CREATE SEARCH INDEX AlbumsIndex
  ON Albums(AlbumTitle_Tokens);

PostgreSQL

In diesem Beispiel wird CREATE SEARCH INDEX verwendet.

CREATE SEARCH INDEX albumsindex ON albums(albumtitle_tokens);

Nachdem Sie den Suchindex hinzugefügt haben, können Sie mit SQL-Abfragen nach Alben suchen, die den Suchkriterien entsprechen. Beispiel:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")

PostgreSQL

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')

Suchindex für ein benanntes Schema erstellen und abfragen

Sie können einen Suchindex für ein benanntes Schema erstellen, wie in den folgenden Beispielen gezeigt.

GoogleSQL

CREATE SCHEMA AlbumSchema;
CREATE TABLE AlbumSchema.Albums (
  AlbumId STRING(MAX) NOT NULL,
  AlbumTitle STRING(MAX),
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) STORED HIDDEN,
) PRIMARY KEY(AlbumId);

CREATE SEARCH INDEX AlbumSchema.AlbumsIndex ON AlbumSchema.Albums(AlbumTitle_Tokens);

PostgreSQL

In PostgreSQL können Sie keine vollständig qualifizierten Namen verwenden, um Indexe für benannte Schemas zu erstellen.

CREATE SCHEMA AlbumSchema;
CREATE TABLE AlbumSchema.albums (
  albumid character varying NOT NULL,
  albumtitle character varying,
  albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) STORED HIDDEN,
  PRIMARY KEY(albumid)
);
CREATE SEARCH INDEX albumsindex ON AlbumSchema.albums(albumtitle_tokens);

Die folgenden Beispiele zeigen, wie der Suchindex im benannten Schema abgefragt wird:

GoogleSQL

SELECT AlbumId
FROM AlbumSchema.Albums
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")

Im folgenden Beispiel wird ein Abfragehinweis verwendet, um den Abfrageoptimierer anzuweisen, den Index mit dem Namen AlbumsIndex beim Ausführen der Abfrage zu verwenden.

SELECT AlbumId
FROM AlbumSchema.Albums@{FORCE_INDEX="AlbumSchema.AlbumsIndex"}
WHERE SEARCH(AlbumTitle_Tokens, "fifth symphony")

PostgreSQL

In PostgreSQL können Sie keine vollständig qualifizierten Namen verwenden, um Indexe für benannte Schemas zu erstellen.

SELECT albumid
FROM AlbumSchema.albums
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')

Im folgenden Beispiel wird ein Abfragehinweis verwendet, um den Abfrageoptimierer anzuweisen, den Index mit dem Namen albumsindex beim Ausführen der Abfrage zu verwenden.

SELECT albumid
FROM AlbumSchema.albums /*@ FORCE_INDEX = albumsindex */
WHERE spanner.search(albumtitle_tokens, 'fifth symphony')

Datenkonsistenz

Wenn ein Index erstellt wird, verwendet Spanner automatisierte Prozesse, um die Daten zu füllen und die Konsistenz zu gewährleisten. Wenn Schreibvorgänge festgeschrieben werden, werden die Indexe in derselben Transaktion aktualisiert. Cloud Spanner führt automatisch Datenkonsistenzprüfungen durch.

Schemadefinitionen für Suchindexe

Suchindexe werden für eine oder mehrere TOKENLIST-Spalten einer Tabelle definiert. Suchindexe haben die folgenden Komponenten:

  • Basistabelle: Die Spanner-Tabelle, die indexiert werden muss.
  • TOKENLIST-Spalte: Eine Sammlung von Spalten, die die Tokens definieren, die indexiert werden müssen. Die Reihenfolge dieser Spalten ist nicht wichtig.

In der folgenden Anweisung ist die Basistabelle beispielsweise „Albums“. TOKENLIST-Spalten werden für AlbumTitle (AlbumTitle_Tokens) und Rating (Rating_Tokens) erstellt.

GoogleSQL

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  SingerId INT64 NOT NULL,
  ReleaseTimestamp INT64 NOT NULL,
  AlbumTitle STRING(MAX),
  Rating FLOAT64,
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
  Rating_Tokens TOKENLIST AS (TOKENIZE_NUMBER(Rating)) HIDDEN
) PRIMARY KEY(AlbumId);

PostgreSQL

CREATE TABLE albums (
  albumid character varying NOT NULL,
  singerid bigint NOT NULL,
  releasetimestamp bigint NOT NULL,
  albumtitle character varying,
  rating double precision,
  albumtitle_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(albumtitle)) VIRTUAL HIDDEN,
  rating_tokens spanner.tokenlist GENERATED ALWAYS AS (spanner.tokenize_fulltext(rating)) VIRTUAL HIDDEN,
PRIMARY KEY(AlbumId));

Verwenden Sie die folgende CREATE SEARCH INDEX-Anweisung, um einen Suchindex mit den Tokens für AlbumTitle und Rating zu erstellen:

GoogleSQL

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens, Rating_Tokens)
PARTITION BY SingerId
ORDER BY ReleaseTimestamp DESC

PostgreSQL

CREATE SEARCH INDEX albumsindex
ON albums(albumtitle_tokens, rating_tokens)
PARTITION BY singerid
ORDER BY releasetimestamp DESC

Für Suchindexe gibt es die folgenden Optionen:

  • Partitionen: Eine optionale Gruppe von Spalten, die den Suchindex unterteilen. Das Abfragen eines partitionierten Index ist oft deutlich effizienter als das Abfragen eines nicht partitionierten Index. Weitere Informationen finden Sie unter Suchindexe partitionieren.
  • Spalte für Sortierreihenfolge: Eine optionale INT64-Spalte, die die Reihenfolge des Abrufs aus dem Suchindex festlegt. Weitere Informationen finden Sie unter Sortierreihenfolge für Suchindex.
  • Verschachtelung: Wie sekundäre Indexe können Sie auch Suchindexe verschachteln. Verschachtelte Suchindexe verbrauchen weniger Ressourcen beim Schreiben und Verknüpfen mit der Basistabelle. Weitere Informationen finden Sie unter Verschachtelte Suchindexe.
  • Optionsklausel: Eine Liste von Schlüssel/Wert-Paaren, die die Standardeinstellungen des Suchindex überschreiben.

Internes Layout von Suchindexen

Ein wichtiges Element der internen Darstellung von Suchindexen ist eine docid, die als speichereffiziente Darstellung des Primärschlüssels der Basistabelle dient, der beliebig lang sein kann. Außerdem wird damit die Reihenfolge für das interne Datenlayout gemäß den vom Nutzer bereitgestellten ORDER BY-Spalten der CREATE SEARCH INDEX-Anweisung erstellt. Sie wird als eine oder zwei 64-Bit-Ganzzahlen dargestellt.

Suchindexe werden intern als zweistufige Zuordnung implementiert:

  1. Tokens zu docids
  2. Docids zu Primärschlüsseln der Basistabelle

Dieses Schema führt zu erheblichen Speichereinsparungen, da Spanner nicht den vollständigen Primärschlüssel der Basistabelle für jedes <token, document>-Paar speichern muss.

Es gibt zwei Arten von physischen Indexen, die die beiden Zuordnungsebenen implementieren:

  1. Ein sekundärer Index, der Partitionsschlüssel und eine docid dem Primärschlüssel der Basistabelle zuordnet. Im Beispiel im vorherigen Abschnitt wird {SingerId, ReleaseTimestamp, uid} zu {AlbumId} zugeordnet. Im sekundären Index werden auch alle Spalten gespeichert, die in der STORING-Klausel von CREATE SEARCH INDEX angegeben sind.
  2. Ein Tokenindex, der Tokens Dokument-IDs zuordnet, ähnlich wie invertierte Indexe in der Literatur zum Informationsabruf. Spanner verwaltet für jede TOKENLIST des Suchindex einen separaten Tokenindex. Logisch gesehen enthalten Token-Indizes Listen von docids für jedes Token innerhalb jeder Partition (beim Informationsabruf als Postings-Listen bezeichnet). Die Listen sind nach Tokens sortiert, um einen schnellen Abruf zu ermöglichen. Innerhalb der Listen wird die docid für die Sortierung verwendet. Einzelne Token-Indexe sind ein Implementierungsdetail, das nicht über Spanner APIs verfügbar gemacht wird.

Spanner unterstützt die folgenden Optionen für „docid“.

Google-Suchindex Dokument-ID Verhalten
Die ORDER BY-Klausel wird für den Suchindex weggelassen. {uid} Spanner fügt einen ausgeblendeten eindeutigen Wert (UID) hinzu, um jede Zeile zu identifizieren.
ORDER BY column {column, uid} Spanner fügt die UID-Spalte als Tiebreaker zwischen Zeilen mit denselben column-Werten innerhalb einer Partition hinzu.

Verwendungshinweise:

  • Die interne UID-Spalte wird nicht über die Spanner API bereitgestellt.
  • In Indexen, in denen die UID nicht hinzugefügt wird, schlagen Transaktionen fehl, die eine Zeile mit einer bereits vorhandenen (Partition, Sortierreihenfolge) hinzufügen.

Beispiel:

AlbumId SingerId ReleaseTimestamp SongTitle
a1 1 997 Schöne Tage
a2 1 743 Schöne Augen

Wenn die Vorsortierungsspalte in aufsteigender Reihenfolge sortiert ist, wird der Inhalt des Tokenindex, der nach SingerId partitioniert ist, so partitioniert:

SingerId _token ReleaseTimestamp uid
1 schön 743 uid1
1 schön 997 uid2
1 Tage 743 uid1
1 Augen 997 uid2

Sharding des Suchindex

Wenn Spanner eine Tabelle aufteilt, werden die Suchindexdaten so verteilt, dass sich alle Tokens in einer bestimmten Zeile der Basistabelle in derselben Aufteilung befinden. Mit anderen Worten: Der Suchindex ist nach Dokumenten fragmentiert. Diese Sharding-Strategie hat erhebliche Auswirkungen auf die Leistung:

  1. Die Anzahl der Server, mit denen jede Transaktion kommuniziert, bleibt konstant, unabhängig von der Anzahl der Tokens oder der Anzahl der indexierten TOKENLIST-Spalten.
  2. Suchanfragen mit mehreren bedingten Ausdrücken werden unabhängig voneinander für jeden Split ausgeführt. So werden Leistungseinbußen vermieden, die mit einem verteilten Join verbunden sind.

Suchindexe haben zwei Verteilungsmodi:

  • Einheitliches Sharding (Standard). Beim einheitlichen Sharding werden indexierte Daten für jede Zeile der Basistabelle zufällig einem Index-Split einer Partition zugewiesen.
  • Sortierreihenfolge-Fragmentierung. Beim Sortierreihenfolge-Sharding werden die Daten für jede Zeile der Basistabelle basierend auf den ORDER BY-Spalten (d. h. den Vorsortierspalten) einem Index-Split einer Partition zugewiesen. Bei einer absteigenden Sortierreihenfolge werden beispielsweise alle Zeilen mit den größten Sortierreihenfolgewerten im ersten Index-Split einer Partition und die nächstgrößere Gruppe von Sortierreihenfolgewerten im nächsten Split angezeigt.

Diese Fragmentierungsmodi bieten einen Kompromiss zwischen Hotspot-Risiken und Abfragekosten:

  • Einheitlich fragmentierte Suchindexe werden empfohlen, wenn Lese- oder Schreibmuster im Suchindex zu Hotspots führen könnten. Durch einheitliches Sharding werden Hotspots minimiert, da die Lese- und Schreiblast gleichmäßig auf die Splits verteilt wird. Dies kann jedoch die Ressourcennutzung während der Abfrageausführung erhöhen. In einheitlich fragmentierten Suchindexen müssen Abfragen aufgrund der zufällig verteilten Daten alle Splits innerhalb einer Partition lesen. Beim Zugriff auf gleichmäßig fragmentierte Indexe liest Spanner alle Splits parallel, um die Gesamtlatenz der Abfrage zu reduzieren.
  • Nach Sortierreihenfolge fragmentierte Suchindexe sind vorzuziehen, wenn Lese- oder Schreibmuster wahrscheinlich keine Hotspots verursachen. Dieser Ansatz kann die Kosten für Abfragen senken, deren ORDER BY mit dem ORDER BY des Index übereinstimmt und die einen relativ niedrigen LIMIT angeben. Bei der Ausführung solcher Abfragen liest Spanner ab den ersten Splits einer Partition inkrementell. Die Abfrage kann abgeschlossen werden, ohne dass alle Splits gelesen werden müssen, wenn LIMIT frühzeitig erfüllt werden kann.
  • Der Fragmentierungsmodus eines Suchindex wird mit der OPTIONS-Klausel konfiguriert.

GoogleSQL

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens, Rating_Tokens)
PARTITION BY SingerId
ORDER BY ReleaseTimestamp DESC
OPTIONS (sort_order_sharding = true);

PostgreSQL

Der Fragmentierungsmodus eines Suchindex wird mit der WITH-Anweisung konfiguriert.

CREATE SEARCH INDEX albumsindex
ON albums(albumtitle_tokens, rating_tokens)
PARTITION BY singerid
ORDER BY releasetimestamp DESC
WITH (sort_order_sharding = true);

Wenn sort_order_sharding=false festgelegt oder nicht angegeben ist, wird der Suchindex mit einheitlichem Sharding erstellt.

Verschachtelte Suchindexe

Wie sekundäre Indexe können Sie Suchindexe in einer übergeordneten Tabelle der Basistabelle verschachteln. Der Hauptgrund für die Verwendung von verschachtelten Suchindexen besteht darin, Basistabellendaten mit Indexdaten für kleine Partitionen zusammenzustellen. Diese opportunistische Zusammenstellung bietet folgende Vorteile:

  • Für Schreibvorgänge ist kein Two-Phase-Commit erforderlich.
  • Back-Joins des Suchindex mit der Basistabelle werden nicht verteilt.

Für verschachtelte Suchindexe gelten die folgenden Einschränkungen:

  1. Nur nach Sortierreihenfolge fragmentierte Indexe können verschachtelt werden.
  2. Suchindexe können nur in Tabellen auf oberster Ebene verschachtelt werden (nicht in untergeordneten Tabellen).
  3. Wie bei verschachtelten Tabellen und sekundären Indexen muss der Schlüssel der übergeordneten Tabelle ein Präfix der PARTITION BY-Spalten im verschachtelten Suchindex sein.

Verschachtelten Suchindex definieren

Im folgenden Beispiel wird gezeigt, wie ein verschachtelter Suchindex definiert wird:

GoogleSQL

CREATE TABLE Singers (
  SingerId INT64 NOT NULL
) PRIMARY KEY(SingerId);

CREATE TABLE Albums (
  SingerId INT64 NOT NULL,
  AlbumId STRING(MAX) NOT NULL,
  AlbumTitle STRING(MAX),
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN
) PRIMARY KEY(SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens)
PARTITION BY SingerId,
INTERLEAVE IN Singers
OPTIONS (sort_order_sharding = true);

PostgreSQL

CREATE TABLE singers(
  singerid bigint NOT NULL
PRIMARY KEY(singerid));

CREATE TABLE albums(
  singerid bigint NOT NULL,
  albumid character varying NOT NULL,
  albumtitle character varying,
  albumtitle_tokens spanner.tokenlist
  GENERATED ALWAYS
AS (
  spanner.tokenize_fulltext(albumtitle)
) VIRTUAL HIDDEN,
  PRIMARY KEY(singerid, albumid)),
INTERLEAVE IN PARENT singers ON DELETE CASCADE;

CREATE
  SEARCH INDEX albumsindex
ON
  albums(albumtitle_tokens)
  PARTITION BY singerid INTERLEAVE IN singers WITH(sort_order_sharding = true);

Sortierreihenfolge für Suchindex

Die Anforderungen für die Definition der Sortierreihenfolge des Suchindex unterscheiden sich von denen für sekundäre Indexe.

Betrachten Sie beispielsweise die folgende Tabelle:

GoogleSQL

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  ReleaseTimestamp INT64 NOT NULL,
  AlbumName STRING(MAX),
  AlbumName_Token TOKENLIST AS (TOKEN(AlbumName)) HIDDEN
) PRIMARY KEY(AlbumId);

PostgreSQL

CREATE TABLE albums (
  albumid character varying NOT NULL,
  releasetimestamp bigint NOT NULL,
  albumname character varying,
  albumname_token spanner.tokenlist
      GENERATED ALWAYS AS(spanner.token(albumname)) VIRTUAL HIDDEN,
PRIMARY KEY(albumid));

Die Anwendung könnte einen sekundären Index definieren, um Informationen mithilfe von AlbumName, sortiert nach ReleaseTimestamp, zu suchen:

CREATE INDEX AlbumsSecondaryIndex ON Albums(AlbumName, ReleaseTimestamp DESC);

Der entsprechende Suchindex sieht so aus (hier wird die Tokenisierung mit genauer Übereinstimmung verwendet, da sekundäre Indexe keine Volltextsuchen unterstützen):

CREATE SEARCH INDEX AlbumsSearchIndex
ON Albums(AlbumName_Token)
ORDER BY ReleaseTimestamp DESC;

Die Sortierreihenfolge des Suchindex muss die folgenden Anforderungen erfüllen:

  1. Verwenden Sie nur INT64-Spalten für die Sortierreihenfolge eines Suchindex. Spalten mit beliebigen Größen verbrauchen zu viele Ressourcen im Suchindex, da Spanner neben jedem Token eine docid speichern muss. Insbesondere kann die Spalte für die Sortierreihenfolge nicht den Typ TIMESTAMP verwenden, da TIMESTAMP eine Nanosekunden-Genauigkeit verwendet, die nicht in eine 64-Bit-Ganzzahl passt.
  2. Spalten für die Sortierreihenfolge dürfen nicht NULL sein. Es gibt zwei Möglichkeiten, diese Anforderung zu erfüllen:

    1. Deklarieren Sie die Spalte für die Sortierreihenfolge als NOT NULL.
    2. Konfigurieren Sie den Index so, dass NULL-Werte ausgeschlossen werden.

Ein Zeitstempel wird häufig verwendet, um die Sortierreihenfolge festzulegen. Eine gängige Praxis ist die Verwendung von Mikrosekunden seit der Unix-Epoche für solche Zeitstempel.

Anwendungen rufen in der Regel zuerst die neuesten Daten ab. Dazu verwenden sie einen Suchindex, der in absteigender Reihenfolge sortiert ist.

NULL-gefilterte Suchindexe

Suchindexe können die Syntax WHERE column_name IS NOT NULL verwenden, um Zeilen der Basistabelle auszuschließen. Die NULL-Filterung kann auf Partitionierungsschlüssel, Spalten für die Sortierreihenfolge und gespeicherte Spalten angewendet werden. NULL-Filterung für gespeicherte Array-Spalten ist nicht zulässig.

Beispiel

GoogleSQL

CREATE SEARCH INDEX AlbumsIndex
ON Albums(AlbumTitle_Tokens)
STORING (Genre)
WHERE Genre IS NOT NULL

PostgreSQL

CREATE SEARCH INDEX albumsindex
ON albums(albumtitle_tokens)
INCLUDE (genre)
WHERE genre IS NOT NULL

In der Abfrage muss die NULL-Filterbedingung (Genre IS NOT NULL für dieses Beispiel) in der WHERE-Klausel angegeben werden. Andernfalls kann der Query Optimizer den Suchindex nicht verwenden. Weitere Informationen finden Sie unter Anforderungen an SQL-Abfragen.

Wenn Sie den Filter WHERE <column> IS NOT NULL in der Indexdefinition verwenden, werden nur Werte ungleich null indexiert. So kann der Abfrageoptimierer den Index für relevante Abfragen effektiv verwenden, auch wenn die IS NOT NULL-Bedingung nicht explizit in der WHERE-Klausel der Abfrage enthalten ist.

Verwenden Sie die NULL-Filterung für eine generierte Spalte, um Zeilen anhand beliebiger Kriterien auszuschließen. Weitere Informationen finden Sie unter Teilindex mit einer generierten Spalte erstellen.

Nächste Schritte