ventajas valor desventajas definicion datos clave caracteristicas sql ruby-on-rails ruby key-value-store activerecord

sql - desventajas - definicion de valor en base de datos



¿Pros/contras de almacenar hash serializado contra el objeto de base de datos clave/valor en ActiveRecord? (3)

Si tengo varios objetos que tienen básicamente un Profile , lo que estoy usando para almacenar atributos aleatorios, ¿cuáles son los pros y los contras de:

  1. Almacenar un hash serializado en una columna para un registro, vs.
  2. Almacenar un montón de objetos clave / valor que belong_to al objeto principal.

Código

Digamos que tienes registros de STI como estos:

class Building < ActiveRecord::Base has_one :profile, :as => :profilable end class OfficeBuilding < Building; end class Home < Building; end class Restaurant < Building; end

Cada has_one :profile

Opción 1. Hash serializado

class SerializedProfile < ActiveRecord::Base serialize :settings end create_table :profiles, :force => true do |t| t.string :name t.string :website t.string :email t.string :phone t.string :type t.text :settings t.integer :profilable_id t.string :profilable_type t.timestamp end

Opción 2. Key / Value Store

class KeyValueProfile < ActiveRecord::Base has_many :settings end create_table :profiles, :force => true do |t| t.string :name t.string :website t.string :email t.string :phone t.string :type t.integer :profilable_id t.string :profilable_type t.timestamp end create_table :settings, :force => true do |t| t.string :key t.text :value t.integer :profile_id t.string :profile_type t.timestamp end

¿Cuál escogerías?

Supongamos que el 99% del tiempo no necesitaré buscar por la settings personalizada. Solo me pregunto cuáles son las ventajas y desventajas en términos de desempeño y la probabilidad de problemas futuros. Y el número de settings personalizadas probablemente será de 10 a 50.

Preferiría ir con la segunda opción, con la tabla de configuración, porque sigue las convenciones orientadas a objetos de ActiveRecord. Pero me pregunto si en este tipo de situación se produciría un costo de rendimiento demasiado alto.

Nota: Me estoy preguntando en términos de RDBMS solamente. Esto sería un ajuste perfecto para MongoDB / Redis / CouchDB / etc. pero quiero saber puramente los pros y los contras en términos de SQL.


Me enfrenté al mismo dilema que describió y terminó con la implementación de la tabla clave / valor debido a las posibles ventajas de mantenimiento que otros mencionaron. Es más fácil pensar en cómo podría seleccionar y actualizar la información en filas separadas de la base de datos en una migración futura en lugar de un solo hash serializado.

Otro problema que he experimentado personalmente al usar un Hash serializado es que debe tener cuidado de que los datos serializados que está almacenando no sean mayores de lo que puede contener el campo de texto DB. Puede terminar fácilmente con datos faltantes o dañados si no tiene cuidado. Por ejemplo, al usar la clase y tabla SerializedProfile que describió, podría causar este comportamiento:

profile = SerializedProfile.create(:settings=>{}) 100.times{ |i| profile.settings[i] = "A value" } profile.save! profile.reload profile.settings.class #=> Hash profile.settings.size #=> 100 5000.times{ |i| profile.settings[i] = "A value" } profile.save! profile.reload profile.settings.class #=> String profile.settings.size #=> 65535

Todo el código que diga, tenga en cuenta sus límites de base de datos o sus datos serializados se recortarán la próxima vez que se recuperen y ActiveRecord no podrá volver a serializarlos.

Para aquellos de ustedes que quieran usar un Hash serializado, ¡adelante! Creo que tiene potencial para funcionar bien en algunos casos. Me topé con el complemento activerecord-attribute-fakers que parece ser un buen ajuste.


Recomendaría simplemente crear un atributo de llamada de modelo y tener cada uno de los objetos que necesitan muchos de ellos tiene muchos. Entonces no tienes que perder el tiempo con la serialización o algo tan quebradizo como ese. Si usa la sintaxis: join, no tiene ningún problema de rendimiento real con esto.

Serializar los datos en su RDBMS es casi siempre imprudente. Es más que preguntas, se trata de la capacidad de describir y migrar sus datos (y la serialización destruye esa capacidad).

class Building < ActiveRecord::Base has_many :attributes end class Attribute < ActiveRecord::Base belongs_to :building end create_table :attributes, :force => true do |t| t.integer :building_id t.string :att_name t.string :data t.timestamp end


Tuve el mismo problema, pero finalmente tomé la decisión.

La opción de serialización hash hace que el problema de mantenimiento. Es difícil consultar, ampliar o refactorizar dichos datos; cualquier cambio sutil requiere una migración, lo que significa que se puede volver a deserializar y volver a serializar cada registro, y en función de la serialización de refactorización puede ocurrir una excepción. Intenté tanto la serialización binaria como JSON: el segundo es más fácil de extraer y corregir, pero aún así es demasiado complicado.

Lo que trato de usar ahora es la tabla de configuraciones separadas, mucho más fácil de mantener. Planeo usar la gema de Preferences para lo que principalmente hace abstracción para un uso fácil. No estoy seguro de si funciona con Rails 3 todavía, es pequeño, por lo que puedo extenderlo si es necesario.

Actualización nov 2013

Rails 4 recientemente lanzado es compatible con las nuevas funciones de PostgreSQL 9.1+, como los tipos de columnas hstore o json para sus conjuntos de datos dinámicos. Aquí hay un artículo que cubre el uso de hstore en Rails 4 . Ambos tipos admiten capacidades de indización y consulta avanzada (Json con Pg 9.3). Hstore también está disponible para usuarios de Rails 3 con la activerecord-postgres-hstore .

Estoy en el proceso de migrar algunas de las tablas de preferencias no críticas de mi proyecto a hstores. En las migraciones acabo de actualizar las definiciones de tabla y execute una consulta SQL por tabla para mover los datos.