Dieser Artikel ist der Modernisierung von Microsoft SQL Server gewidmet und basiert auf einem Projekt, das Ispirer für ein großes Unternehmen im Bereich Finanzberatung durchgeführt hat. Der Kunde nutzte die Leistungsfähigkeit einer SQL Server-Datenbank, um die Finanzinformationen seiner Kunden effizient zu verwalten, zu verarbeiten, darauf zuzugreifen und zu überwachen. Ziel des Kunden war die Migration von SQL Server in die Cloud bei gleichzeitiger Optimierung der Systemarchitektur und der Wartungskosten.
Das Ispirer-Team bot an, die Geschäftslogik auf Java zu übertragen, da die Datenbank im OLTP-Modus verwendet wird. Wir werden das Thema sorgfältig analysieren und das Projekt des Kunden prüfen, bei dem es um die Konvertierung von SQL Server-Geschäftsregeln in Java geht. Darüber hinaus werden wir die Gründe untersuchen, warum sich Unternehmen für die Migration von SQL-Code auf eine Anwendungsschicht entscheiden. Dabei wird der gesamte Prozess umfassend untersucht.
Um die Kosten der Cloud-Infrastruktur zu optimieren, entschied sich der Kunde für die Migration von Tabellen und Daten nach PostgreSQL. Da wir auf Datenbank- und Anwendungsmigration spezialisiert sind, wandte sich der Kunde mit folgenden Aufgaben an uns:
Aufgrund des erheblichen Umfangs des Projekts war der Kunde bestrebt, die Migrationskosten durch die Implementierung von Automatisierung zu minimieren. Um die Effizienz des Ispirer Toolkits zu optimieren, haben wir beschlossen, dass seine Anpassung im Voraus durchgeführt werden sollte. Dieser Ansatz ermöglichte es uns, dem Team des Kunden ein Tool mit einer T-SCL-zu-Java-Konvertierungsrate von etwa 90 % bereitzustellen.
Lassen Sie uns nun tiefer in die Migration von Tabellen und Daten eintauchen.
Betrachten wir die Gründe, warum sich der Kunde für die Migration von einem lokalen SQL Server in die Cloud entschieden hat. Dieser Übergang bringt eine Reihe unbestreitbarer Vorteile mit sich:
Einsparmaßnahmen. Einer der Hauptgründe für die Migration von SQL Server zu PostgreSQL in der Cloud sind Kosteneinsparungen. Früher empfand der Kunde es als teuer, SQL Server-Datenbanken vor Ort zu halten. Dies war auf den Bedarf an Spezialausrüstung, Softwarelizenzen und qualifizierten Datenbankadministratoren zurückzuführen. PostgreSQL bietet als Open-Source-Datenbank eine kostengünstige Alternative. Kunden können durch die Nutzung der Cloud Geld sparen. Sie müssen nur für das bezahlen, was sie nutzen, anstatt hohe Vorauszahlungen zu leisten. Darüber hinaus können sie weniger für den Betrieb ausgeben.
Skalierbarkeit. Cloud Computing lässt sich einfacher skalieren als eine lokale Infrastruktur, um größere Arbeitslasten und mehr Benutzer zu bedienen. Damit ein lokales System mit den Anforderungen eines Unternehmens skaliert werden kann, mussten Unternehmen physische Server, Softwarelizenzen, Speicher und Netzwerkausrüstung erwerben und installieren, um Geschäftsdienste in herkömmlichen IT-Umgebungen zu skalieren. In der Cloud sind die meisten dieser Ressourcen sofort mit wenigen Klicks verfügbar und können je nach benötigten Ressourcen automatisch nach oben oder unten skaliert werden. PostgreSQL in der Cloud bietet ein hohes Maß an Skalierbarkeit, sodass unser Kunde seine Ressourcen je nach Bedarf problemlos anpassen kann.
Sicherheit. Der Einsatz der Cloud-Technologie bietet dank der fortschrittlichen Identitätskontrolle, Zugriffsverwaltung und Authentifizierungssysteme, die von Cloud-Anbietern bereitgestellt werden, erhebliche Sicherheitsvorteile. Oftmals verfügen Cloud-Anbieter über bessere Sicherheitsstandards als interne IT-Teams oder lokale Systeme, wodurch die Datenumgebung sicherer wird.
Eine starke Verschlüsselung in der Cloud verringert das Risiko von Datenschutzverletzungen. Es umfasst mehrschichtige Sicherheit, eine gute Schlüsselverwaltung und sichere Zugriffskontrollen, die Unternehmen dabei helfen, den Benutzerzugriff effektiv zu kontrollieren. Darüber hinaus überwachen Cloud-Anbieter den physischen Zugriff streng und implementieren Maßnahmen wie Anonymität, Replikation und Verschlüsselung, um den Datenschutz zu stärken. Bis 2025 werden voraussichtlich etwa 80 % der Unternehmen von physischen Rechenzentren auf Cloud-Dienste umsteigen. Diese Verschiebung wird durch die verbesserten Sicherheitsvorteile der Cloud vorangetrieben.
Der Wechsel von SQL Server zu PostgreSQL in der Cloud erfordert eine sorgfältige Planung und Ausführung unter Berücksichtigung spezifischer Überlegungen. Basierend auf dem Projekt des Kunden hat unser Team die folgenden Schritte zur Modernisierung von SQL Server hervorgehoben:
Schema- und Datentransformation. Daten sollten genau transformiert werden, um den Anforderungen von PostgreSQL zu entsprechen. Dies kann den Umgang mit Nuancen wie Datumsformaten und Zeichenkodierung beinhalten.
Einschränkungen und Auslöser. Es ist von entscheidender Bedeutung, die Unterschiede bei der Verwendung von Einschränkungen und Triggern in den beiden Datenbanken zu verstehen. Es ist erforderlich, die erforderlichen Änderungen entsprechend vorzunehmen. Darüber hinaus kann die Funktionalität von Triggern in die Anwendung verlagert werden. Diese Aufgabe ist jedoch alles andere als einfach, daher ist es wichtig, die Vor- und Nachteile abzuwägen.
Leistungsoptimierung. Durch die Optimierung des Migrationsprozesses können Ausfallzeiten und Datenübertragungszeiten minimiert werden. Für eine effiziente Migration ist es wichtig, Parallelisierung zu nutzen, die Netzwerkbandbreite zu optimieren und in leistungsstarke Hardware zu investieren
Datenvalidierung und -tests. Um die Integrität und Funktionalität der Daten zu gewährleisten, ist eine strenge Validierung der migrierten Daten erforderlich. Umfangreiche Tests stellen sicher, dass Anwendungen nahtlos mit der neuen PostgreSQL-Datenbank zusammenarbeiten.
Sicherheit und Berechtigungen. Sicherheitseinstellungen, Benutzerkonten und Berechtigungen in PostgreSQL sollten so konfiguriert werden, dass sie mit dem ursprünglichen SQL Server-Setup übereinstimmen, um einen nahtlosen Übergang zu gewährleisten.
In der Vergangenheit verwendeten unsere Kunden gespeicherte Prozeduren für ihre Geschäftslogik, weil sie dachten, dass dies die Leistung verbessern würde. Aber seien wir ehrlich: Im Vergleich zur Anwendungsschicht ist die SQL-Sprache möglicherweise nicht die optimale Wahl für die Unterbringung der Geschäftslogik.
Tatsächlich fragt SQL nur die Daten in einer Datenbank ab oder ändert sie. Hier können uns viele mit faulen Tomaten bewerfen, denn die SQL-Sprache ist gut darin, komplexe Verknüpfungen, Filterungen und Sortierungen durchzuführen, um aus einer Abfrage genau die Daten zu erhalten, die Sie benötigen, und nicht mehr. Warum dann etwas ändern und die Geschäftslogik auf die Anwendungsebene bringen?
Die Frage scheint logisch. Beantworten wir es genauer. Im Folgenden haben wir vier Hauptgründe aufgeführt, warum Sie ernsthaft darüber nachdenken sollten, Geschäftslogik in die Anwendung zu übertragen. Die Entscheidung des Kunden, die Geschäftslogik auf die Anwendungsebene zu verlagern, hatte folgende Gründe:
Aus Gründen der Skalierbarkeit ist die Speicherung der Geschäftslogik auf Anwendungsebene die beste Option. Warum? Denn im Allgemeinen ist es wesentlich einfacher, die Ressourcen Ihres Anwendungsservers zu skalieren als die Ressourcen Ihres Datenbankservers. Dies wird fast überall anerkannt. Bei den meisten Webanwendungen ist das Hinzufügen weiterer Server normalerweise einfach, wenn viel Datenverkehr zu bewältigen ist. Der Wert zusätzlicher Anwendungsserver verringert sich jedoch, wenn Ihre Datenbank nicht auch skaliert werden kann, um der gestiegenen Nachfrage gerecht zu werden. Die Skalierung eines Datenbankservers ist wesentlich anspruchsvoller als das einfache Hinzufügen von Anwendungsservern.
Das Speichern von Geschäftslogik in einer Datenbank kann zu Problemen bei der Wartbarkeit führen. Das Ändern gespeicherter Prozeduren kann viele Anwendungen stören, die Erweiterbarkeit einschränken und die Einhaltung des „Don't Repeat Yourself“-Prinzips (DRY) erschweren. SQL-Code, der mehr als 100 Zeilen umfasst, ist oft komplex und bereitet Schwierigkeiten bei der Fehlerbehebung. Die Trennung der Geschäftslogik in die Anwendungsebene kann den Einstieg neuer Teammitglieder erleichtern und bietet eine intuitivere Plattform für die Umgestaltung.
SQL ist eine schlechte Wahl für die Kodierung der Geschäftsregeln Ihres Systems. Es ist nicht flexibel und wir können uns nicht darauf verlassen, dass es komplexe Modelle darstellt, da es keine richtigen Abstraktionen erzeugen kann. Diese Einschränkung ist der Hauptgrund dafür, die Verwendung für die Geschäftslogik zu vermeiden. Dabei geht es nicht um Tools oder Support, sondern um die Unfähigkeit von SQL, ein einfaches und ausdrucksstarkes Domänenmodell zu erstellen, im Gegensatz zum objektorientierten und funktionalen Design, das mehr Möglichkeiten bietet.
In der Softwareentwicklung ist die Wiederverwendung von Code eine effiziente Möglichkeit, Zeit und Kosten zu sparen, wenn vorhandener Code für neue Aufgaben angepasst wird. Objektorientierte Programmierung (OOP) ist eine Methode, die das Code-Recycling erleichtert und ihn für verschiedene Anwendungen geeignet macht. Allerdings bietet SQL, das häufig in Datenbanken verwendet wird, eine begrenzte Flexibilität für die Wiederverwendung von Code. Zu den Optionen gehören die Verwendung von „Ansichten“ und „gespeicherten Prozeduren“, wobei letztere zu einer Fülle von Parametern führen können. Um die richtige Wahl für Ihr Projekt zu treffen, ist es wichtig, jede Methode gründlich zu untersuchen.
Die Konvertierung von Transact-SQL in Java erfordert verschiedene wesentliche Überlegungen. Der Prozess umfasst die Zuordnung von SQL-Datentypen zu ihren Java-Äquivalenten, um eine genaue Datendarstellung sicherzustellen. Dazu gehört auch die Übersetzung von SQL-Abfragen in Java-Code, wobei Java zur Abwicklung von Datenbankinteraktionen auf Bibliotheken wie JDBC oder Hibernate angewiesen ist. Darüber hinaus fehlen bestimmten ESQL-Funktionen direkte Entsprechungen in Java, was möglicherweise den Eindruck erweckt, dass die automatische Konvertierung ineffizient sei.
Während der Anpassungsphase unseres Projekts konnten wir eine Reihe von Konvertierungslösungen erstellen, die die Automatisierungsrate steigerten. Diese Lösungen, von denen zunächst angenommen wurde, dass sie nicht automatisierbar seien, erwiesen sich letztendlich als erfolgreich. Schauen wir uns einige davon im Detail an.
Konvertieren einer INSERT-Anweisung in Kombination mit SCOPE_IDENTITY(), um den letzten in eine Identitätsspalte eingefügten Identitätswert zu erhalten.
Quelle:
ALTER PROCEDURE example1 AS BEGIN Declare @idBit int Declare @c int Insert Into tab (c) Values (@c) Set @idBit = SCOPE_IDENTITY() End
Ziel:
@Service public class Example1 implements IExample1 { @Autowired private JdbcTemplate jdbcTemplate; private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Example1.class); @Override public Integer spExample1() throws SQLException, Exception { Integer mStatus = 0; KeyHolder keyHolder = new GeneratedKeyHolder(); try { Integer idBit = null; Integer c = null; { final Integer tmpC = c; jdbcTemplate.update(connection-> { PreparedStatement ps = connection.prepareStatement("Insert Into tab(c) \r\n" + " Values(?)", new String[] { "" }); ps.setInt( 1, tmpC); return ps; }, keyHolder); } idBit = Tsqlutils.<Integer > strToNum(keyHolder.getKey().toString(), Integer.class); return mStatus; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return mStatus; } } }
Quelle:
ALTER PROCEDURE [returnSeveralResultSet] @p1 int, @p2 varchar(50) AS Begin select cob_ft, lower(buzon) from tab1 where cob_id = @p1 and cob_ft = @p2 select dep_ft, lower(fiton) from tab2 END
Ziel:
@Service public class Returnseveralresultset implements IReturnseveralresultset { @Autowired private JdbcTemplate jdbcTemplate; private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Returnseveralresultset.class); private Integer errorCode = 0; private String sqlState = ""; @Override public Map<String, Object> spReturnseveralresultset(Integer p1, String p2) throws Exception { Integer mStatus = 0; Map<String, Object> outData = new HashMap<>(); List<SqlRowSet> outRsList = new ArrayList<>(); SqlRowSet rowSet; try { rowSet = jdbcTemplate.queryForRowSet("select cob_ft, lower(buzon) from tab1 \r\n" + " where cob_id = ? and cob_ft = ?", p1, p2); outRsList.add(rowSet); rowSet = jdbcTemplate.queryForRowSet("select dep_ft, lower(fiton) from tab2"); outRsList.add(rowSet); return outData; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return outData; } finally { outData.put("status", mStatus); outData.put("rsList", outRsList); } } }
Quelle:
create procedure datediffFn as declare @var1 int set @var1 = DATEDIFF(dd, '1999-01-01', '2000-02-01') set @var1 = DATEDIFF(mm, getdate(), '2000-02-01') set @var1 = DATEDIFF(week, '2005-12-31 23:59:59.9999999', '2006-01-01 00:00:00.0000000');
Ziel:
public Integer spDatedifffn() throws Exception { Integer mStatus = 0; try { Integer var1 = null; var1 = Tsqlutils.datediff("dd", Tsqlutils.toTimestamp("1999-01-01"), Tsqlutils.toTimestamp("2000-02-01")); var1 = Tsqlutils.datediff("mm", new Timestamp(new java.util.Date().getTime()), Tsqlutils.toTimestamp("2000-02-01")); var1 = Tsqlutils.datediff("week", Tsqlutils.toTimestamp("2005-12-31 23:59:59.9999999"), Tsqlutils.toTimestamp("2006-01-01 00:00:00.0000000")); return mStatus; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return mStatus; } }
Quelle:
create PROCEDURE spSendDbmail AS BEGIN EXEC msdb.dbo.sp_send_dbmail @profile_name = 'New DB Ispirer Profile', @recipients = '[email protected]', @body = '<h1>This is actual message embedded in HTML tags</h1>', @subject = 'Automated Success Message' , @file_attachments = 'C:\Temp\Attached.txt', @body_format='HTML', @copy_recipients = '[email protected]', @blind_copy_recipients = '[email protected]'; END
Ziel:
import java.util.*; import com.ispirer.mssql.mail.MailService; public class Spsenddbmail { private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Spsenddbmail.class); public Integer spSpsenddbmail() throws Exception { Integer mStatus = 0; try { MailService.send("New DB Ispirer Profile", "Automated Success Message", "<h1>This is actual message embedded in HTML tags</h1>", "[email protected]", "[email protected]", "[email protected]", "C:\\Temp\\Attached.txt", "HTML"); return mStatus; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return mStatus; } } }
Quelle:
create procedure workWithXml AS begin declare @result bit, @myDoc XML, @myStr varchar(1000), @ProdID INT SET @myDoc = '<Root> <ProductDescription ProductID="1" ProductName="Road Bike"> <Features> <Warranty>1 year parts and labor</Warranty> <Maintenance>3 year parts and labor extended maintenance is available</Maintenance> </Features> </ProductDescription> </Root>' SET @result = @myDoc.exist('(/Root/ProductDescription/@ProductID)[1]') SET @myStr = cast(@myDoc.query('/Root/ProductDescription/Features') as varchar(max)) SET @ProdID = @myDoc.value('(/Root/ProductDescription/@ProductID)[1]', 'int' ) end;
Ziel:
import java.util.*; import com.ispirer.mssql.xml.XMLUtils; public class Workwithxml { private static final org.slf4j.Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Workwithxml.class); public Integer spWorkwithxml() throws Exception { Integer mStatus = 0; try { Boolean result = null; String myDoc = null; String myStr = null; Integer prodID = null; myDoc = "<Root> " + "<ProductDescription ProductID=\"1\" ProductName=\"Road Bike\"> " + "<Features> " + "<Warranty>1 year parts and labor</Warranty> " + "<Maintenance>3 year parts and labor extended maintenance is available</Maintenance> " + "</Features> " + "</ProductDescription> " + " </Root>"; result = XMLUtils.exist(myDoc, "(/Root/ProductDescription/@ProductID)[1]"); myStr = XMLUtils.query(myDoc, "/Root/ProductDescription/Features"); prodID = XMLUtils.<Integer > value(myDoc, "(/Root/ProductDescription/@ProductID)[1]", Integer.class); return mStatus; } catch (Exception e) { LOGGER.error(String.valueOf(e)); mStatus = -1; return mStatus; } } }
Dank unserer Anpassungsbemühungen hat unser Team erfolgreich eine Reihe von Techniken entwickelt, um den Übergang von T-SQL zu Java zu automatisieren. Dadurch wurde die Gesamtmigrationszeit für das gesamte Projekt erheblich verkürzt, sodass wir die Migration im Vergleich zu einer möglichen manuellen Migration um das Vierfache beschleunigen konnten. Unsere Toolkit-Anpassung hat nicht nur den Übergang beschleunigt, sondern auch die Gesamteffizienz des Projekts verbessert und die wertvolle Wirkung unserer Anpassungsinitiativen deutlich gemacht. Die in den Beispielen angegebenen Methoden werden dem Kunden zusammen mit den Konvertierungsergebnissen zur Verfügung gestellt.
Zusammenfassend lässt sich sagen, dass die Umstellung der Geschäftslogik von Transact-SQL auf Java ein vielschichtiger Prozess ist, der ein umfassendes Verständnis beider Sprachen und ihrer unterschiedlichen Funktionen erfordert.
In diesem Artikel haben wir die Migration der Geschäftslogik auf eine App-Ebene ausführlich untersucht und wertvolle Erkenntnisse für diejenigen bereitgestellt, die einen solchen Übergang planen. Der Fall unseres Kunden beweist, dass solche Modernisierungsprojekte automatisiert werden können, was bei der Migration erheblich Zeit und Aufwand spart. Das Projekt unseres Kunden ist ein überzeugender Beweis für das bemerkenswerte Potenzial der Automatisierung. Es zeigt, dass es Modernisierungsaspekte gibt, in denen die Automatisierung Prozesse erfolgreich rationalisieren kann, die zunächst möglicherweise über ihre Möglichkeiten hinausgehen.
Letztendlich ist die Migration von Transact-SQL zu Java ein strategischer Schritt für Unternehmen, die mehr Flexibilität, plattformübergreifende Kompatibilität und Skalierbarkeit anstreben. Auch wenn es einige Herausforderungen mit sich bringt, machen die Vorteile in Bezug auf Portabilität, Leistung und Anpassungsfähigkeit an moderne Softwarearchitekturen diesen Übergang zu einem lohnenswerten Unterfangen für diejenigen, die ihre Datenbanksysteme und -anwendungen modernisieren möchten.