Varchar als Foreignkey/Primary Key



  • Sind eure DB-Operationen CPU-Bound? Wird die meiste Zeit in Join Operatoren verbraten? Dann könnte es leicht sein dass ein Wechsel von varchar(20) zu int für die Keys was bringt.

    Wenn die DB-Operationen eher Disk-Bound sind, dann wirst du vermutlich fast nix rausholen können.



  • witte schrieb:

    Mir ist nicht ganz klar ob Datenbank-NF verletzt wurden oder ob du einfach den Datentyp varchar als Primkey "verabscheust". Ich würde in dem Fall die Tabellen nicht leichtfertig ändern sondern erst prüfen ob es wirklich was bringt.
    Ich kenne mich mit Sybase nicht aus aber die werden doch sicherlich auch 64b-Generatoren besitzen. Das sollte doch wohl reichen. Alternativ kannst du auch GUID's verwenden, die vllt eine Stored Function bereitstellt.

    Also die Tabelle Dataset hat ein Feld, welches den Namen enthält, Primary Key, unique.
    Die Tabelle XYZ hat dann ein Feld fkDatasetid varchar(20) mit dem Namen.
    Das könnte man schon als leichte Verletzung der Normalform ansehen.

    Generatoren oder solche Dinge kennt Sybase afaik nicht, zumindest in der Version 12.5, welche hier eingesetzt wird.
    Es gibt nur IDENTITY, eine art Autoincrement, welches eine id in Form von numeric(x,0) zur Verfügung stellt.
    Problem ist hier höchstens, das diese Sequenz natürlich endlich ist.

    Ob CPU gebunden oder IO gebunden ist eine gute Frage. Ich denke beides ist der Fall.
    Gerade bei den Importen stelle ich mir ein UPDATE XYZ SET a=b,d=c,u=v WHERE datasetid='MyDataSetId42' suboptimal vor, trotz Index und PK auf diese Spalte.
    SELECTs und andere Operationen kommen natürlich noch hinzu.

    Und da das hier so riesig ist, und die DB natürlich schon ein paar Jahre in Produktion läuft, muss man wohl sehen das wenn überhaupt man erst ein hybrides System hat, was beides beinhaltet, und nur die neuen Tabellen ohne das varchar Feld auskommen können durch die ID.



  • Ob CPU gebunden oder IO gebunden ist eine gute Frage. Ich denke beides ist der Fall.

    Nachsehen?
    Lass dir am DB-Server ein paar Performance-Counter mitschreiben oder wenigstens anzeigen: CPU-Auslastung und Disk-Queue-Depth.

    Dann sorg dafür dass ordentlich Last auf den Server kommt - viele Anfragen gleichzeitig starten oder so.

    Wenn die Disk-Queue-Depth im Schnitt > 1 ist dann sind die Abfragen vermutlich Disk-Bound. Wenn die CPU Auslastung nahe 100% kommt dann sind sie CPU-Bound.

    Anderer Vorschlag: erschlagt das Problem doch mit schnellerer Hardware statt viel Zeit (und Geld) in diverse Optimierungs-Versuche zu investieren.



  • hustbaer schrieb:

    Ob CPU gebunden oder IO gebunden ist eine gute Frage. Ich denke beides ist der Fall.

    Nachsehen?
    Lass dir am DB-Server ein paar Performance-Counter mitschreiben oder wenigstens anzeigen: CPU-Auslastung und Disk-Queue-Depth.

    Dann sorg dafür dass ordentlich Last auf den Server kommt - viele Anfragen gleichzeitig starten oder so.

    Wenn die Disk-Queue-Depth im Schnitt > 1 ist dann sind die Abfragen vermutlich Disk-Bound. Wenn die CPU Auslastung nahe 100% kommt dann sind sie CPU-Bound.

    Anderer Vorschlag: erschlagt das Problem doch mit schnellerer Hardware statt viel Zeit (und Geld) in diverse Optimierungs-Versuche zu investieren.

    Also zunächst, auch ich bin kein Sybase DBA, für mich ist Sybase auch Exot was DBs angeht.
    Gerade exotischer wird es auch dadurch das das System auf Hard und Software läuft, die schon relativ alt ist.

    Was last angeht: so richtig belastet wird die Datenbank wohl eher nicht, das Programm hat wenige User, und die DB läuft auf einer Solarismaschine.
    Die Last entsteht wenn überhaupt durch die Importmengen und das alter der Hardware.
    Habe aber dazu keine Kenntnisse, wir entwickeln hier nur, Kunde ist eine andere große Firma...
    Die Datenbank enthält wohl je nach Tabelle zwischen 200000 und 600000 Datensätze ca.

    Aber zurück zum Thema:
    Leider findet man so gut wie nichts über die Effektivität von varchars als Indexe, jede Sache zu Relationen in Datenbanken verwendet hier numerische Ids, solange man beispiele etc. sucht.
    Zu PKs habe ich einige Dinge finden können, aber auch hier kein Vergleich für Performance.
    Stellt sich für mich die Frage, wie wichtig ist für den Index der Datentyp des Quellfeldes überhaupt?



  • @Solarisguy:
    Ich kann dir leider auch keine passenden Links geben.

    Ich persönlich *schätze*, dass es bei den meisten Anwendungen egal sein wird, ob man Strings oder Integers als Keys verwendet, so lange die Strings halbwegs kurz bleiben.

    Doof wäre wenn die Strings relativ lange sind, da dadurch ein Index auf das entsprechende Feld entsprechend grösser wird. Dadurch müssen mehr Daten gelesen/geschrieben werden, und dadurch können weniger Zeilen eines Index im Cache gehalten werden. Beides Dinge die Performance kosten.

    Andrerseits...

    Du hast vorhin schon was von Normalisierung geschrieben. Ein String als Key ist nicht immer gleich ein Verstoss gegen eine Normalform. (Und selbst wenn, könnte man diesen Verstoss nicht einfach dadurch entfernen, indem man eine numerische ID einführt, und den String dann in einem Lookup-Table (ID, String) ablegt.)
    Es spricht nichts dagegen dass Keys eine Bedeutung haben (also keine sog. Surrogate-Keys sind).
    Was du bedenken solltest: wenn du den String-Key durch eine numerische ID + Lookup-Table ersetzt, dann werden einige Abfragen dadurch vielleicht schneller, weil die numerische ID weniger Platz braucht und weniger CPU Zeit bei Vergleichen.
    Andere Abfragen könnten aber langsamer werden, dadurch dass ein zusätzlicher JOIN ausgeführt werden muss.

    Zuletzt nochmal wegen Hardware: falls Bedenken bei neuer Hardware bestehen was Kompabilität etc. angeht wäre hier vielleicht VMware ein möglicher Ausweg. VMware kompatible Hardware gibt es wie Sand am Meer. Fall es sich um Solaris 9 oder 10 handelt, wäre das eine Option (Solaris 8 wird von VMware nicht unterstützt). Dummerweise gibt es keine P2V Tools die speziellen Support für Solaris drin haben, aber mit etwas Glück kannst du ein Disk-Image der physischen Maschine 1:1 in VMware booten.

    p.S.: Solaris 8 geht anscheinend doch irgendwie...



  • hustbaer schrieb:

    Ich persönlich *schätze*, dass es bei den meisten Anwendungen egal sein wird, ob man Strings oder Integers als Keys verwendet, so lange die Strings halbwegs kurz bleiben.

    Naja, es ist nur ein varchar. Trotzdem denke ich das eine numerische ID einfach besser von der Performance sein sollte.
    Das Blöde ist halt, das es nicht möglich ist, das mal eben auszutauschen, da hängt sehr viel dran.

    hustbaer schrieb:

    Doof wäre wenn die Strings relativ lange sind, da dadurch ein Index auf das entsprechende Feld entsprechend grösser wird. Dadurch müssen mehr Daten gelesen/geschrieben werden, und dadurch können weniger Zeilen eines Index im Cache gehalten werden. Beides Dinge die Performance kosten.

    Das ist halt die Frage, wie das auf so einer alten DB ist. Ein IDENTITY Feld mit numeric(6,0) würde ich auf 4-8Byte schätzen, gegen die meisten varchars ist das dann schon ein Unterschied.
    Andererseits scheint es auch keine großen Tabellen (> 1 Million Datensätze) in der DB zu geben.

    hustbaer schrieb:

    Du hast vorhin schon was von Normalisierung geschrieben. Ein String als Key ist nicht immer gleich ein Verstoss gegen eine Normalform. (Und selbst wenn, könnte man diesen Verstoss nicht einfach dadurch entfernen, indem man eine numerische ID einführt, und den String dann in einem Lookup-Table (ID, String) ablegt.)
    Es spricht nichts dagegen dass Keys eine Bedeutung haben (also keine sog. Surrogate-Keys sind).
    Was du bedenken solltest: wenn du den String-Key durch eine numerische ID + Lookup-Table ersetzt, dann werden einige Abfragen dadurch vielleicht schneller, weil die numerische ID weniger Platz braucht und weniger CPU Zeit bei Vergleichen.
    Andere Abfragen könnten aber langsamer werden, dadurch dass ein zusätzlicher JOIN ausgeführt werden muss.

    Da es sowieso eine Hybridlösung nur sein kann, wären die alten Abfragen nicht wirklich betroffen, neue Tabellen würden dann aber über einen Numerischen Index zugreifen. Und ich sehe es schon als Verletzung der Normalform an, wenn ein String überall dupliziert wird. In der einen Tabelle legen wir Datensätze an, und in einer weiteren legen wir dann Messdaten dazu ab, und als Fremdschlüssel dient dann der Name des Datensatzes.

    Ich habe gestern mal einen kleinen Test gemacht, und siehe es ist interessant:
    Ein Datensatz welcher als namen nur einen Buchstaben hat, wird 10-20 Sekunden schneller importiert, so zumindest die ersten Messungen dazu.

    Zur Zeit ist in meinem Testfall es so, das der Import für eine kleine Testdatei (150mb) in einen neuen Datensatz 170000 Inserts auslöst, verteilt auf ca. 10 Tabellen. Bei jedem Insert wird nun jeweils auch der Name des Datensatzes mit übergeben, ebenso bei jedem UPDATE, SELECT, DELETE etc.
    Offiziell unterstützen müssen wir Dateien bis 500 mb.

    Auch denke ich das ein numerischer Index weniger IO verursachen würde, falls die DB nicht im Hintergrund diese Dinge zusammenfasst, entsteht durch die Duplizierung ja auch ein ziemlicher Datenoverhead (100-200mb schätze ich hier zur Zeit).

    hustbaer schrieb:

    Zuletzt nochmal wegen Hardware: falls Bedenken bei neuer Hardware bestehen was Kompabilität etc. angeht wäre hier vielleicht VMware ein möglicher Ausweg. VMware kompatible Hardware gibt es wie Sand am Meer. Fall es sich um Solaris 9 oder 10 handelt, wäre das eine Option (Solaris 8 wird von VMware nicht unterstützt). Dummerweise gibt es keine P2V Tools die speziellen Support für Solaris drin haben, aber mit etwas Glück kannst du ein Disk-Image der physischen Maschine 1:1 in VMware booten.

    p.S.: Solaris 8 geht anscheinend doch irgendwie...

    Solaris8 (meistens in einem Container auf Solaris10) ist zur Zeit das OS.
    Aber die Hardware ist nicht meine Baustelle, habe da auch keinen Einfluss drauf.



  • Solarisguy schrieb:

    hustbaer schrieb:

    Ich persönlich *schätze*, dass es bei den meisten Anwendungen egal sein wird, ob man Strings oder Integers als Keys verwendet, so lange die Strings halbwegs kurz bleiben.

    Naja, es ist nur ein varchar. Trotzdem denke ich das eine numerische ID einfach besser von der Performance sein sollte.
    Das Blöde ist halt, das es nicht möglich ist, das mal eben auszutauschen, da hängt sehr viel dran.

    Ich verstehe eigentlich nicht ganz was du willst. Drückt der Schuh denn? Ist das System zu langsam?
    Wenn nicht, dann vergiss es einfach, und wende dich produktiveren Dingen zu.

    Wenn schon solltet ihr das etwas ernsthafter angehen, und das schliesst auch Überlegungen bezüglich Hardware mit ein.

    Ein Datensatz welcher als namen nur einen Buchstaben hat, wird 10-20 Sekunden schneller importiert, so zumindest die ersten Messungen dazu.

    Sehr sinnvolle Aussage 🙄
    10-20 Sekunden schneller als was? Ne Stunde? Ne Minute? Halbe Minute?



  • hustbaer schrieb:

    Solarisguy schrieb:

    hustbaer schrieb:

    Ich persönlich *schätze*, dass es bei den meisten Anwendungen egal sein wird, ob man Strings oder Integers als Keys verwendet, so lange die Strings halbwegs kurz bleiben.

    Naja, es ist nur ein varchar. Trotzdem denke ich das eine numerische ID einfach besser von der Performance sein sollte.
    Das Blöde ist halt, das es nicht möglich ist, das mal eben auszutauschen, da hängt sehr viel dran.

    Ich verstehe eigentlich nicht ganz was du willst. Drückt der Schuh denn? Ist das System zu langsam?
    Wenn nicht, dann vergiss es einfach, und wende dich produktiveren Dingen zu.

    Ja, man wäre gerne schneller, bzw. das Programm wird erweitert, und die Datenmengen nehmen evtl. auch zu.
    Das Programm ist jetzt insgesamt 10 Jahre alt, und wird jedes Jahr um neue Funktionen erweitert und angepasst.

    hustbaer schrieb:

    Wenn schon solltet ihr das etwas ernsthafter angehen, und das schliesst auch Überlegungen bezüglich Hardware mit ein.

    Tun wir ja ernsthaft, und da ist das halt eine der Fragestellungen.
    Das neuere Hardware und bessere Hardware da natürlich mehr Performance bringt ist klar.
    Meine Aufgabe ist es u.a. auch zu sehen, wo man im Programm dies noch verbessern kann.

    Und das soll dann auch im aktuellen Kontext sein. so ist das halt in diesem Projekt.
    Ich verstehe nicht, warum mir jeder immer die selben (einfachen) Ratschläge gibt.
    Das Programm läuft nun mal in dieser Konfiguration beim Endkunden, und vor einem größeren Migrationsprojekt wird sich da auch nichts dran ändern.

    hustbaer schrieb:

    Ein Datensatz welcher als namen nur einen Buchstaben hat, wird 10-20 Sekunden schneller importiert, so zumindest die ersten Messungen dazu.

    Sehr sinnvolle Aussage 🙄
    10-20 Sekunden schneller als was? Ne Stunde? Ne Minute? Halbe Minute?

    Habe da heute genauere Messungen gemacht, und jeweils 3 mal den gleichen Import laufen lassen, einmal mit 20 stelligen Namen und einmal mit 1 stelligen ('a').
    Ergebnis:
    Der Unterschied zwischen beiden Importen ist im Durchschnitt 104 Sekunden.
    Je kürzer der Name desto schneller auch der Import.



  • Um das in Relation zu setzen:
    Die Importe laufen zwischen 16:30 udn 19 Minuten.
    Wobei 16-17 Minuten für kurze Datasatznamen sind, und 19 für welche mit 20 Zeichen langem Namen.
    Sonst besteht im Import kein Unterschied.



  • So, habe in der Sybase Doku einen großen Teil zu Performance gefunden.

    Es lässt sich damit zu dem Thema folgendes Zusammenfassen:

    • Numerische Indexe sind i.d.R. mindestens gleichwertig, teilweise aber besser
    • Besteht in einer indexierten varchar Spalte keine große Varianz in der Länge, sollte man char nutzen, da dies Platz im Index spart.

    Was mir noch beim Studium der DB aufgefallen ist, das DB Design ist sehr einfach, und viel ausser varchar und int wird nicht verwendet.
    Habe aber zweifel das z.b. unsere Parameterwerte in den Tabellen größer sind als 65000, so das man hier auch tinyint nutzen könnte, bei 10 int werten wären das schon 20 Byte pro Datensatz. So könnte man für die Abfragen die IO Last senken.



  • Was du auch mal in deiner Sybase Doku nachschauen kannst ob es effizientere Importmöglichkeiten gibt. Verschiedene dbms unterstützen neben dem Parsen von sql auch Direkt-importmöglichkeiten wie das Laden von CSV oder anderen Formaten wo die Felder eine feste Breite aufweisen.



  • witte schrieb:

    Was du auch mal in deiner Sybase Doku nachschauen kannst ob es effizientere Importmöglichkeiten gibt. Verschiedene dbms unterstützen neben dem Parsen von sql auch Direkt-importmöglichkeiten wie das Laden von CSV oder anderen Formaten wo die Felder eine feste Breite aufweisen.

    Ich weiss, aber es ist leider so, das das alles aus XML Dateien kommt, und wir es dann in die DB einspeisen tun. Ist recht komplex, und auch nicht so das wir nur wenige Tabellen damit bedienen.

    Krass ist natürlich der ganze Importprozess momentan schon, wir haben fast 12000 Transactions in einem (mittleren) Import.



  • Was noch gehen könnte wäre Indexe entfernen, Daten importieren und Indicies wieder aufbauen. Eventuell sogar mit Deaktivierung der Fremdschlüsselbeziehungen während des Imports wenn Sybase das unterstützt.
    Gibt es vvlt ein Sybase-Consultant, den man sich für 2-3 Tage ausleihen kann?



  • Also das BULK COPY läuft ziemlich lowlevel, und indexe etc. müsste man dann sowieso abschalten.
    Was leider nicht geht sind BULK INSERTS wie in MySQL (INSERT foo values (a)(b)(c)).
    BULK COPY wird teilweise schon genutzt.

    Ein Sybase Experte wäre natürlich eine Idee, aber das Programm und die DB sind recht komplex, in 2-3 Tagen könnte der auch keine Aussagen treffen.



  • Solarisguy schrieb:

    Also das BULK COPY läuft ziemlich lowlevel, und indexe etc. müsste man dann sowieso abschalten.
    Was leider nicht geht sind BULK INSERTS wie in MySQL (INSERT foo values (a)(b)(c)).
    BULK COPY wird teilweise schon genutzt.

    Ein Sybase Experte wäre natürlich eine Idee, aber das Programm und die DB sind recht komplex, in 2-3 Tagen könnte der auch keine Aussagen treffen.

    Naja...
    Wenn es für Sybase diverse Profiling-Tools gibt, könnte der vielleicht schon relativ schnell zu einem Ergebnis kommen.
    Schlechte Performance kann ja an vielem liegen, kann theoretisch sogar ein fehlender Index sein.

    Und sonst müssen es halt 5-10 Tage Sybase-Experte sein 🙂
    Wenn die Anwendung wichtig genug ist, kann das sich das schon bezahlt machen.


Anmelden zum Antworten