Performance-Überlegung für Primary Key für sehr große Tabelle?



  • Ich möchte Aktienkurse in einer SQL Server (Express) Datenbank verwalten.

    Der grundsätzliche Aufbau besteht aus 2 Tabellen:

    shares: Den Aktiengesellschaften, dort ist nur die ISIN (internationale Wertpapierkenn-Nummer) und der Name der AG gespeichert.

    prices: Der Kurstabelle, dort soll jeden Tag der Kurs, der Umsatz, evtl. die Geld-/Briefspanne, ... gespeichert werden.

    Von der shares Tabelle zeigt ein Primary Key auf die Kurse in der prices Tabelle.

    Und hier habe ich zu wenig Erfahrung, wie man das performancemäßig am besten löst.

    Die Datenbank soll die Kurse von ca. 3.000 Aktien über einen Zeitraum von ca. 3 Jahren speichern, ältere Kurse können gelöscht werden. Das wären dann rund 3000x52x5x3=2.340.000 Datensätze. IMHO schon eine ganze Menge, oder - hier fehlt mir die Erfahrung - ist das für eine Datenbank (SQL-Server Express) "ein Klacks", und ich muss mir keine Sorgen über die Performance machen?

    Jetzt zum eigentlichen Problem:

    Die ISIN ist eindeutig und nicht NULL, könnte also als Primary Key dienen. Leider ist die ISIN nicht wie die alten WKN (vor 2003) eine ganze Zahl sondern eine alphanumerische Zeichenkette mit 12 Zeichen Länge (fixed).

    Kann ich die direkt als Primary Key verwenden oder wird das langsam und/oder wird dann der Index sehr groß. Oder ist es performancemäßig deutlich besser, ich lege einen extra Integer(32 Bit) mit Autoincrement für jede AG an und nutze den als Primary Key? Letzteres ist halt nicht so bequem, wenn man mal manuell in der Datenbank suchen möchte, bzw. bei Fehlern "debuggen" muss.

    Dazu bitte folgendes bedenken: Die Kurse können auch mehr als einmal täglich geholt werden, d. h. bei jedem Eintragen eines Kurses muss überprüft werden:

    1. Ist der Kurs schon in der shares Tabelle, falls nein, neuer Eintrag in shares

    2. wurde der Kurs an diesem Tag schon einmal eingetragen, falls ja wird er nur aktualisiert, falls nein wird ein neuer Datensatz in der Kurstabelle erstellt.

    Beim Anzeigen der Werte eines bestimmten Tages sollen die Kurse natürlich nach AG-Name sortiert ausgegeben werden, d. h. bei jeder Suche muss anhand des Namens der Primary Key in der shares Tabelle ermittelt werden und dann die entsprechenden Einträge in der prices Tabelle, d. h. die AG-Name-Spalte in shares und die Datumsspalte in prices wird ein foreign Key.



  • johan schrieb:

    Die ISIN ist eindeutig und nicht NULL, könnte also als Primary Key dienen. Leider ist die ISIN nicht wie die alten WKN (vor 2003) eine ganze Zahl sondern eine alphanumerische Zeichenkette mit 12 Zeichen Länge (fixed).

    Kann ich die direkt als Primary Key verwenden oder wird das langsam und/oder wird dann der Index sehr groß. Oder ist es performancemäßig deutlich besser, ich lege einen extra Integer(32 Bit) mit Autoincrement für jede AG an und nutze den als Primary Key? Letzteres ist halt nicht so bequem, wenn man mal manuell in der Datenbank suchen möchte, bzw. bei Fehlern "debuggen" muss.

    Ich würde folgendes vorschlagen:
    - Verwende als Primärschlüssel nie Anwendungsrelevante Daten. Die ISIN ist so ein Anwendungsrelevantes Datum. Es kann sein das du später (viel später) dadurch echte Probleme beim Erweitern der Anwendung bekommst.
    - Verwende intern für Primärschlüssel einfach eine ID-Spalte (Eine Spalte mit dem Namen "ID" als Integer, Number oder so...) und verlinke die beiden Tabellen (Primär- und Fremdschlüssel) über eine solche Primärschlüsselspalte.
    - Wenn du deine Anwendung so baust, dass sie überall IDs verwenden, dann sparst du dir später "teure" where-Klauseln die auf irgendwelche TEXT-Spalten zugreifen.

    Außerdem kommt mir das ganze mit meiner Erfahrung sauberer vor.

    Beim Anzeigen der Werte eines bestimmten Tages sollen die Kurse natürlich nach AG-Name sortiert ausgegeben werden, d. h. bei jeder Suche muss anhand des Namens der Primary Key in der shares Tabelle ermittelt werden und dann die entsprechenden Einträge in der prices Tabelle, d. h. die AG-Name-Spalte in shares und die Datumsspalte in prices wird ein foreign Key.

    Das verstehe ich nicht so ganz (ich stecke aber auch nicht in d. Aufgabe drin wie du). Die Datumsspalte würde ich auf keinen Fall zum foreign Key machen. Du kannst auch einfach so nach AG-Namen und Datum sortieren (order by ag_name,datum). Sollte performancetechnisch keine große Auswirkung haben.



  • chris++@off schrieb:

    Ich würde folgendes vorschlagen:
    - Verwende als Primärschlüssel nie Anwendungsrelevante Daten. Die ISIN ist so ein Anwendungsrelevantes Datum. Es kann sein das du später (viel später) dadurch echte Probleme beim Erweitern der Anwendung bekommst.
    - Verwende intern für Primärschlüssel einfach eine ID-Spalte (Eine Spalte mit dem Namen "ID" als Integer, Number oder so...) und verlinke die beiden Tabellen (Primär- und Fremdschlüssel) über eine solche Primärschlüsselspalte.
    - Wenn du deine Anwendung so baust, dass sie überall IDs verwenden, dann sparst du dir später "teure" where-Klauseln die auf irgendwelche TEXT-Spalten zugreifen.

    Außerdem kommt mir das ganze mit meiner Erfahrung sauberer vor.

    Habe ich mir fast gedacht, dann mache ich die Lösung mit der extra ID, danke.

    chris++@off schrieb:

    Das verstehe ich nicht so ganz (ich stecke aber auch nicht in d. Aufgabe drin wie du). Die Datumsspalte würde ich auf keinen Fall zum foreign Key machen. Du kannst auch einfach so nach AG-Namen und Datum sortieren (order by ag_name,datum). Sollte performancetechnisch keine große Auswirkung haben.

    Ich hatte gedacht, dass er bei einem foreign Key einen Index für diese Spalte anlegt, und dann das Durchsuchen viel schneller wird.



  • Du kannst für solche Spalten auch einen Index anlegen:

    create index <name> on <table> ...

    Bietet den Vorteil der schnellen Sortierung. Das ist sauberer als ein Fremdschlüssel der nur wegen der Performance existiert.



  • OK danke.


Log in to reply