Domanda

Ho un numero di oggetti diversi con un numero variabile di attributi. Fino ad ora ho salvato i dati in file XML che consentono facilmente un numero in continua evoluzione di attributi. Ma sto provando a spostarlo in un database.

Quale sarebbe il tuo modo preferito di archiviare questi dati?

Alcune strategie che ho identificato finora:

  • Avere un singolo campo denominato " attributi " nella tabella dell'oggetto e memorizza i dati serializzati o json'ed.
  • Memorizzando i dati in due tabelle (oggetti, attributi) e usando un terzo per salvare le relazioni, rendendolo una vera relazione n: m. Soluzione molto pulita, ma forse molto costosa per recuperare un intero oggetto e tutti i suoi attributi
  • Identificazione degli attributi che tutti gli oggetti hanno in comune e creazione di campi per questi nella tabella dell'oggetto. Memorizzare gli attributi rimanenti come dati serializzati in un altro campo. Questo ha un vantaggio rispetto alla prima strategia, che semplifica le ricerche.

Qualche idea?

È stato utile?

Soluzione

Se mai hai intenzione di cercare attributi specifici, è una cattiva idea serializzarli in una singola colonna, poiché dovrai utilizzare le funzioni per riga per ottenere le informazioni - questo raramente si adatta bene.

Opterei per la tua seconda scelta. Avere un elenco di attributi in una tabella degli attributi, gli oggetti nella propria tabella e una tabella di relazioni molti-a-molti chiamata attributi degli oggetti.

Ad esempio:

objects:
    object_id    integer
    object_name  varchar(20)
    primary key  (object_id)
attributes:
    attr_id      integer
    attr_name    varchar(20)
    primary key  (attr_id)
object_attributes:
    object_id    integer  references (objects.object_id)
    attr_id      integer  references (attributes.attr_id)
    oa_value     varchar(20)
    primary key (object_id,attr_id)

Si nota la tua preoccupazione per le prestazioni ma, nella mia esperienza, è sempre più costoso dividere una colonna che combinare più colonne. Se si scopre che ci sono problemi di prestazioni, è perfettamente accettabile interrompere 3NF per motivi di prestazioni.

In quel caso lo memorizzerei allo stesso modo ma avrei anche una colonna con i dati grezzi serializzati. Se si utilizzano i trigger di inserimento / aggiornamento per mantenere sincronizzati i dati colonnari e combinati, non si avranno problemi. Ma non dovresti preoccuparti fino a quando non emerge un problema reale.

Usando questi trigger, minimizzi il lavoro richiesto per solo quando i dati cambiano. Tentando di estrarre le informazioni della sotto-colonna, fai un lavoro inutile su ogni seleziona.

Altri suggerimenti

Una variazione sulla tua soluzione 2d è solo due tabelle (supponendo che tutti gli attributi siano di un solo tipo):

T1: | Colonne dati oggetto | Object_id |

T2: | ID oggetto | nome_attributo | valore attributo | (indice univoco sulle prime 2 colonne)

Ciò è ancora più efficiente se combinato con la terza soluzione, ad es. tutti i campi comuni vanno in T1.

Non è consigliabile rimuovere l'attributo > 1 nello stesso BLOB: non è possibile filtrare in base agli attributi, non è possibile aggiornarli in modo efficiente

Lasciatemi dare un po 'di concretezza a ciò che diceva DVK.

Supponendo che i valori siano dello stesso tipo della tabella (buona fortuna, penso che ne avrai bisogno):

dynamic_attribute_table
------------------------
id         NUMBER
key        VARCHAR
value      SOMETYPE?

esempio (automobili):

|id|    key   |   value   |
---------------------------
| 1|'Make'    |'Ford'     |
| 1|'Model'   |'Edge'     |
| 1|'Color'   |'Blue'     |
| 2|'Make'    |'Chevrolet'|
| 2|'Model'   |'Malibu'   |
| 2|'MaxSpeed'|'110mph'   |

Quindi,
entity 1 = {('Make', 'Ford'), ('Model', 'Edge'), ('Color', 'Blue')}
e,
entity 2 = {('Make', 'Chevrolet'), ('Model', 'Malibu'), ('MaxSpeed', '110mph')}.

Se stai usando un db relazionale, penso che tu abbia fatto un buon lavoro elencando le opzioni. Ognuno di essi ha i suoi pro e contro. Sei nella posizione migliore per decidere cosa funziona meglio per le tue circostanze.

L'approccio serializzato è probabilmente il più veloce (a seconda del codice per la deserializzazione), ma significa che non sarà possibile interrogare i dati con SQL. Se dici che non hai bisogno di interrogare i dati con SQL, sono d'accordo con @longneck, forse dovresti usare uno stile chiave / valore db invece di un db relazionale.

MODIFICA - leggendo più dei tuoi commenti, PERCHÉ stai passando a un db se la velocità è la tua principale preoccupazione. Cosa c'è di sbagliato nella tua attuale implementazione XML?

In passato implementavo questo schema :

t_class (id RAW(16), parent RAW(16)) -- holds class hierachy.
t_property (class RAW(16), property VARCHAR) -- holds class members.
t_declaration (id RAW(16), class RAW(16)) -- hold GUIDs and types of all class instances
t_instance (id RAW(16), class RAW(16), property VARCHAR2(100), textvalue VARCHAR2(200), intvalue INT, doublevalue DOUBLE, datevalue DATE) -- holds 'common' properties

t_class1 (id RAW(16), amount DOUBLE, source RAW(16), destination RAW(16)) -- holds 'fast' properties for class1.
t_class2 (id RAW(16), comment VARCHAR2(200)) -- holds 'fast' properties for class2
--- etc.

RAW (16) è dove Oracle contiene GUID s

Se si desidera selezionare tutte le proprietà per un oggetto, si emette:

SELECT  i.*
FROM    (
        SELECT  id 
        FROM    t_class
        START WITH
                id = (SELECT class FROM t_declaration WHERE id = :object_id)
        CONNECT BY
                parent = PRIOR id
        ) c
JOIN    property p
ON      p.class = c.id
LEFT JOIN
        t_instance i
ON      i.id = :object_id
        AND i.class = p.class
        AND i.property = p.property

t_property contiene cose su cui normalmente non cerchi (come, descrizioni di testo ecc.)

Le proprietà veloci sono in realtà normali tabelle che hai nel database, per rendere efficienti le query. Possiedono valori solo per le istanze di una determinata classe o dei suoi discendenti. Questo per evitare join extra.

Non è necessario utilizzare tabelle rapide e limitare tutti i dati a queste quattro tabelle.

sembra che tu abbia bisogno di qualcosa che lecchi couchdb , non un RDBMS.

se hai intenzione di modificare / manipolare / eliminare gli attributi in un secondo momento, fare un vero n: m (seconda opzione) sarà quello che cercherò. (O prova a renderlo 2 tabella dove si ripete lo stesso attributo, ma la dimensione dei dati sarà alta)

Se non hai a che fare con gli attributi (solo per acquisire e mostrare i dati), puoi andare avanti e archiviarli in un campo con qualche separatore (assicurati che il separatore non si verifichi nel valore dell'attributo)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top