Information ausblenden
Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm

Performance Bei Riesen Tabelle

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von NeoPrince, 13 September 2013.

  1. NeoPrince

    NeoPrince Aktiver Benutzer

    Hi

    Ich Habe Eine Tabelle mit momentan ca. 50 milionen Logdaten -> ca 5GB und das Werden Täglich mehr.
    Hab schon Diverse optimierungen vorgenommen die Im Internet vorgeschlagen werden, Engine auf Inno DB umgestellt, Datenbank läuft in einer Ramdisk, Optimierung der Datentypen in der Tabelle etc.
    Ich hab mich jetzt Dazu Entschlossen Das Problem zu beheben indem ich Eine Strukturänderung vornehme, Kleinere Tabellen sollten ja auch mehr Performance bringen.
    Die Tabelle Sieht momentan volgendermaßen aus:

    Stringnummer; Logdaten(4 felder mit messdaten); Timestamp

    Jeder String bringt ca. alle 5 minuten einen eintrag in die Tabelle.
    es gibt momentan ca 1000 Strings die in ca. 30. Anlagen zusammengeschlossen sind. das heißt in 5 minuten kommen ca 1000 neue Datensätze dazu.
    Die Überlegung war nun:
    Entweder ich lege für jeden Monat eine Neue Log Tabelle an,
    Oder Ich lege für jede Anlage eine Neue Tabelle An,

    Die Frage Ist nun, ob von euch einer Schon Erfahrung mit so großen Datenmengen hat und ob es für soetwas evtl bessere vorgehensweisen gibt. Ich bin für alle verbesserungsvorschläge offen.
     
  2. ukulele

    ukulele Datenbank-Guru

    Erfahrungen kann ich leider nicht bieten befasse mich mit kleinen Datenbeständen. Generell bezweifle ich aber das viele kleine Tabellen die Sache besser machen denn SQL ist eigentlich dafür gemacht große Datenmengen zu speichern und zu "organisieren", zumindest nach meinem Verständniss.

    Was genau ist denn das Performance Problem, das Schreiben oder das Lesen der Daten?

    Ich hätte noch Ideen:
    1) Index, wirst du vermutlich schon nutzen
    2) überflüssige alte Daten löschen oder archivieren oder nur noch die Auswertung speichern (ähnlich wie im CERN) aber das ist natürlich immer eine Frage des Anwendungsgebietes
    3) Partitioning - habe ich mich noch nicht so mit befasst aber nach meinem Verständniss kann man damit bei großen Datenmengen Performance gewinnen
    4) Anderes DBMS - MySQL ist sicherlich viel genutzt und auch in großen Unternehmen a la Google einsatzfähig. Aber für ich kann mir vorstellen das PostgreSQL hier noch mehr zu bieten hat
     
    NeoPrince gefällt das.
  3. akretschmer

    akretschmer Datenbank-Guru

    Was ist denn genau das Problem? Dazu hast du nix gesagt. 50 Milluonen sind kein Thema, ich betreue eine Anwendung, wo aller 2 Tage etwa so viel reinkommt, seit Jahren. Ist aber, siehe auch @ukulele , PostgreSQL. Also, was ist Dein Problem? Explain ist bekannt?
     
    NeoPrince gefällt das.
  4. NeoPrince

    NeoPrince Aktiver Benutzer

    Das Problem sind Abfragen auf diese Tabelle.
    Die Dauern jeh nach dem wie sie gejoint sind mehrere Minuten. Das reinschreiben ist kein Problem.
    Explain sagt mir nichts Googelgoogel...

    zu ukulele
    1: Indizes hab ich
    2: Das Mit dem Nur Auswertung Speichern ist ne gute idee. das Kann ich teilweise machen.
    3: Partitioning sagt mir auch nichts muss ich mal googeln
    4: Anderes DBMS ist leider keine Option für das Projekt aber ich werd es mir für die Zukunft merken

    Gruß und danke für die Vorschläge
     
  5. akretschmer

    akretschmer Datenbank-Guru


    Also, Urlaub ist zu Ende, mit dem Handy zu antworten ist nicht sooo der Brüller. Zu Deinen Fragen:

    Partitioning: macht Sinn, wenn die Abfragen dazu passen. Stell Dir vor, Du fragst ab, ob eine Zahl geteilt durch 3 einen Rest von X mit X in (0,1,2) hat. Das ist Deine Where-Condition. Da kannst Du Deine Tabelle foo in 3 Teiltabellen splitten, foo_0, foo_1 und foo_2. Dazu noch einen INSERT-Trigger. In PG mal als Schnellschuß so:

    Code:
    test=# create table foo (id serial primary key, value int);
    NOTICE:  CREATE TABLE will create implicit sequence "foo_id_seq" for serial column "foo.id"
    NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo"
    CREATE TABLE
    Time: 9,728 ms
    test=*# create table foo_0 (check (value %3 = 0)) inherits (foo);
    CREATE TABLE
    Time: 1,112 ms
    test=*# create table foo_1 (check (value %3 = 1)) inherits (foo);
    CREATE TABLE
    Time: 1,138 ms
    test=*# create table foo_2 (check (value %3 = 2)) inherits (foo);
    CREATE TABLE
    Time: 1,261 ms
    test=*# create or replace function insert_foo() returns trigger as $$begin execute 'insert into foo_' || (new.value % 3)::text || ' (value) values(' || new.value || ')'; return null; end; $$ language plpgsql;
    CREATE FUNCTION
    Time: 0,401 ms
    test=*# create trigger trg1 before insert on foo for each row execute procedure insert_foo();CREATE TRIGGER
    Time: 0,263 ms
    
    Wenn wir jetzt eine Zahl eingeben:

    Code:
    test=*# insert into foo (value) values(4711);
    INSERT 0 0
    Time: 0,742 ms
    test=*# select * from foo;
     id | value
    ----+-------
      2 |  4711
    (1 row)
    
    Time: 0,372 ms
    test=*# select * from only foo;
     id | value
    ----+-------
    (0 rows)
    
    Time: 0,202 ms
    test=*# select * from only foo_1;
     id | value
    ----+-------
      2 |  4711
    (1 row)
    
    so landet diese in der Teiltabelle foo_1, wie oben gezeigt. Bei einer Abfrage, welche einer der Partitionierungsregel passende WHERE-Condition hat, wird nun nur foo (immer) und foo_X abgefragt, was man schön via EXPLAIN sehen kann:

    Code:
    test=*# explain select * from foo where value % 3 = 1;
      QUERY PLAN
    -----------------------------------------------------------------------
     Result  (cost=0.00..42.10 rows=12 width=8)
      ->  Append  (cost=0.00..42.10 rows=12 width=8)
      ->  Seq Scan on foo  (cost=0.00..0.00 rows=1 width=8)
      Filter: ((value % 3) = 1)
      ->  Seq Scan on foo_1 foo  (cost=0.00..42.10 rows=11 width=8)
      Filter: ((value % 3) = 1)
    (6 rows)
    
    Also, foo_0 und foo_2 werden nicht durchsucht, nur foo und foo_1, weil die DB 'weiß', daß nur dort Values mit der Condition drin sein können, nicht in foo_0, nicht in foo_2.

    Achtung: das gezeigte ist in PostgreSQL gemacht.

    Fazit:

    • Partitionierung verteilt Daten auf unterschiedliche Tabellen, nach außen 'sehe' ich meine Haupttabelle (welche aber eigentlich immer leer ist). Nur mit dieser arbeite ich normalerweise aber. Die abgeleiteten Kindtabellen fasse ich 'normalerweise' nicht direkt an. (es gibt Ausnahmen)
    • macht nur Sinn, wenn ich Abfragen habe, die die Partitionierung nutzen können.
    • lohnt sich erst ab mind. 1 - 10 Millionen Records pro Kindtabelle (Faustregel in PG)
    • EXPLAIN ist ein Werkzeug, um zu sehen, wie die DB die Abfrage ausführt. MySQL kann das zwar auch, ist aber sehr eingeschränkt.
    • MySQL und Partitionierung? Ich weiß es nicht
    • Da Du beharrlich verschweigst, wie Deine Abfragen konkret aussehen, können wir auch nicht mehr weiter helfen
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden