Entwurf für Abfragen

Anwendungen für einen Tabellenspeicherdienst können intensiv lesen, intensiv schreiben oder beides. Dieser Artikel konzentriert sich auf die Dinge, die Sie beim Entwurf Ihres Tabellenspeicherdienstes beachten sollten, um Lesevorgänge effizient zu unterstützen. In der Regel ist ein Entwurf, der Lesevorgänge effizient unterstützt, auch für Schreibvorgänge effizient. Es gibt jedoch weitere Überlegungen, die beim Entwerfen der Unterstützung von Schreibvorgängen zu beachten sind und im Artikel Entwurf für die Datenänderung erläutert werden.

Ein guter Ausgangspunkt für den Entwurf Ihrer Lösung für einen Tabellenspeicherdienst mit effizientem Lesen der Daten ist, sich zu fragen: „Welche Abfragen meiner Anwendung müssen ausgeführt werden, um die benötigten Daten abzurufen, die vom Tabellenspeicherdienst benötigt werden?“

Hinweis

Für einen Tabellenspeicherdienst ist es wichtig, den Entwurf von Anfang an richtig zu machen, da Änderungen zu einem späteren Zeitpunkt schwierig und teuer sind. Beispielsweise ist es bei einer relationalen Datenbank oft möglich, Leistungsprobleme in Angriff zu nehmen, indem Sie einfach einer vorhandenen Datenbank Indexe hinzufügen. Diese Möglichkeit steht bei einem Tabellenspeicherdienst nicht zur Verfügung.

Dieser Abschnitt konzentriert sich auf die Hauptprobleme, mit denen Sie sich beim Entwurf der Tabellen für die Abfrage befassen müssen. Die in diesem Abschnitt behandelten Themen umfassen:

Auswirkungen der Wahl von PartitionKey und RowKey auf die Abfrageleistung

In den folgenden Beispielen wird angenommen, dass der Tabellenspeicherdienst Entitäten von Mitarbeitern mit der folgenden Struktur speichert (bei den meisten Beispielen fehlt die Eigenschaft Zeitstempel aus Gründen der Übersichtlichkeit):

Spaltenname Datentyp
PartitionKey (Abteilungsname) String
RowKey (Mitarbeiter-ID) String
Vorname String
Nachname String
Alter Integer
EmailAddress String

Im Artikel Einführung zu Tabellenspeicher in Azure werden einige der wichtigsten Funktionen des Azure-Tabellenspeicherdiensts beschrieben, die direkten Einfluss auf den Entwurf für Abfragen haben. Dadurch ergeben sich die folgenden allgemeinen Richtlinien für den Entwurf von Abfragen für den Tabellenspeicherdienst. Beachten Sie, dass die in den Beispielen unten verwendete Filtersyntax aus dem REST-API-Tabellenspeicherdienst stammt. Weitere Informationen finden Sie unter Query Entities (Abfragen von Entitäten).

  • Eine Punktabfrage ist die effizienteste Abfrage und wird für Abfragen mit hohem Volumen oder für Abfragen mit geringer Latenzzeit empfohlen. Eine solche Abfrage kann Indizes verwenden, um durch die Angabe der PartitionKey- und RowKey-Werte eine einzelne Entität sehr effizient zu suchen. Beispiel: $filter=(PartitionKey eq 'Sales') und (RowKey eq '2')
  • Am zweitbesten ist eine Range Query, die den PartitionKey verwendet und nach einem Bereich von RowKey-Werten filtert, um mehr als eine Entität zurückzugeben. Der PartitionKey-Wert identifiziert eine bestimmte Partition, die RowKey-Werte identifizieren eine Teilmenge der Entitäten in dieser Partition. Beispiel: $filter=PartitionKey eq 'Sales' und RowKey ge 'S' und RowKey lt 'T'
  • Am drittbesten ist ein Partition Scan, der den PartitionKey verwendet und nach einer anderen Nicht-Schlüssel-Eigenschaft filtert und der mehr als eine Entität zurückgeben kann. Der PartitionKey -Wert identifiziert eine bestimmte Partition und die Eigenschaftswerte wählen eine Teilmenge der Entitäten in dieser Partition aus. Beispiel: $filter=PartitionKey eq 'Sales' und LastName eq 'Smith'
  • Ein Tabellenscan schließt den PartitionKey nicht ein und ist sehr ineffizient, da er alle Partitionen, aus denen Ihre Tabelle besteht, der Reihe nach auf passende Entitäten hin durchsucht. Er führt einen Tabellenscan durch, unabhängig davon, ob der Filter RowKeyverwendet. Beispiel: $filter=LastName eq 'Jones'
  • Abfragen, die mehrere Entitäten zurückgeben, geben diese nach PartitionKey und RowKey sortiert zurück. Um eine Neusortierung der Entitäten im Client zu vermeiden, müssen Sie einen RowKey mit der am häufigsten verwendeten Sortierreihenfolge auswählen.

Beachten Sie, dass die Verwendung von or für die Festlegung eines Filters, der auf RowKey-Werten basiert, zu einem Partitionsscan führt und nicht als Bereichsabfrage behandelt wird. Aus diesem Grund sollten Sie Abfragen vermeiden, die z. B. folgende Filter verwenden: $filter=PartitionKey eq 'Sales' und (RowKey eq '121' or RowKey eq '322')

Beispiele für clientseitigen Code, der die Storage Client Library zur Ausführung effizienter Abfragen verwendet, finden Sie unter:

Beispiele für clientseitigen Code, der mehrere Entitätstypen handhaben kann, die in der gleichen Tabelle gespeichert sind, finden Sie unter:

Auswählen eines geeigneten PartitionKey

Bei der Auswahl des PartitionKey sollte ein Abgleich zwischen der Notwendigkeit, die Verwendung von EGTs (Entity Group Transaction) freizugeben (zur Sicherstellung der Konsistenz), und der Anforderung zur Verteilung von Entitäten auf mehrere Partitionen (um eine skalierbare Lösung sicherzustellen) vorgenommen werden.

Ein Extremfall ist, dass Sie alle Entitäten in einer einzelnen Partition speichern würden. Dies würde aber möglicherweise die Skalierbarkeit Ihrer Lösung begrenzen und verhindern, dass der Tabellenspeicherdienst Anforderungen für den Lastenausgleich vornehmen kann. Im anderen Extremfall könnten Sie eine Entität pro Partition speichern, was höchst skalierbar wäre und es dem Tabellenspeicherdienst ermöglichen würde, einen Lastenausgleich für Anforderungen vorzunehmen, was aber verhindern würde, dass Sie Entitätsgruppentransaktionen verwenden können.

Ein idealer PartitionKey ermöglicht die Verwendung von effizienten Abfragen und verfügt über ausreichende Partitionen, um sicherzustellen, dass Ihre Lösung skalierbar ist. In der Regel werden Sie feststellen, dass Ihre Entitäten über eine geeignete Eigenschaft verfügen, die Ihre Entitäten über ausreichende Partitionen verteilt.

Hinweis

Beispielsweise kann in einem System, auf dem Informationen über Benutzer und Mitarbeiter gespeichert werden, die Benutzer-ID eine guter PartitionKey sein. Sie haben möglicherweise mehrere Entitäten, für die eine bestimmte Benutzer-ID als Partitionsschlüssel verwendet wird. Jede Entität, die Daten zu einem Benutzer speichert, wird in einer einzigen Partition gruppiert, und somit kann über Entitätsgruppentransaktionen auf diese Entitäten zugegriffen werden, während sie gleichzeitig hoch skalierbar sind.

Bei der Wahl des PartitionKey-Werts sind weitere Aspekte zu bedenken, die sich darauf beziehen, wie Sie Entitäten einfügen, aktualisieren und löschen. Weitere Informationen finden Sie unter Entwurf für Datenänderung.

Optimieren von Abfragen für den Tabellenspeicherdienst

Der Tabellenspeicherdienst indiziert die Entitäten automatisch unter Verwendung von PartitionKey- und RowKey-Werten in einem einzelnen gruppierten Index. Aus diesem Grund stellen Punktabfragen die effizienteste Lösung dar. Allerdings gibt es mit Ausnahme des gruppierten Index für PartitionKey und RowKey keine weiteren Indizes.

Viele Entwürfe müssen Anforderungen erfüllen, um die Suche nach Entitäten auf Grundlage mehrerer Kriterien zu ermöglichen. Suchen Sie z. B. Mitarbeiterentitäten auf Grundlage der E-Mail-Adresse, Mitarbeiter-ID oder Nachname. Die in Entwurfsmuster für die Tabelle beschriebenen Muster befassen sich mit diesen Arten von Anforderungen und beschreiben Möglichkeiten zum Umgehen der Tatsache, dass der Tabellenspeicherdienst keine sekundären Indizes zur Verfügung stellt:

  • Sekundäres Indexmuster für Intra-Partition – Speichern mehrerer Kopien jeder Entität mit unterschiedlichen RowKey-Werten (in der gleichen Partition) zur Ermöglichung schneller und effizienter Suchvorgänge und alternativer Sortierreihenfolgen mit unterschiedlichen RowKey-Werten.
  • Sekundäres Indexmuster für Inter-Partition – Speichern mehrerer Kopien der einzelnen Entitäten mithilfe verschiedener RowKey-Werte in separaten Partitionen oder in separaten Tabellen zur Aktivierung schneller und effizienter Suchvorgänge und alternativer Sortierreihenfolgen mit unterschiedlichen RowKey-Werten.
  • Indexmuster für Entitäten – Verwalten von Indexentitäten, um effiziente Suchvorgänge zu ermöglichen, die Listen mit Entitäten zurückgeben.

Sortieren von Daten im Tabellenspeicherdienst

Der Tabellenspeicherdienst gibt Entitäten zurück, die in aufsteigender Reihenfolge nach PartitionKey und RowKey sortiert sind. Diese Schlüssel sind String-Werte. Um sicherzustellen, dass die numerischen Werte ordnungsgemäß sortieren, sollten sie mit einer festen Länge konvertiert und mit Nullen aufgefüllt werden. Wenn etwa der als RowKey verwendete Mitarbeiter-ID-Wert ein ganzzahliger Wert ist, sollten Sie die Mitarbeiter-ID 123 in 00000123 konvertieren.

Viele Anwendungen verfügen über Anforderungen für die Verwendung von Daten, die in unterschiedlicher Reihenfolge sortiert sind,z. B. bei Sortierung von Mitarbeitern nach Name oder durch das Verknüpfen eines Datums. Die folgenden Muster befassen sich mit der Verwendung alternativer Sortierreihenfolgen für Entitäten:

  • Sekundäres Indexmuster für Intra-Partition – Speichern mehrerer Kopien jeder Entität mit unterschiedlichen RowKey-Werten (in der gleichen Partition) zur Ermöglichung schneller und effizienter Suchvorgänge und alternativer Sortierreihenfolgen mit unterschiedlichen RowKey-Werten.
  • Sekundäres Indexmuster für Inter-Partition – Speichern mehrerer Kopien der einzelnen Entitäten mit verschiedenen RowKey-Werten in separaten Partitionen in separaten Tabellen für schnelle und effiziente Suchvorgänge und alternative Sortierreihenfolgen mit verschiedenen RowKey-Werten.
  • Log Tail-Muster – Abrufen der n Entitäten, die zuletzt einer Partition hinzugefügt wurden, indem Sie einen RowKey -Wert verwenden, mit dem nach Datum und Uhrzeit in umgekehrter Reihenfolge sortiert wird.

Nächste Schritte