Einerseits haben wir einen „klassischen“ SQL Server 2019 sowohl vor Ort als auch in der Cloud. In dieser Kategorie würden beide Azure SQL-Datenbanken als einzelne/elastische/verwaltete Instanzen eingetragen. Von dort aus haben wir weitere Varianten, die sich wesentlich vom „klassischen“ SQL Server unterscheiden:

  • Azure SQL-Datenbank-Hyperskcale. Diese Variante ist diejenige, auf die wir uns in diesem Artikel konzentrieren, und zeichnet sich durch eine SMP-Architektur aus, bei der die Speicherschicht horizontal skalierbar ist. Es ist nur in Azure verfügbar.
  • Azure Synapse Analytics. Diese Alternative, die früher als Parallel Datawarehouse bekannt war, basiert auf einer MPP-Architektur, bei der sowohl die Speicherung als auch die Berechnung skalierbar sind, was eine hohe Leistung auch bei großen Datenmengen ermöglicht. Nur in Azure verfügbar.
  • Big Data Cluster.Unterstützt von Kubernetes bietet diese Lösung eine Lösung ähnlich der Azure Synapse Analytics, die sowohl vor Ort als auch in einer von Azure AKS oder einer anderen Alternative gehosteten Wolke ausgeführt werden kann.

Wie wir bereits erwähnt haben, zeichnet sich Azure SQL Database HyperScale vor allem durch die Trennung von Speicherung und Berechnung durch die Verwendung von Page-Servern und Logging-Service aus. Das folgende Diagramm zeigt die vollständige Architektur:

Aus der Sicht des Plattenzugriffs sehen wir, dass wir eine mehrstufige Struktur mit mehreren Caches haben. In den Rechenknoten selbst verfügen wir über einen persistenten RBPEX-Cache (Resilient Buffer Pool Extension), der es den am häufigsten aufgerufenen Seiten ermöglicht, nicht zu irgendeinem Pageserver gehen zu müssen, da sie sich im lokalen SSD befinden. Im Falle eines Cache-Fehlers auf dieser Ebene würden wir zum größten RBPEX-Cache gehen, der sich in jedem der Pageserver befindet. Im Falle eines Ausfalls in diesem Cache würden wir bereits auf den traditionellen Azure-Speicher zugreifen.

Diese neue Konfiguration für die Datenschicht gibt uns horizontale Skalierbarkeit in Bezug auf die Größe unserer Datenbank. So können wir beispielsweise erreichen, dass die Wiederherstellungszeiten einer Datenbank nicht vom gespeicherten Datenvolumen abhängen, sondern nahezu konstant bleiben. Letztes Jahr veröffentlichte Microsoft Research ein sehr interessantes Whitepaper über das Sokrates-Projekt (https://www.microsoft.com/en-us/research/uploads/prod/2019/05/socrates.pdf), das die Grundlage für das Angebot der SQL-Datenbank HyperScale bildete und in dem viele Details über die interne Funktionsweise, die durchgeführten Benchmarks usw. enthalten sind.

Wenn wir die Kosten analysieren, die im Moment Azure für die gleiche Konfiguration mit 4 vCores und 500 GB verursacht, können wir eine Vorstellung davon bekommen, wo diese Alternative positioniert ist:

  • Azure SQL Database General Purpose: $793/Monat
  • Azure SQL Managed Instance General Purpose: $791/Monat
  • Azure SQL Database HyperScale: $875/Monat
  • Azure SQL Database Business Critical: $2108/Monat
  • Azure SQL Managed Instance Business Critical: $2103/Monat

Aus Kostensicht ist es eine etwas teurere Option als die General Purpose-Alternativen, aber nicht viel mehr, und viel billiger als die geschäftskritischen. Auf der Ebene der Leistung liegen wir theoretisch von der generalistischen Seite her irgendwo dazwischen. Das heißt, in Business Critical haben wir lokalen SSD-Speicher, der am schnellsten ist, während wir in General Purpose SSDs verwenden, die aber entfernt sind (Premium-Speicher). Im Fall von HyperScale ist die letzte Speicherschicht die traditionelle Speicherung, aber dank der SSD-Cache-Hierarchie, die wir besprochen haben, verhält sie sich auf einem Leistungsniveau, das in den meisten Fällen viel mehr wie SSDs ist.

Vom Standpunkt des Schreibens von Transaktionsprotokollen aus betrachtet, hat HyperScale ein Ziel von 100 MB/s, was sogar noch höher ist als bei Business Critical. Ein größerer Unterschied besteht in der maximalen Datenbank-/Instanzgröße, die wir mit HyperScale bis zu 100 TB erreichen können, verglichen mit dem Maximum von 4 TB in Business Critical und 8 TB in General Purpose. Es stimmt, dass diese Größen recht hoch sind, aber im Fall von Managed Instance müssen wir berücksichtigen, dass sie von der gesamten Instanz geteilt werden, so dass diese 4-8 TB knapp werden können, wenn wir die Größen mehrerer Datenbanken hinzufügen.

Dennoch glauben wir, dass zumindest theoretisch das ideale Szenario für diese HyperScale-Alternative diejenigen OLTP-Datenbanken wären, die im Laufe der Zeit „gemästet“ wurden und bei denen sich die meisten Operationen auf „neuere“ Daten konzentrieren, auch wenn es gelegentlich analytische Operationen oder umfangreiche Berichte usw. gibt, die historische Daten konsultieren.

Dazu erstellen wir eine SQL-Datenbank für allgemeine Zwecke mit der AdventureWorksLT-Datenbank (das gegebene Beispiel) und „mästen“ sie bis zu einer bestimmten Größe. Wir beginnen damit, die Instanz mit 4 vCores und maximal 500 GB zu konfigurieren:

Sobald wir die Probe haben, fahren wir mit der „Mast“ fort, für die wir zunächst eine erste Tabelle erstellen, die als Vorlage dienen wird:

CREATE TABLE SalesLT.SalesOrderHeaderEnlarged
  (
  SalesOrderID int NOT NULL IDENTITY (1, 1) NOT FOR REPLICATION,
  RevisionNumber tinyint NOT NULL,
  OrderDate datetime NOT NULL,
  DueDate datetime NOT NULL,
  ShipDate datetime NULL,
  Status tinyint NOT NULL,
  OnlineOrderFlag dbo.Flag NOT NULL,
  SalesOrderNumber  AS (isnull(N'SO'+CONVERT([nvarchar](23),[SalesOrderID],0),N'')),
  PurchaseOrderNumber dbo.OrderNumber NULL,
  AccountNumber dbo.AccountNumber NULL,
  CustomerID int NOT NULL,
  BillToAddressID int NOT NULL,
  ShipToAddressID int NOT NULL,
  CreditCardApprovalCode varchar(15) NULL,
  SubTotal money NOT NULL,
  TaxAmt money NOT NULL,
  Freight money NOT NULL,
  TotalDue  AS (isnull(([SubTotal]+[TaxAmt])+[Freight],(0))),
  Comment nvarchar(128) NULL,
  rowguid uniqueidentifier NOT NULL ROWGUIDCOL,
  ModifiedDate datetime NOT NULL
  )  ON [PRIMARY]
GO

SET IDENTITY_INSERT SalesLT.SalesOrderHeaderEnlarged ON
GO
INSERT INTO SalesLT.SalesOrderHeaderEnlarged (
SalesOrderID, RevisionNumber, OrderDate, DueDate, ShipDate, Status, OnlineOrderFlag, PurchaseOrderNumber, AccountNumber, CustomerID, BillToAddressID, ShipToAddressID, CreditCardApprovalCode, SubTotal, TaxAmt, Freight, Comment, rowguid, ModifiedDate)
SELECT 
SalesOrderID, RevisionNumber, OrderDate, DueDate, ShipDate, Status, OnlineOrderFlag, PurchaseOrderNumber, AccountNumber, CustomerID, BillToAddressID, ShipToAddressID,  CreditCardApprovalCode, SubTotal, TaxAmt, Freight, Comment, rowguid, ModifiedDate 
FROM SalesLT.SalesOrderHeader 
GO
SET IDENTITY_INSERT SalesLT.SalesOrderHeaderEnlarged OFF

Insertaremos en esta tabla unos cuantos registros multiplicados a partir de la tabla original:

INSERT INTO SalesLT.SalesOrderHeaderEnlarged 
  (RevisionNumber, OrderDate, DueDate, ShipDate, Status, OnlineOrderFlag, 
   PurchaseOrderNumber, AccountNumber, CustomerID, 
   BillToAddressID, ShipToAddressID, CreditCardApprovalCode, SubTotal, TaxAmt, Freight, Comment, 
   rowguid, ModifiedDate)
SELECT RevisionNumber, DATEADD(dd, number, OrderDate) AS OrderDate, 
   DATEADD(dd, number, DueDate),  DATEADD(dd, number, ShipDate), 
   Status, OnlineOrderFlag, 
   PurchaseOrderNumber, 
   AccountNumber, 
   CustomerID, BillToAddressID, 
   ShipToAddressID, CreditCardApprovalCode, 
 SubTotal, TaxAmt, Freight, SalesOrderID, 
   NEWID(), DATEADD(dd, number, ModifiedDate)
FROM SalesLT.SalesOrderHeader AS soh WITH (HOLDLOCK TABLOCKX)
CROSS JOIN (
    SELECT number
    FROM (	SELECT TOP 1000 ROW_NUMBER() over (order by (select 1)) number
        FROM sys.objects s1,sys.objects s2,sys.objects s3,sys.objects s4,sys.objects s5
      ) AS tab
) AS r

Sobald dies geschehen ist, werden wir, um den Prozess ein wenig zu beschleunigen, die Tabellen mit SELECT INTO klonen, bis wir eine Größe von 400 GB erreichen, wobei wir sie so nummerieren, als ob sie „nicht-einheimische“ Partitionen oder ähnliches wären:

SELECT * INTO SalesLT.SalesOrderDetailEnlarged2 FROM SalesLT.SalesOrderDetailEnlarged
SELECT * INTO SalesLT.SalesOrderDetailEnlarged3 FROM SalesLT.SalesOrderDetailEnlarged 
SELECT * INTO SalesLT.SalesOrderDetailEnlarged4 FROM SalesLT.SalesOrderDetailEnlarged 
SELECT * INTO SalesLT.SalesOrderDetailEnlarged5 FROM SalesLT.SalesOrderDetailEnlarged 
SELECT * INTO SalesLT.SalesOrderDetailEnlarged6 FROM SalesLT.SalesOrderDetailEnlarged
(…)
SELECT * INTO SalesLT.SalesOrderDetailEnlarged885 FROM SalesLT.SalesOrderDetailEnlarged
SELECT * INTO SalesLT.SalesOrderDetailEnlarged886 FROM SalesLT.SalesOrderDetailEnlarged 
SELECT * INTO SalesLT.SalesOrderDetailEnlarged887 FROM SalesLT.SalesOrderDetailEnlarged 
SELECT * INTO SalesLT.SalesOrderDetailEnlarged888 FROM SalesLT.SalesOrderDetailEnlarged 
SELECT * INTO SalesLT.SalesOrderDetailEnlarged889 FROM SalesLT.SalesOrderDetailEnlarged

Am Ende des Prozesses haben wir unsere gemästete Datenbank:

Sobald wir die Daten haben, werden wir einen Count(*) durchführen, die alle erzeugten Tabellen/Partitionen und ein Paar von Operationen umfasst, die eine Stichprobe von 0,1% und 1% für jede dieser Tabellen/Partitionen erhalten. Damit wäre das, was wir simulieren wollen, der Fall einer massiven Operation, die alle Daten zusammen mit ein paar Operationen lesen muss, die sogar massiv in Bezug auf den konsultierten „Gesamtplatz“ sind und tatsächlich eine viel kleinere Anzahl von Zeilen verarbeiten.

Der erste Test Count(*) besteht im Wesentlichen aus der Ausführung einer Abfrage, die der von einer UNION ALL der beteiligten Tabellen ähnelt:

SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged10 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged100 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged101 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged102 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged103 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged104 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged105 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged106 UNION ALL
(…)
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged899 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged9 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged90 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged91 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged92 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged93 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged94 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged95 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged96 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged97 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged98 UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged99 

In diesem Szenario können wir sehen, dass die Leistung der Ein-/Ausgabe des General Purpose nicht ausreicht, um die 4 zugewiesenen vCores zu „füttern“, was die Abfrage verlangsamt:

Die Gesamtzeit der Operation war sehr hoch, 4179 Sekunden, etwa 70 Minuten, wobei jede Probe 5 Minuten in der Grafik darstellt. Wenn wir die Operation erneut durchführen, ist die Dauer ziemlich ähnlich, wir sehen keine wesentlichen Unterschiede.

Für Tests an einer 0,1- und 1-Prozent-Stichprobe verwenden wir eine Abfrage ähnlich der oben genannten mit der Option TABLESAMPLE:

SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged10 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged100 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged101 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged102 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged103 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged104 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged105 TABLESAMPLE (0.1 PERCENT) UNION ALL 
(…)
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged9 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged90 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged91 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged92 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged93 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged94 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged95 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged96 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged97 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged98 TABLESAMPLE (0.1 PERCENT) UNION ALL 
SELECT COUNT (*) FROM SalesLT.SalesOrderDetailEnlarged99 TABLESAMPLE (0.1 PERCENT)

Im Falle der 0,1% der Zeilen beträgt die Gesamtzahl der gezählten Zeilen etwa 6K pro Tabelle, was eine Gesamtzahl von 4,5M Zeilen ergibt. Die Dauer in General Purpose betrug 52 Sekunden für die 0,1%, während sie für die 1% 411 Sekunden betrug.

Der nächste Schritt ist das Upgrade dieser 400 GB großen Datenbank auf Business Critical:

Der Gesamtprozess für die 400 GB dauerte insgesamt etwas mehr als eine Stunde, was angesichts des Datenvolumens und der Tatsache, dass diese Art von Vorgang normalerweise selten ist, keine übertriebene Zeit ist:

Sobald wir die Datenbank in Business Critical haben, werden wir die vorherigen Abfragen wiederholen. Im Falle der massiven Zählung(*) sinkt die Zeit von 70 Minuten des General Purpose auf 846 Sekunden, also 14 Minuten. Darüber hinaus können wir sehen, wie die CPU zu über 80% genutzt wird, während der Input/Output auf 30% sinkt, so dass das Gegenteil passiert, als im Fall des General Purpose:

Bei den 0,1%-Zählungen gingen wir von 52 Sekunden auf 9 Sekunden und im Falle von 1% von 411 Sekunden auf 36 Sekunden, so dass die Verbesserung sehr signifikant ist. In diesen speziellen Fällen sprechen wir über Verbesserungen zwischen 5 und 10 Mal, wenn wir auf Business Critical wechseln. Wenn wir die Operationen erneut ausführen, erhalten wir praktisch berechnete Zeiten, was eine gute Stabilität der Leistung in diesem Umfeld bedeutet.

Daraus können wir den Schluss ziehen, dass, wenn wir hohe Volumina haben, der Input/Output-Verbrauch wichtig ist und wir stabile Zeiten wollen, in denen der Business Critical viel ausgeglichener ist als der General Purpose.

Sobald uns diese Referenzen vorliegen, werden wir zu HyperScale übergehen. Es ist wichtig zu beachten, dass diese Änderung nicht umkehrbar ist, so dass wir später nicht wieder zu Business Critical oder General Purpose zurückkehren können.

Der Änderungsprozess dauerte etwa 2 Stunden, was ein Hinweis darauf sein kann, dass die Leistung möglicherweise schlechter ist als in Business Critical (wie die Preispositionierung selbst nahelegt):

Sobald wir die Skalierung vorgenommen haben, führen wir den ersten Count(*) zum ersten Mal auf HyperScale durch und erhalten eine Gesamtdauer von 3804 Sekunden. Dieser Wert liegt zwischen General Purpose (4179 Sekunden) und Business Critical (846 Sekunden), aber näher an der ersten Zeit. Unter Berücksichtigung der Architektur dieses Dienstes und der Existenz mehrerer Cache-Ebenen sollte es jedoch einen Unterschied geben, wann auf die Daten wieder zugegriffen werden muss. Wenn wir die Operation ein zweites Mal ausführen, sehen wir, dass die Ausführungszeit auf 1027 Sekunden sinkt, was diesmal viel näher an Business Critical liegt als bei General Purpose. Bei der dritten Ausführung sehen wir, dass sie sich in einer Umgebung von 1009 bis 1047 Sekunden bewegen, so dass wir die Zahl der zweiten Ausführung nicht wesentlich verbessern.

Wenn wir den CPU-Verbrauch analysieren, können wir sehen, wie deutlich der zweite Lauf höhere Nutzungsspitzen erzielt, indem er eine höhere Input-/Output-Leistung erzielt und damit die Gesamtlaufzeit reduziert wird:

Beachten Sie auch, dass die Metrik avg_data_io_percent aufgrund der entkoppelten Speicherung der Berechnung keine signifikanten „globalen“ Werte anzuzeigen scheint. Das heißt, es zeigt etwas an, aber nur lokal, den Teil der IO, der tempdb und dem lokalen Cache entspricht.

Leider haben wir auf der metrischen Ebene in Azure keine Informationen über Cache-Trefferquoten, wie viele Page-Server wir zu einem bestimmten Zeitpunkt haben, welche Größe jeder einzelne hat, usw..

Einige dieser Informationen können wir von den DMVs erhalten, insbesondere über dm_io_virtual_file_stats, wie in der Dokumentation angegeben (https://docs.microsoft.com/en-us/azure/sql-database/sql-database-HyperScale-performance-diagnostics):

select * from sys.dm_io_virtual_file_stats(0,NULL); -- Tempdb and local cache
select * from sys.dm_io_virtual_file_stats(db_id(),1); -- Data from Page Servers
select * from sys.dm_io_virtual_file_stats(db_id(),2); -- Log service 

Von diesen Daten ist die geringe Anzahl von Treffern im lokalen Cache (Zeile mit database_id=0 und file_id=0) bemerkenswert, so dass entweder diese Daten nicht korrekt sind oder der von uns geschätzte Performance-Vorteil über den lokalen Cache im Speicher plus den RBPEX-Cache der Auslagerungsserver selbst kommen muss.

Bei den Zeiten im Fall von Count(*) über 0,1% gingen wir von 52 Sekunden in General Purpose und 9 Sekunden in Business Critical auf 17 Sekunden in HyperScale, doppelt so lang wie Business Critical, aber weit entfernt von den 52 Sekunden in General Purpose. Bei der Zählung von über 1 % gingen wir von 411 Sekunden bei „General Purpose“ und 36 Sekunden bei „Business Critical“ auf 100 Sekunden bei „HyperScale“ über, wiederum in der Mitte, aber näher an „Business Critical“ als „General Purpose“.

In einem abschließenden Test wollten wir auch die Einfügezeiten vergleichen, die wir für jede der von uns in General Purpose geklonten Tabellen hatten, wobei jede Operation etwa 30 Sekunden erforderte, mit HyperScale sind es nur etwa 6-7 Sekunden. Es kann daher ein guter Anwendungsfall sein, wenn die Abholzungsgeschwindigkeit der anderen Alternativen gering ist:

SELECT * INTO SalesLT.SalesOrderDetailEnlarged_hyper FROM SalesLT.SalesOrderDetailEnlarged  
-- 30-35 sec GP
-- 6-7 sec HyperScale

Wir sehen, dass im Falle von HyperScale diese Log-Performance nicht durch die Anzahl der Kerne begrenzt ist, sondern ein konstantes Maximum darstellt, so dass bei intensiverer Schreiblast in einer Konfiguration mit wenigen vCores das Vorhersehbare in diesem Aspekt sogar Business Critical schlagen würde (es stimmt, dass es ein Aspekt ist, bei dem Business Critical lahm ist).

Schließlich sollten wir nicht vergessen, dass ein weiteres wesentliches Merkmal von HyperScale die Verwendung von Snapshots sowohl für Backups als auch für Wiederherstellungen ist. Wenn es sich um große Datenmengen handelt, macht diese Funktion einen großen Unterschied in der Zeit aus, die für die flexible Durchführung dieser Operationen benötigt wird.

Ein weiteres Merkmal, das in HyperScale besonders agil ist, ist die schnelle Skalierung nach oben oder unten im Vergleich zu anderen Alternativen. Zum Beispiel hat der Wechsel von 4 vCores zu 6 vCores dank dieser Trennung zwischen Berechnung und Daten einige Sekunden, nicht einmal eine Minute, benötigt, obwohl es sich um eine 400 GB große Datenbank handelt:

Zusammenfassend sind wir der Meinung, dass HyperScale einen sehr interessanten Mittelweg auf der Leistungsebene zwischen General Purpose und Business Critical darstellt. In den meisten Fällen ist die Leistung näher an Business Critical, und dennoch sind die Kosten viel näher an General Purpose. Vergessen wir nicht, dass wir damit eine Größe von bis zu 100 TB erreichen können, was deutlich über den 8 TB und 4 TB der anderen Alternativen liegt, so dass es möglicherweise die einzige PaaS-Option ist, wenn das zu verarbeitende Datenvolumen sehr hoch ist.

Wenn Sie eine Datenbank haben, die außer Kontrolle geraten ist, sowohl OLTP- als auch analytische Lasten unterstützt und Sie sie mit einer PaaS-Alternative modernisieren möchten, empfehlen wir Ihnen, ernsthaft einen Proof of Concept mit Azure SQL Database HyperScale in Betracht zu ziehen.

Rubén Garrigós
Rubén Garrigós, Mentor bei SolidQ

Ich bin ein Experte für hochverfügbare Unternehmenslösungen auf der Grundlage von SQL Server-Design, -Tuning und -Fehlerbehebung. In den letzten fünfzehn Jahren habe ich mit Datenzugriffstechnologien von Microsoft in führenden Unternehmen auf der ganzen Welt gearbeitet.

Heutzutage bin ich Microsoft SQL Server und .NET-Anwendungsarchitekt mit SolidQ. Ich bin von Microsoft als Lösungsexperte für die Microsoft Datenplattform (MSCE: Datenplattform) und als Lösungsexperte für die Microsoft Private Cloud (MSCE: Private Cloud) zertifiziert. Als Microsoft Certified Trainer (MCT) habe ich mehrere offizielle Microsoft-Kurse sowie andere Kurse mit dem Schwerpunkt SQL Server unterrichtet. Ich habe auch Sitzungen bei offiziellen Veranstaltungen für verschiedene Benutzergruppen von Microsoft-Technologien gehalten.