Suchindexe partitionieren

Spanner unterstützt sowohl nicht partitionierte als auch partitionierte Suchindexe. Auf dieser Seite wird beschrieben, wie Sie einen partitionierten Suchindex in Spanner erstellen.

Ein nicht partitionierter Index wird erstellt, wenn die Klausel PARTITION BY in der Indexdefinition weggelassen wird. Bei einem nicht partitionierten Index muss eine Abfrage aus allen Indexaufteilungen gelesen werden. Das schränkt die potenzielle Skalierbarkeit von Volltextsuchanfragen ein.

Partitionierte Indexe unterteilen den Index dagegen in kleinere Einheiten, eine für jede eindeutige Partition. Abfragen können jeweils nur in einer einzelnen Partition gesucht werden, die durch eine Gleichheitsbedingung in der WHERE-Klausel angegeben wird. Abfragen auf partitionierte Indexe sind im Allgemeinen effizienter als Abfragen auf nicht partitionierte Indexe, da Spanner nur Daten für eine einzelne Partition lesen muss. Die Partitionierung des Suchindexes ist analog zum Schlüsselpräfix eines sekundären Index.

Angenommen, es gibt 1.000.000 SingerIds in einer Datenbank und die folgenden beiden Indexe:

GoogleSQL

CREATE TABLE Albums (
  AlbumId STRING(MAX) NOT NULL,
  SingerId STRING(MAX) NOT NULL,
  ReleaseTimestamp INT64 NOT NULL,
  AlbumTitle STRING(MAX),
  AlbumTitle_Tokens TOKENLIST AS (TOKENIZE_FULLTEXT(AlbumTitle)) HIDDEN,
  SingerId_Tokens TOKENLIST AS (TOKEN(SingerId)) HIDDEN
) PRIMARY KEY(SingerId, AlbumId);

CREATE SEARCH INDEX AlbumsUnpartitionedIndex
ON Albums(AlbumTitle_Tokens, SingerId_Tokens);

CREATE SEARCH INDEX AlbumsIndexBySingerId
ON Albums(AlbumTitle_Tokens)
PARTITION BY SingerId;

PostgreSQL

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

CREATE SEARCH INDEX albumsunpartitionedindex
ON albums(albumtitle_tokens, singerid_tokens);

CREATE SEARCH INDEX albumsindexbysingerid
ON albums(albumtitle_tokens)
PARTITION BY singerid;

In der folgenden Abfrage wird der Index AlbumsIndexBySingerId ausgewählt, da nur nach Daten für einen einzelnen Sänger gesucht wird. Bei dieser Art von Abfrage werden in der Regel weniger Ressourcen verbraucht.

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SingerId = "singer1"
AND SEARCH(AlbumTitle_Tokens, 'happy')

PostgreSQL

SELECT albumid
FROM albums
WHERE singerid = 'singer1'
AND spanner.search(albumtitle_tokens, 'happy')

Es ist auch möglich, AlbumsUnpartitionedIndex für eine Abfrage zu erzwingen, um dieselben Ergebnisse zurückzugeben. Sie verbraucht jedoch mehr Ressourcen, da die Abfrage auf alle Indexaufteilungen zugreifen und alle Alben für alle Sänger filtern muss, um das Token „glücklich“ zu finden, anstatt nur die Aufteilungen, die dem Sänger singer1 entsprechen.

Es gibt jedoch Fälle, in denen die Anwendung alle Alben durchsuchen muss, anstatt nur die Alben eines bestimmten Sängers. In diesen Fällen müssen Sie einen nicht partitionierten Index verwenden:

GoogleSQL

SELECT AlbumId
FROM Albums
WHERE SEARCH(AlbumTitle_Tokens, 'piano concerto 1')

PostgreSQL

SELECT albumid
FROM albums
WHERE spanner.search(albumtitle_tokens, 'piano concerto 1')

Im Allgemeinen wird empfohlen, die Partitionierung so detailliert wie möglich vorzunehmen, was für die Abfrage praktisch und angemessen ist. Wenn die Anwendung beispielsweise ein E-Mail-Postfach abfragt, bei dem jede Abfrage auf ein bestimmtes Postfach beschränkt ist, partitionieren Sie den Suchindex nach der Postfach-ID. Wenn bei der Abfrage jedoch alle Postfächer durchsucht werden müssen, ist ein nicht partitionierter Index besser geeignet.

Bestimmte Anwendungen erfordern möglicherweise mehrere Partitionierungsstrategien, um ihren spezifischen Suchanforderungen gerecht zu werden. Ein Inventarverwaltungssystem muss beispielsweise Suchanfragen unterstützen, die nach Produkttyp oder Hersteller gefiltert werden. Außerdem sind für einige Anwendungen möglicherweise mehrere Vorsortierungen erforderlich, z. B. eine Sortierung nach Erstellungs- oder Änderungszeit. In diesen Fällen sollten Sie mehrere Suchindizes erstellen, die jeweils für die entsprechenden Abfragen optimiert sind. Der Abfrageoptimierer von Spanner wählt automatisch einen Index für jede Abfrage aus.

Nächste Schritte