DB für CRM



  • [quote="hustbaer"]

    wtfwpf schrieb:

    Datenbanken können nicht zaubern.

    Da ist mir grad eine Software eingefallen, über die es mal eine Kurznotiz in der c´t gab. Die wird als Datenbanktreiber angesprochen und fungiert als Proxy zur richtigen Datenbank. Dabei führt sie Statistiken über die Anfragen und kann sie mit der Zeit optimieren. Da stand was von bis zu Faktor 1000. Das Teil war glaub ich sauteuer.
    Wohl auch so ein Tool, um ganz schlecht programmierte Datenbankanwendungen nachträglich zu verbessern. Wobei ich mir auch nicht so ganz vorstellen kann, wie das funktioniert. Der Proxy müsste zumindest zusätzliche Indexe anlegen können, und ob er das kann/darf ging da nicht so wirklich hervor.



  • Ich stimme nman voll und ganz zu. PostgreSQL ist grossartig. Es ist einfach in jeder Hinsicht besser als MySQL. Es ist kostenlos und auf allen relevanten Plattformen verfügbar.

    Sqlite ist für kleine Sachen auch sehr gut geeignet. Es ist halt sehr einfach zu administrieren.

    Wenn beim Kunden MS-SQL im Einsatz ist, ist das allerdings das Killerargument. Keine andere Datenbank ist so viel besser oder schneller als MS-SQL, dass sich ein Umstieg wirklich lohnen würde.

    Ansonsten: immer schön Datenbankneutral programmieren. Dann kann man die Datenbank später zur Not auch austauschen.



  • tntnet schrieb:

    Ansonsten: immer schön Datenbankneutral programmieren. Dann kann man die Datenbank später zur Not auch austauschen.

    Ich glaube dazu muss man mindestens Tests (Unit-Tests, Integrationstests, ...) mit einer zweiten DB machen. Sonst stehen die Chancen wohl sehr schlecht dass man später noch einfach umsteigen kann.
    (OK, ein Tool das alle SQL Statements prüft und meldet sobald ein non-Standard Feature verwendet wird würde vermutlich auch reichen - weiss nicht ob es so etwas gibt.)



  • Es muss ja nicht mal komplett datenbankneutral sein. Ich hätte oftmals auch keine Lust, auf datenbankspezifische Features zu verzichten. Aber man braucht eine Zwischenschicht für die Datenbankzugriffe. Dann kanns von mir aus eine Implementierung für den MS-SQL, für Orace und für PostgreSql geben. In der jeweiligen Schicht kann man dann auch spezielle Features benutzen, um die Performance usw. zu verbessern.



  • Ich verstehe das Problem nicht so ganz. Ich kenne SQL und weiss, was ich damit machen kann. Und meine SQL-Abfragen sind praktisch immer Datenbankneutral.

    Welche Features nutzt ihr denn, welches sich mit Standard-SQL nicht abbilden lässt?

    Mag sein, dass man mit speziellen Features noch mal ein wenig Performance raus holen kann, aber in der Regel ist das nicht so viel, dass es relevant wäre.

    Die Datentypen sind in den Datenbanken unterschiedlich. Da hat man dann verschiedene DDLs für die einzelnen Datenbanken, aber der Applikation selbst sollte das nichts ausmachen.



  • Ich hab grad kein konkretes Beispiel. Geht auch nicht unbedingt um einfache Queries. Aber z.B. so Sachen wie Volltextsuche, temporäre Tabellen, hierarchische Daten vom Sql Server usw. Dann vielleicht ein bisschen Logik in Triggern und Stored Procedures implementieren. Kann sich durchaus lohnen.



  • tntnet schrieb:

    Welche Features nutzt ihr denn, welches sich mit Standard-SQL nicht abbilden lässt?

    * Clustered Indexes sind soweit ich weiss nicht Standard SQL
    * Filtered Indexes ebenso
    * Rekursive Common Table Expressions sind zwar IIRC Standard, werden aber nicht von allen DBs unterstützt
    * Join Hints
    * Optimizer Hints (Angabe von Indexen die verwendet werden sollen, "FAST TOP 1" etc.)
    "WITH (NOEXPAND)" ist IIRC z.B. nicht Standard, auf MS-SQL Standard-Edition aber nötig wenn man möchte dass der Optimizer Indexe von Indexed-Views verwendet (die Enterprise-Edition hat das Optimizer-Feature "automatisch gucken ob es einen verwendbaren Indexed-View Index gibt" im Gegensatz zur Standard-Edition dann nicht gesperrt, wodurch die Notwendigkeit für "WITH (NOEXPAND)" dort dann wegfällt).
    * XML Spalten (mit XML Indexen, XPath Queries etc.)
    * Unterschiedliche Syntax die nötig ist wenn man performant aus einem Batch heraus viele Zeilen auf einmal einfügen will
    * Unterstützte Parametertypen bei parametrisierten Prepared Statements (z.B. gibt es AFAIK DBs die Arrays unterstützen ala "WHERE x IN @param")

    Das sind so die Dinge die mir spontan einfallen. Einige davon mögen standardisiert sein, so genau kenne ich den Standard dann auch nicht. Einige davon sind es sicher nicht. Nützlich können sie in den verschiedensten Situationen alle sein.

    Bei den etwas "spezielleren" Datentypen bzw. auch Funktionen gibt es auch immer wieder Dinge die auf verschiedenen DBs unterschiedlich funktionieren. Und da muss man nichtmal exotisch werden, ISNULL/COALESCE (T-SQL) vs. NVL (Oracle) vs. ISNULL (MySql - heisst gleich, tut aber anders als T-SQL ISNULL). Oder T-SQL's CONVERT.



  • @Mechanics
    Klar muss es nicht der selbe Code sein. Ich wollte damit nur sagen: Wenn man seine Applikation "neutral" halten will, oder auch nur die 2-3 wichtigsten DBs unterstützen will, dann muss man die auch von Anfang an alle testen. Oder spätestens zu dem Zeitpunkt wo man ein 2. System unterstützen muss, eine Testbatterie aufbauen, mit der man möglichst 100% "SQL Coverage" hat. Weil man sonst nie sichergehen kann dass auch wirklich alle SQL Statements die in der Applikation vorkommen auch auf allen DBs laufen.

    Zumindest wenn man Entwickler hat die mehr als Standard SQL können, und z.T. gar nicht wissen was alles non-Standard Erweiterungen "ihres" Systems sind. Bzw. was alles Standard SQL Syntax ist die aber von alternativen Systemen unter Umständen nicht gefressen wird. Und wenn SQL - wie ich vermute - oft "on the job" gelernt wird, dann wird es sehr viele solche Entwickler geben. Denn was schert es mich, wenn ich Feature A mit SQL-DB X implementieren muss, was SQL-DB Y oder Z dazu sagen.

    Wenn dagegen für jedes SQL Statement das ich schreibe ein Test geschrieben wird, weil es das Feature sonst nicht durchs Review schafft, dann schert es mich. Und dann kann man die Applikation auch mehr oder weniger "DB-neutral" halten.

    Bzw. wenn trotz Test-Case erstmal nur eine DB supported werden muss, dann kann man später relativ problemlos Support für weitere DBs dazubasteln. Weil man einfach nur gucken muss dass alle Tests fehlerfrei durchlaufen. Die paar Bugs die dann trotzdem noch übrig bleiben, weil halt keine Testbatterie wirklich alle denkbaren Fälle abdecken wird, kann man dann in Revisions/Hotfixes beheben. Wenn es dagegen keine solche Testbatterie gibt, dann müsste man alles mit Hand testen. Und zu dem Zeitpunkt wo das 2. DB System dazukommt kann die Software leicht schon so gross sein, dass das ... ziemlich aufwendig würde.



  • hustbaer schrieb:

    tntnet schrieb:

    Welche Features nutzt ihr denn, welches sich mit Standard-SQL nicht abbilden lässt?

    * Clustered Indexes sind soweit ich weiss nicht Standard SQL
    * Filtered Indexes ebenso
    * Rekursive Common Table Expressions sind zwar IIRC Standard, werden aber nicht von allen DBs unterstützt
    * Join Hints
    * Optimizer Hints (Angabe von Indexen die verwendet werden sollen, "FAST TOP 1" etc.)
    "WITH (NOEXPAND)" ist IIRC z.B. nicht Standard, auf MS-SQL Standard-Edition aber nötig wenn man möchte dass der Optimizer Indexe von Indexed-Views verwendet (die Enterprise-Edition hat das Optimizer-Feature "automatisch gucken ob es einen verwendbaren Indexed-View Index gibt" im Gegensatz zur Standard-Edition dann nicht gesperrt, wodurch die Notwendigkeit für "WITH (NOEXPAND)" dort dann wegfällt).
    * XML Spalten (mit XML Indexen, XPath Queries etc.)
    * Unterschiedliche Syntax die nötig ist wenn man performant aus einem Batch heraus viele Zeilen auf einmal einfügen will
    * Unterstützte Parametertypen bei parametrisierten Prepared Statements (z.B. gibt es AFAIK DBs die Arrays unterstützen ala "WHERE x IN @param")

    Das sind so die Dinge die mir spontan einfallen. Einige davon mögen standardisiert sein, so genau kenne ich den Standard dann auch nicht. Einige davon sind es sicher nicht. Nützlich können sie in den verschiedensten Situationen alle sein.

    Bei den etwas "spezielleren" Datentypen bzw. auch Funktionen gibt es auch immer wieder Dinge die auf verschiedenen DBs unterschiedlich funktionieren. Und da muss man nichtmal exotisch werden, ISNULL/COALESCE (T-SQL) vs. NVL (Oracle) vs. ISNULL (MySql - heisst gleich, tut aber anders als T-SQL ISNULL). Oder T-SQL's CONVERT.

    Im wesentlichen sind das doch Optimierungssachen. Und die verwendet man erst, wenn es wirklich notwendig ist. Und auch dann muss man abwägen, ob der Performancegewinn wirklich notwendig ist oder ob Portabilität wichtiger ist.

    Ich glaube, da hört meine spezifischen Kenntnisse über die Datenbanken auf, daher frage ich doch mal.

    Ein clustered Index taucht doch in einer SQL-Abfrage nicht auf? Oder ein filtered Index? Da ergibt sich in der Applikation also kein Kompatibilitätsproblem.

    Optimizer hints braucht man in der Regel nicht. Die Datenbank optimiert in aller Regel sehr gut, bzw. gut genug.

    In NVL oder ähnlichen Funktionen sehe ich keinen wirklichen Sinn. Das kann man problemlos in der Applikation behandeln.

    XML Spalten (oder JSON) kann man verwenden. Muss man aber nicht. Ich bevorzuge, solche Sachen in der Applikation zu behandeln. Eine normalisierte relationale benötigt das eigentlich nicht.

    Massendaten laden ist sicher eine Sache, die spezifisch ist. Aber das wird man in der Regel nicht aus einer "normalen" Applikation machen.

    Parametrisierten prepared statements mit arrays sind sicher nett. Aber auch das kann man relativ leicht in der Applikation behandeln, indem man die Statements doch dynamisch zusammen baut. Sicher geht da ein wenig Performance verloren. Aber wieder muss man abwägen, ob die Portabilität nicht höher wiegt.

    Ach ja - stored procedures: Ich implementiere meine Applikationslogik lieber in der Applikation als in der Datenbank. Da gehört sie hin. Auch hier ist natürlich eine stored procedure möglicherweise einen Tick schneller. Aber wieder muss man fragen, ob es sich wirklich lohnt.



  • tntnet schrieb:

    Im wesentlichen sind das doch Optimierungssachen. Und die verwendet man erst, wenn es wirklich notwendig ist. Und auch dann muss man abwägen, ob der Performancegewinn wirklich notwendig ist oder ob Portabilität wichtiger ist.

    Die meisten Sachen: ja.
    Bestimmte Dinge sind aber unglaublich praktisch, sparen also auch ordentlich Code. z.B. Arrays als Parameter übergeben zu können.
    Bei anderen Dingen ist der Performance-Gewinn den man hat schnell mal Faktor 100 oder 1000 - z.B. beim Einfügen mehrerer Zeilen auf einmal mit MS-SQL. Das kann man dann oft nicht vernachlässigen.

    tntnet schrieb:

    Ich glaube, da hört meine spezifischen Kenntnisse über die Datenbanken auf, daher frage ich doch mal.

    Ein clustered Index taucht doch in einer SQL-Abfrage nicht auf? Oder ein filtered Index? Da ergibt sich in der Applikation also kein Kompatibilitätsproblem.

    In Abfragen nicht, aber natürlich im DDL. Je nachdem wie die Applikation installiert bzw. upgedated wird sind solche Statements dann auch in der Applikation selbst zu finden.

    Und die Verfügbarkeit bzw. Nichtverfügbarkeit dieser Features verändert was man machen kann und was nicht. Bei einer DB die wie SQLite nur Nested Loops Joins kann, kann man bestimmte Abfragen auf bestimmte Tabellen mit bestimmten Inhalten einfach nicht machen (also nicht wenn man will dass sie auch irgendwann fertig werden). Wenn der Server dagegen Merge und/oder Hash Joins kann, dann kann man sie machen.
    Ähnlich, wenn auch nicht ganz so krass, verhält es sich mit Clustered-Indexes oder Filtered-Indexes.

    tntnet schrieb:

    Optimizer hints braucht man in der Regel nicht. Die Datenbank optimiert in aller Regel sehr gut, bzw. gut genug.

    Optimizer Hints braucht man nicht, so lange bis man sie eben doch braucht. Ich hab' einige Fälle erlebt wo der Optimizer einfach hin und wieder beschlossen hat "ab jetzt verwende ich einen anderen Plan", und dieser andere Plan hat dann SO viel länger gedauert dass ab da alle Clients in ein Timeout gelaufen sind, und im Prinzip nichts mehr gegangen ist. Nen genauen Slowdown-Faktor kann ich dir nicht sagen, aber in dem einen Fall sind Abfragen die davor so 1-2 Sekunden gedauert haben danach in ein Timeout gelaufen. Welches IIRC auf mehrere Minuten (schätze 5-10) eingestellt war. Also wirklich massiv, nicht "wir stellen nen schnelleren Server hin und gut".
    Dann schreibt man 'nen Optimizer Hint rein.

    tntnet schrieb:

    In NVL oder ähnlichen Funktionen sehe ich keinen wirklichen Sinn. Das kann man problemlos in der Applikation behandeln.

    Nicht wenn du es für z.B. nen JOIN brauchst. Bzw. auch bei Gruppierung oder in Aggregatfunktionen. Klar, man kann in der Applikation gruppieren und aggregieren etc., aber wieso etwas mühsam in C++/C#/Java ausprogrammieren was in SQL 2 Zeilen sind?
    Gut, in C# wäre es dank LINQ auch nicht SO viel mehr Aufwand. In C++ würde ich aber ordentlich fluchen.

    tntnet schrieb:

    XML Spalten (oder JSON) kann man verwenden. Muss man aber nicht. Ich bevorzuge, solche Sachen in der Applikation zu behandeln. Eine normalisierte relationale benötigt das eigentlich nicht.

    Wenn man sehr unterschiedliche Daten zu Objekten ablegen muss, sind XML Spalten praktisch. Klar kann man das alles in ein normalisiertes Modell aufdröseln, aber oft steht der Aufwand nicht dafür. Zumindest nicht wenn man ein DBMS verwendet das XML Spalten kann. In der Applikation kann man es machen, ja, aber nur wenn man nicht per Index in diesen XML-Schnippeln suchen muss. SQL Server kann das nämlich schön über nen XML-Index optimieren -- in der Applikation müsste man dafür nen Table-Scan machen. Oder nen externen XML-Index pflegen. Also entweder miese Performance oder wieder deutlicher Mehraufwand.

    tntnet schrieb:

    Parametrisierten prepared statements mit arrays sind sicher nett. Aber auch das kann man relativ leicht in der Applikation behandeln, indem man die Statements doch dynamisch zusammen baut. Sicher geht da ein wenig Performance verloren. Aber wieder muss man abwägen, ob die Portabilität nicht höher wiegt.

    Ja klar muss man das abwägen. Ich sag' ja nicht dass Portabilität nicht wichtig ist. Ich sag' nur dass man Portabilität kaum erreichen kann wenn man sie nicht vorab testet. Weil es eben zu viele praktische Dinge gibt die sonst einfach verwendet werden.

    So lange man alleine programmiert und selbst nicht in die Versuchung kommt non-Standard Sachen zu verwenden, und gut genug weiss welche Standard Features auch wirklich portabel sind (was ja wie gesagt nicht auf alle zutrifft), wird es kein Problem sein. Bei grösseren Projekten wo Entwickler kommen und gehen, und wo es keine dahingehenden Tests gibt, schätze ich die Chance dass sich keine nicht-portablen Konstrukte einschleichen aber sehr gering ein. Das wollte ich sagen. Nicht mehr und nicht weniger. 🙂


Anmelden zum Antworten