PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Modelowanie dużych obiektów PostgreSQL w Rails

Jeśli używasz ActiveRecord, który jest dostarczany z Railsem z jednym z jego adapterów, jedyne formalne mapowanie typu bazy danych na typ Rails lub Ruby, które ma miejsce, jest zazwyczaj zdefiniowane w NATIVE_DATABASE_TYPES stała w adapterze, która jest zwracana przez jego native_database_types metoda. Dla PostgreSQL w Rails 3.2.x, czyli w ActiveRecord::ConnectionAdapters::PostgreSQLAdapter czyli tutaj . Tak więc dla tego adaptera typ "binarny" w Railsach jest odwzorowany na typ "bytea" w PG. W przypadku niektórych typów możesz zastąpić ten typ bazy danych, do którego mapuje, używając klejnotu o nazwie activerecord-native_db_types_override . Ale chcemy używać dużych obiektów, więc...

Migracje

Jak zauważył Jim Deville w komentarzach, możesz określić niestandardową kolumnę w tabeli, taką jak:

t.column :some_oid, 'blob_oid', :null => false

Jeśli potrzebujesz zrobić jeszcze więcej, co jest niestandardowe, możesz również użyć execute("SQL GOES HERE;") utworzyć tabelę za pomocą prostego SQL. A jeśli masz istniejący starszy schemat lub zmiany SQL, które zostały wprowadzone poza migracjami, rozważ użycie pliku structure.sql (config.active_record.schema_format = :sql opcja w config/application.rb a następnie wykonaj:rake db:structure:dump ).

Odczyt/zapis/sprawdzenie długości/usunięcie dużych obiektów

Skopiowano z pewnymi modyfikacjami w celu wyjaśnienia itp. z:https://github.com/diogob/carrierwave-postgresql/blob/v0.1.0/lib/carrierwave/storage/postgresql_lo.rb :

Zaktualizowano :możemy, ale nie musimy, umieścić początek przed lo_read/lo_write/lo_lseek i wykonać lo_close w bloku zapewnienia, ponieważ na Dokumentacja PG „Wszelkie deskryptory dużych obiektów, które pozostają otwarte po zakończeniu transakcji, zostaną automatycznie zamknięte”. (dzięki Diogo za te informacje)

    require 'pg'

    ...

    def read
      (...).transaction do
        lo = connection.lo_open(identifier)
        content = connection.lo_read(lo, file_length)
        connection.lo_close(lo)
        content
      end
    end

    def write(file)
      (...).transaction do
        lo = connection.lo_open(identifier, ::PG::INV_WRITE)
        size = connection.lo_write(lo, file.read)
        connection.lo_close(lo)
        size
      end
    end

    def delete
      connection.lo_unlink(identifier)
    end

    def file_length
      (...).transaction do
        lo = connection.lo_open(identifier)
        size = connection.lo_lseek(lo, 0, 2)
        connection.lo_close(lo)
        size
      end
    end

Zamiast connection , użyj surowego połączenia z modelu lub bazy, np. ActiveRecord::Base.connection.raw_connection (zobacz to ).

(...).transaction wywołuje transakcję na modelu lub bazie, np. ActiveRecord::Base.transaction (zobacz to ).

identifier jest oidem, który musisz przekazać/ustawić lub uzyskać po prostu wykonując connection.lo_creat .

Inne przykłady/informacje:

Te ostatnie i niektóre odpowiedzi tutaj zasugeruj, że warto rozważyć przechowywanie dużych plików oddzielnie od bazy danych, np. dzięki czemu możesz korzystać z pamięci w chmurze. Ale jeśli tylko przechowujesz ścieżki/identyfikatory do zewnętrznych plików, które nie zarządzane przez bazę danych, tracisz spójność ACID (jeden lub więcej rekordów bazy danych może wskazywać na jeden lub więcej plików, których tam nie ma lub może istnieć jeden lub więcej plików, które nie mają jednego lub więcej skojarzonych rekordów w bazie danych). Innym argumentem przemawiającym za przechowywaniem plików w systemie plików jest możliwość strumieniowego przesyłania plików, ale duży obiekt PG przechowuje pliki w systemie plików w sposób zarządzany przez postgres, aby zapewnić spójność ACID i umożliwić przesyłanie strumieniowe (czego nie można zrobić z normalnym BLOBem /Rails typu binarnego). Więc to po prostu zależy; niektórzy uważają przechowywanie w oddzielnej pamięci za pomocą odniesień do ścieżki za lepszą opcję, a niektórzy wolą spójność ACID za pośrednictwem dużych obiektów.

Łatwy sposób

Po prostu użyj CarrierWave i carrierwave-postgresql .




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Dlaczego moja sygnatura czasowa została przesunięta w strefie czasowej?

  2. Czym dokładnie jest operator do porównania między `bigint` i `date` w postgresql?

  3. Błąd podczas otwierania pgAdmin 4 na Macu

  4. Przypisz całkowitą wartość miesiąca do każdego dnia miesiąca

  5. NodeJS — Dodaj tablicę ciągu znaków w zapytaniu PostgreSQL