2016-07-10 10 views
1

Momentan verwende ich Ruby PStore um große Objekte (> 1GB) auf der Festplatte zu speichern. Leider scheint die Größe des PStore bei ca. 2GB begrenzt zu sein und dies reicht für meine Anwendung nicht aus.Ruby PStore vs Postgres

Ich habe dann begonnen, mit Postgres 9.5 + PostGIS zu experimentieren. Dies würde es erlauben, mehr Daten zu speichern und zusätzlich einige räumliche Operationen durchzuführen, die ich in Zukunft benötigen werde. Ich benutze pg-0.18.4 auf einem MacBook Pro (16GB) mit Yosemite.

Zu meiner Überraschung (ich bin kein Datenbankexperte) ist der Leistungsverlust enorm. Als Beispiel:

  • PStore auf der Festplatte zu schreiben: 130.428481s
  • DB-Einsätze: 4280.366986s

Um Ihnen weitere Informationen, das ist mein Skript die Tabelle zu erstellen:

CREATE TABLE public.radiation(
    id integer NOT NULL, 
    time timestamp with time zone NOT NULL, 
    surface_total_shortwave double precision, 
    person_total_shortwave double precision, 
    mean_radiant_temperature double precision, 
    cell_id integer 
) WITH (OIDS=FALSE) 

Jede Zeile der Tabelle repräsentiert einen bestimmten berechneten Wert an einer bestimmten Stelle auf einem Netz (cell_id) zu einem bestimmten Zeitpunkt (Zeit).

Die INSERT ist (in Ruby):

INSERT INTO radiation (
    id, 
    time, 
    surface_total_shortwave, 
    person_total_shortwave, 
    mean_radiant_temperature, 
    cell_id 
) VALUES (
    #{id}, 
    '#{time}', 
    #{surface_total_shortwave}, 
    #{person_total_shortwave}, 
    #{mean_radiant_temperature}, 
    #{cell_id} 
) 

Gemäß Empfehlungen hier, alle Schlüssel, Indizes, Trigger usw. deaktiviert sind. Alle INSERT sind innerhalb einer einzigen Transaktion.

Wenn die Abfrage so geändert wird, dass statt einer Zeile pro Cell_ID zu speichern, speichern ich die volle Array (double precision[]), die INSERT Zeit wird vergleichbar mit PStore, aber ich verliere die räumlichen Fähigkeiten (glaube ich).

Meine Frage ist. Ist das normal? Kann die Leistung auf gewisse Weise verbessert werden? Vielleicht binäre Daten speichern?

Würde es einen Unterschied machen, direkt mit libpq zu C zu wechseln?

Antwort

1

hatte ich das gleiche Problem, wenn eine Indizierung app Codierung, zuerst mit dem Moneta Juwel versucht, aber das ist für mich nicht funktioniert. Gelöst wurde es mit SqLite, das mit Datenbanken im Speicher arbeiten kann. Hier ein Beispiel, es verwendet ActiveRecord (keine Schienen).

ActiveRecord::Base.establish_connection(:adapter => "sqlite3",:database => "db/words.db") 
unless ActiveRecord::Base.connection.table_exists?('words') 
    ActiveRecord::Schema.define do 
    create_table :words do |word_table| 
     word_table.column :word, :string 
    end 
    end 
end 

hier eine der Klassen meines Modells

class Word < ActiveRecord::Base 
    establish_connection(:adapter => "sqlite3",:database => ":memory:") 
    has_many :occurances 
    has_many :filenames, through: :occurances 
end 

Der Indexteil (Schreiben) verwendet diese Technik Tausende von Wörtern in ein paar Sekunden zu schreiben, der Leseteil (für eine Website) verwendet einfachen Zugriff von der Festplatte.

Wissen Sie nicht, welche Ruby-Implementierung Sie verwenden, aber ich habe es geschafft, dieses Problem auf andere Fälle mit MRI Ruby 2.3 64 Bit (unter Windows) zu lösen, die viel mehr Speicher und auch mit jRuby verwenden können Sie können zusätzliche Speicherverwaltungsparameter bereitstellen.

Da diese Art von Apps ressourcenhungrig und riesig ist, ist die Leistung wichtig, daher ist es am besten, die erste Lösung mit einer dieser Techniken zu kombinieren.

Der Vorschlag von Ilya ist auch sehr gut, in Masse schreiben, das kann mit meinen Lösungen kombiniert werden.

In jedem Fall, überdenken Sie Ihre Algorithmen, oft ist es nicht notwendig, so viel zu schreiben, indem Sie optimieren.

+0

Vielen Dank für Ihren Rat. Einfach auf 'SQLite' zu ​​wechseln (in der Datei, da ich die Daten speichern muss), hat die Leistung enorm gesteigert. Mein mittelfristiger Plan ist, [Sequel] (http://sequel.jeremyevans.net/) zu verwenden. Das Hinzufügen von "vorbereiteten Aussagen" hat mich zusätzlich um 50% verbessert. – Rojj

+0

Schreiben in Stapeln (wenn möglich) könnte auch die Geschwindigkeit sehr profitieren, siehe die Antwort, die ich hier schrieb http://StackOverflow.com/Questions/38332004/Processing-Big-amount-of-csv-files/38332342#38332342 Könnten Sie bitte die Antwort akzeptieren? – peter

2

erstellen Sie zwei Dinge versuchen:

  1. Führen Sie alle INSERT s in einer Transaktion:

    SET synchronous_commit TO OFF; 
    BEGIN; 
    INSERT ... ; 
    INSERT ... ; 
    COMMIT; 
    SET synchronous_commit TO ON; 
    

    Beachten Sie, dass dies:

    BEGIN; 
    INSERT ...; 
    INSERT ...; 
    COMMIT; 
    
  2. Disable synchronous commit während dies zu tun kann bei Stromausfall während des Einsteckens zu Datenverlust führen.

+0

Danke. Alle "INSERT" wo bereits in einer Transaktion (Frage aktualisiert). Ich habe das 'synchrone Commit' getestet und der Unterschied ist vernachlässigbar. – Rojj

+0

Hallo Ilya, außer Batches, irgendeine Idee, wie synchrone Commit mit ActiveRecord zu deaktivieren? auch möglich in Orakel? – peter

+0

Es tut mir leid, dass ich Oracle noch nie benutzt habe. Für ActiveRecord und PostgreSQL gibt es gem [surus] (https://rubygems.org/gems/surus). –