Ontwerp voor query's
Tabelserviceoplossingen kunnen leesintensief, schrijfintensief of een combinatie van de twee zijn. Dit artikel is gericht op de zaken die u in gedachten moet houden wanneer u uw Table-service zo ontwerpt dat leesbewerkingen efficiënt worden ondersteund. Een ontwerp dat efficiënt leesbewerkingen ondersteunt, is doorgaans ook efficiënt voor schrijfbewerkingen. Er zijn echter aanvullende overwegingen waarmee u rekening moet houden bij het ontwerpen ter ondersteuning van schrijfbewerkingen, zoals besproken in het artikel Ontwerpen voor gegevenswijziging.
Een goed uitgangspunt voor het ontwerpen van uw Table-serviceoplossing om u in staat te stellen gegevens efficiënt te lezen, is de vraag 'Welke query's moet mijn toepassing uitvoeren om de gegevens op te halen die nodig zijn uit de Table-service?'
Notitie
Met de Table-service is het belangrijk om het ontwerp van te voren correct te krijgen, omdat het later moeilijk en duur is om het te wijzigen. In een relationele database is het bijvoorbeeld vaak mogelijk om prestatieproblemen op te lossen door gewoon indexen toe te voegen aan een bestaande database: dit is geen optie met de Table-service.
Deze sectie is gericht op de belangrijkste problemen die u moet oplossen wanneer u tabellen ontwerpt voor het uitvoeren van query's. De onderwerpen die in deze sectie worden behandeld, zijn onder andere:
- Hoe uw keuze van PartitionKey en RowKey van invloed is op de queryprestaties
- Een geschikte PartitionKey kiezen
- Query's optimaliseren voor de Table-service
- Gegevens sorteren in de Tabelservice
Hoe uw keuze van PartitionKey en RowKey van invloed is op de queryprestaties
In de volgende voorbeelden wordt ervan uitgegaan dat de tabelservice werknemersentiteiten met de volgende structuur opslaat (de meeste voorbeelden laten de eigenschap Timestamp voor de duidelijkheid weg):
Kolomnaam | Gegevenstype |
---|---|
PartitionKey (afdelingsnaam) | Tekenreeks |
RowKey (werknemer-id) | Tekenreeks |
FirstName | Tekenreeks |
LastName | Tekenreeks |
Age | Geheel getal |
Emailaddress | Tekenreeks |
In het artikel Overzicht van Azure Table Storage worden enkele van de belangrijkste functies van de Azure Table-service beschreven die een directe invloed hebben op het ontwerpen voor query's. Deze resulteren in de volgende algemene richtlijnen voor het ontwerpen van Tabelservice-query's. Houd er rekening mee dat de filtersyntaxis die in de onderstaande voorbeelden wordt gebruikt, afkomstig is van de REST API van de Table-service. Zie Query-entiteiten voor meer informatie.
- Een puntquery is de meest efficiënte zoekactie om te gebruiken en wordt aanbevolen om te worden gebruikt voor zoekopdrachten met grote volumes of zoekopdrachten waarvoor de laagste latentie is vereist. Een dergelijke query kan de indexen gebruiken om een afzonderlijke entiteit zeer efficiënt te vinden door zowel de waarden PartitionKey als RowKey op te geven. Bijvoorbeeld: $filter=(PartitionKey eq 'Sales') en (RowKey eq '2')
- De tweede beste is een bereikquery die gebruikmaakt van de PartitionKey en filtert op een bereik van RowKey-waarden om meer dan één entiteit te retourneren. De waarde PartitionKey identificeert een specifieke partitie en de RowKey-waarden identificeren een subset van de entiteiten in die partitie. Bijvoorbeeld: $filter=PartitionKey eq 'Sales' en RowKey ge 'S' en RowKey lt 'T'
- De derde beste is een partitiescan die gebruikmaakt van de PartitionKey en filters op een andere niet-sleuteleigenschap en die meer dan één entiteit kan retourneren. De waarde PartitionKey identificeert een specifieke partitie en de eigenschapswaarden selecteren voor een subset van de entiteiten in die partitie. Bijvoorbeeld: $filter=PartitionKey eq 'Sales' en LastName eq 'Smith'
- Een tabelscan bevat niet de PartitionKey en is zeer inefficiënt omdat hiermee alle partities waaruit uw tabel bestaat, worden gezocht naar overeenkomende entiteiten. Er wordt een tabelscan uitgevoerd, ongeacht of het filter gebruikmaakt van de RowKey. Bijvoorbeeld: $filter=LastName eq 'Jones'
- Query's die meerdere entiteiten retourneren, retourneren deze gesorteerd in de volgorde PartitionKey en RowKey . Om te voorkomen dat de entiteiten in de client worden gebruikt, kiest u een RowKey die de meest voorkomende sorteervolgorde definieert.
Houd er rekening mee dat het gebruik van een 'of' om een filter op te geven op basis van RowKey-waarden resulteert in een partitiescan en niet wordt behandeld als een bereikquery. Daarom moet u query's vermijden die filters gebruiken, zoals: $filter=PartitionKey eq 'Sales' en (RowKey eq '121' of RowKey eq '322')
Zie voor voorbeelden van code aan de clientzijde die de Storage-clientbibliotheek gebruiken om efficiënte query's uit te voeren:
- Een puntquery uitvoeren met behulp van de Storage-clientbibliotheek
- Meerdere entiteiten ophalen met linq
- Projectie aan serverzijde
Zie voor voorbeelden van code aan de clientzijde die meerdere entiteitstypen kan verwerken die zijn opgeslagen in dezelfde tabel:
Een geschikte PartitionKey kiezen
Uw keuze voor PartitionKey moet de noodzaak om het gebruik van entiteitsgroepstransacties in te schakelen (om consistentie te garanderen) afwegen tegen de vereiste om uw entiteiten over meerdere partities te verdelen (om een schaalbare oplossing te garanderen).
Aan de ene kant kunt u al uw entiteiten in één partitie opslaan, maar dit kan de schaalbaarheid van uw oplossing beperken en voorkomt dat de tabelservice taken kan verdelen. Aan de andere kant kunt u één entiteit per partitie opslaan, die zeer schaalbaar is en waarmee de tabelservice aanvragen kan verdelen, maar waardoor u geen entiteitsgroepstransacties kunt gebruiken.
Een ideale PartitionKey is een partitiesleutel waarmee u efficiënte query's kunt gebruiken en die voldoende partities heeft om ervoor te zorgen dat uw oplossing schaalbaar is. Normaal gesproken zult u merken dat uw entiteiten een geschikte eigenschap hebben waarmee uw entiteiten over voldoende partities worden verdeeld.
Notitie
In een systeem waarin informatie over gebruikers of werknemers wordt opgeslagen, kan UserID bijvoorbeeld een goede PartitionKey zijn. Mogelijk hebt u verschillende entiteiten die een bepaalde UserID als partitiesleutel gebruiken. Elke entiteit waarin gegevens over een gebruiker worden opgeslagen, wordt gegroepeerd in één partitie, zodat deze entiteiten toegankelijk zijn via entiteitsgroepstransacties, terwijl ze nog steeds zeer schaalbaar zijn.
Er zijn aanvullende overwegingen bij uw keuze van PartitionKey die betrekking hebben op hoe u entiteiten invoegt, bijwerkt en verwijdert. Zie Tabellen ontwerpen voor gegevenswijziging voor meer informatie.
Query's optimaliseren voor de Table-service
De Table-service indexeert uw entiteiten automatisch met behulp van de waarden PartitionKey en RowKey in één geclusterde index, vandaar de reden dat puntquery's het meest efficiënt zijn om te gebruiken. Er zijn echter geen andere indexen dan die op de geclusterde index op de PartitionKey en RowKey.
Veel ontwerpen moeten voldoen aan vereisten om entiteiten op te zoeken op basis van meerdere criteria. Bijvoorbeeld het zoeken naar werknemersentiteiten op basis van e-mailadres, werknemer-id of achternaam. De patronen die worden beschreven in Tabelontwerppatronen hebben betrekking op deze typen vereisten en beschrijven manieren om te omzeilen dat de Table-service geen secundaire indexen biedt:
- Secundair indexpatroon tussen partities : sla meerdere kopieën van elke entiteit op met behulp van verschillende RowKey-waarden (in dezelfde partitie) om snelle en efficiënte zoekacties en alternatieve sorteervolgordes mogelijk te maken met behulp van verschillende RowKey-waarden .
- Secundair indexpatroon tussen partities : sla meerdere kopieën van elke entiteit op met behulp van verschillende RowKey-waarden in afzonderlijke partities of in afzonderlijke tabellen om snelle en efficiënte zoekacties en alternatieve sorteervolgordes mogelijk te maken met behulp van verschillende RowKey-waarden .
- Patroon voor indexentiteiten : onderhoud indexentiteiten om efficiënte zoekopdrachten mogelijk te maken die lijsten met entiteiten retourneren.
Gegevens sorteren in de Tabelservice
De Table-service retourneert entiteiten die in oplopende volgorde zijn gesorteerd op basis van PartitionKey en vervolgens op RowKey. Deze sleutels zijn tekenreekswaarden en om ervoor te zorgen dat numerieke waarden correct worden gesorteerd, moet u ze converteren naar een vaste lengte en ze opvulen met nullen. Als de waarde van de werknemer-id die u als RowKey gebruikt bijvoorbeeld een geheel getal is, moet u werknemer-id 123 converteren naar 00000123.
Veel toepassingen hebben vereisten voor het gebruik van gegevens die in verschillende orders zijn gesorteerd, bijvoorbeeld het sorteren van werknemers op naam of op datum van deelname. De volgende patronen hebben betrekking op het wisselen van sorteervolgordes voor uw entiteiten:
- Secundair indexpatroon tussen partities : sla meerdere kopieën van elke entiteit op met behulp van verschillende RowKey-waarden (in dezelfde partitie) om snelle en efficiënte zoekacties en alternatieve sorteervolgordes mogelijk te maken met behulp van verschillende RowKey-waarden.
- Secundair indexpatroon tussen partities : sla meerdere kopieën van elke entiteit op met behulp van verschillende RowKey-waarden in afzonderlijke partities in afzonderlijke tabellen om snelle en efficiënte zoekacties en alternatieve sorteervolgordes mogelijk te maken met behulp van verschillende RowKey-waarden.
- Logboekstaartpatroon : haal de n entiteiten op die het laatst aan een partitie zijn toegevoegd met behulp van een RowKey-waarde die in omgekeerde datum- en tijdvolgorde wordt gesorteerd.