Uit dit verhaal zou je kunnen concluderen dat Windows Azure Sql Database voor grote databases knap waardeloos is, maar deze limieten heb je bij traditionele on-premise databases ook. Uiteindelijk zit je aan de grenzen van de hardware. Ook hier zou je een flexibele schaling willen, maar voor databases is dat niet zo eenvoudig.
Een techniek die tegenwoordig veel gebruikt wordt is Database Sharding. Bij Sharding wordt een enorme tabel in stukken geknipt. Dit knippen gebeurt horizontaal, dus op basis van rijen. Denk bijvoorbeeld aan een wereldwijde klantentabel met miljoenen (linkedin, facebook) records. Je kunt zo'n tabel in stukken hakken door klanten per werelddeel te groeperen in hun eigen tabel. Je krijgt dus een tabel KlantenEuropa, KlantenAzie enz. Dit is overigens geen sharding. Dit is gewoon horizontale partitionering (afbeelding 1), een techniek die al een tijdje bestaat waarbij je de indexgrootte reduceert en dus sneller kunt zoeken. Sharding gaat een stap verder en plaatst die partities op verschillende databaseservers (afbeelding 2). Er komen ook geen tabellen zoals KlantenEurope, maar gewoon Klanten. Binnen hun serverinstantie zijn ze tenslotte tóch uniek. Met deze benadering heb je de voordelen van de traditionele horizontale partitionering plus de extra resources omdat zo'n partitie op een eigen machine kan draaien. Zo'n database-instantie, met zijn eigen tabelfragment, noemt men een shard.
![]() |
Afbeelding 1. Traditionele horizontale partitionering op basis van leeftijd. De User tabel is in stukken geknipt, maar leeft wel binnen dezelfde database-instantie (bron www.cubrid.org). |
![]() |
Afbeelding 2. Dezelfde horizontale partitionering, maar nu zijn de partities op verschillende database-instanties geplaatst. Dit is Sharding (bron www.cubrid.org). |
- In welke database staat de data die jij zoekt?
- De ene shard wordt enorm (klanten uit Azië) terwijl een andere shard klein blijft (klanten uit Australië)
- Hoe ga je overweg met joins?
- Hoe zit het met gegenereerde primary keys?
Een aantal van deze problemen kan ondervangen worden door gebruik te maken van een shard key. Zo'n key beschrijft eigenlijk de kolom waarop je wilt sharden, bijvoorbeeld de kolom werelddeel in de klantentabel, maar het zou ook de leeftijd kunnen zijn, een datum of een getal. Wat je ook kiest, je zult een criterium moeten bepalen op basis waarvan de sharding plaatsvindt. Je kunt hierbij denken aan de volgende schema's:
- Range. Denk hierbij een leeftijd (personen tussen 10 en 20 jaar) of datum (geboren tussen van 1980 tot 1990).
- Key. Hierbij kun je denken aan een bepaalde wiskundige operatie. Stel je hebt als shard key een integer getal gekozen. Je kunt nu sharden op basis van even of oneven getallen. Beter is het om modulo te gebruiken (met een modulo bepaal je de restwaarde van een deling. 6 % 5 = 1, 7 % 5 = 2, 8 % 5 = 3, 10 % 5 = 0, 11 % 5 = 1, enz). Op basis van die restwaarde weet je naar welke database je moet schrijven. In dit rekenvoorbeeld zou je dus vijf shards krijgen.
- Houdt een lookup tabel bij van je shard keys waarin je aangeeft in welke shard je de data moet zoeken.
Het joinen van tabellen is bij sharding lastig omdat deze joins over databases gaan. Je zou dat probleem kunnen ondervangen door gerelateerde data in dezelfde shard te plaatsen (een klant met zijn orders in dezelfde shard). Helaas zul je niet om handmatig bijlezen heen komen, immers de producten die bij een order horen kun je niet sharden. Voordeel is wel dat je die lookup query parallel kunt uitvoeren.
Het wordt ook vervelend bij sql-funties zoals AVG() (gemiddelde). Hierbij zul je het gemiddelde van iedere shard afzondelijk moeten bepalen en de resultaten zien te combineren om tot het eindresultaat te komen.
Het valt allemaal niet mee, maar als je het goed inricht en de juiste shard key kiest, heb je wel de ultieme schaalbare oplossing.
In Windows Azure SQL Database zit reeds een goede voorziening voor sharding, alleen gebruiken ze daar de naam federation. Een shard wordt een federation member en de shard key wordt een federation key. Sql Azure gebruikt een aparte database die bijhoudt welke federations er leven. Deze database noemt men de federation root.
Om een federated database op te zetten, begin je met het aanmaken van een gewone database in de Azure Portal (Zie eerdere blog). Wanneer je inlogt op de database en naar "Administration" gaat, kun je een nieuwe federation aanmaken (afbeelding 3). In het volgende venster (afbeelding 4) moet je de federation key specificeren. Je begint met een naam, vervolgens bepaal je wat voor een type de federation key is. Tenslotte moet je het sharding criterium opgeven. Momenteel weinig keus, we hebben alleen RANGE.
In Windows Azure SQL Database zit reeds een goede voorziening voor sharding, alleen gebruiken ze daar de naam federation. Een shard wordt een federation member en de shard key wordt een federation key. Sql Azure gebruikt een aparte database die bijhoudt welke federations er leven. Deze database noemt men de federation root.
Om een federated database op te zetten, begin je met het aanmaken van een gewone database in de Azure Portal (Zie eerdere blog). Wanneer je inlogt op de database en naar "Administration" gaat, kun je een nieuwe federation aanmaken (afbeelding 3). In het volgende venster (afbeelding 4) moet je de federation key specificeren. Je begint met een naam, vervolgens bepaal je wat voor een type de federation key is. Tenslotte moet je het sharding criterium opgeven. Momenteel weinig keus, we hebben alleen RANGE.
![]() |
Afbeelding 3. Een nieuwe federation aanmaken |
![]() |
Afbeelding 4. De federation key definiëren |
![]() |
Afbeelding 5. De federation root (fedtest) en een federation member (system-bd1c... de onderste). |
![]() |
Afbeelding 6. Het overzicht van de federation members. |
USE FEDERATION (fed_brand = -1) WITH FILTERING = OFF, RESET
GO
Dit statement zorgt ervoor dat de queries nu naar de eerste (en vooralsnog enige) federation member gaan. (fed_brand = -1) geeft aan dat we de federation member met RANGE minimum -1 willen aanspreken, FILTERING = OFF geeft aan dat we alle federation keys willen aanspreken (Met waarde ON krijg je alleen het record, behorende bij de bij fed_brand gespecificeerde waarde, -1 in dit geval). RESET om de connectie te resetten.
![]() |
Afbeelding 7. Een query die naar de eerste federation member gestuurd wordt. |
FEDERATED ON (BrandID = [ID])
De betekenis van dit statement is tweeledig: het geeft aan dat de data gesplitst kan worden en welk veld als federation key moet worden gebruikt (ID in dit geval). Bij de creatie van de producttabel zie je nog zo'n statement, maar nu op de foreign key van de producttabel. Ook deze tabel wordt nu in de splitsing meegenomen. Het zal ertoe leiden dat alle merken met hun bijbehorende producten in dezelfde federation member komen te staan (herinner je dat een join over shards niet mogelijk is).
Wanneer de tabel goed gevuld is, kun je hem gaan splitsten (afbeelding 8). Bij "Split" geef je aan vanaf welke waarde er gesplitst moet worden.
![]() |
Afbeelding 8. Splitsten vanaf ID=4000 |
![]() |
Afbeelding 9. De federation root (fedtest) met drie federation members. |
USE FEDERATION (fed_brand = 4000) WITH FILTERING = OFF, RESET
GO
SELECT * FROM Core.Brand
GO
SELECT * FROM Core.Brand
Deze query zal alle merken vanaf ID = 4000 terug geven. Als je FILTERING=ON zou specificeren, zou je alleen het merk met ID=4000 krijgen.
Sharding is een interessante techniek om schalen van databases mogelijk te maken. Windows Azure SQL Database heeft met federations een fraai initiatief gelanceerd, dat zeker perspectief biedt. Laat onverlet dat sharding een lastige techniek is om te gebruiken. Het vereist een goede keuze voor de sharding key. (Mijn keuze voor de primary key van Brand bleek niet zo'n juiste te zijn. Omdat de grote merken al in het begin van de tabel zaten, leverde dat ongebalanceerde shards op. Te veel producten in de eerste shard).
De volgende keer bespreek ik hoe je met Entity Framework de data uit een federated database trekt.
Ik heb begrepen dat SQL Azure Federations niet verder ontwikkeld wordt. Reden is met name dat de performance van Federations inzakt bij omvang bij grotere hoeveelheden data (totale set > 150GB) en dat de performance veel beter kan zijn als je sharding zelf inricht.
BeantwoordenVerwijderen